diff --git a/src/keys/ed25519-class.js b/src/keys/ed25519-class.js index 1cba96f7..7136cd7f 100644 --- a/src/keys/ed25519-class.js +++ b/src/keys/ed25519-class.js @@ -89,9 +89,17 @@ class Ed25519PrivateKey { } function unmarshalEd25519PrivateKey (bytes) { - bytes = ensureKey(bytes, crypto.privateKeyLength + crypto.publicKeyLength) + // Try the old, redundant public key version + if (bytes.length > crypto.privateKeyLength) { + bytes = ensureKey(bytes, crypto.privateKeyLength + crypto.publicKeyLength) + const privateKeyBytes = bytes.slice(0, crypto.privateKeyLength) + const publicKeyBytes = bytes.slice(crypto.privateKeyLength, bytes.length) + return new Ed25519PrivateKey(privateKeyBytes, publicKeyBytes) + } + + bytes = ensureKey(bytes, crypto.privateKeyLength) const privateKeyBytes = bytes.slice(0, crypto.privateKeyLength) - const publicKeyBytes = bytes.slice(crypto.privateKeyLength, bytes.length) + const publicKeyBytes = bytes.slice(crypto.publicKeyLength) return new Ed25519PrivateKey(privateKeyBytes, publicKeyBytes) } @@ -111,11 +119,9 @@ async function generateKeyPairFromSeed (seed) { } function ensureKey (key, length) { - if (Buffer.isBuffer(key)) { - key = new Uint8Array(key) - } - if (!(key instanceof Uint8Array) || key.length !== length) { - throw errcode(new Error('Key must be a Uint8Array or Buffer of length ' + length), 'ERR_INVALID_KEY_TYPE') + key = Uint8Array.from(key || []) + if (key.length !== length) { + throw errcode(new Error(`Key must be a Uint8Array or Buffer of length ${length}, got ${key.length}`), 'ERR_INVALID_KEY_TYPE') } return key } diff --git a/src/keys/secp256k1-class.js b/src/keys/secp256k1-class.js index e8c53902..daa54878 100644 --- a/src/keys/secp256k1-class.js +++ b/src/keys/secp256k1-class.js @@ -78,8 +78,7 @@ module.exports = (keysProtobuf, randomBytes, crypto) => { * The public key is a protobuf encoding containing a type and the DER encoding * of the PKCS SubjectPublicKeyInfo. * - * @param {function(Error, id)} callback - * @returns {undefined} + * @returns {Promise} */ async id () { const hash = await this.public.hash() diff --git a/test/aes/aes.spec.js b/test/aes/aes.spec.js index 45b4b11f..9a993668 100644 --- a/test/aes/aes.spec.js +++ b/test/aes/aes.spec.js @@ -98,7 +98,7 @@ describe('AES-CTR', () => { // @ts-check /** - * @type {function(Cipher): void} + * @type {function(Cipher): Promise} */ async function encryptAndDecrypt (cipher) { const data = Buffer.alloc(100) diff --git a/test/fixtures/go-key-ed25519.js b/test/fixtures/go-key-ed25519.js index 2fc78302..c72d0da5 100644 --- a/test/fixtures/go-key-ed25519.js +++ b/test/fixtures/go-key-ed25519.js @@ -2,28 +2,42 @@ const { Buffer } = require('buffer') module.exports = { - // These were generated in a gore (https://github.com/motemen/gore) repl session: + // Generation code from https://github.com/libp2p/js-libp2p-crypto/issues/175#issuecomment-634467463 // - // :import github.com/libp2p/go-libp2p-crypto - // :import crypto/rand - // priv, pub, err := crypto.GenerateEd25519Key(rand.Reader) - // pubkeyBytes, err := pub.Bytes() - // privkeyBytes, err := priv.Bytes() - // data := []byte("hello! and welcome to some awesome crypto primitives") - // sig, err := priv.Sign(data) + // package main // - // :import io/ioutil - // ioutil.WriteFile("/tmp/pubkey_go.bin", pubkeyBytes, 0644) - // // etc.. - // - // Then loaded into a node repl and dumped to arrays with: + // import ( + // "crypto/rand" + // "fmt" + // "strings" + + // "github.com/libp2p/go-libp2p-core/crypto" + // ) + + // func main() { + // priv, pub, _ := crypto.GenerateEd25519Key(rand.Reader) + // pubkeyBytes, _ := pub.Bytes() + // privkeyBytes, _ := priv.Bytes() + // data := []byte("hello! and welcome to some awesome crypto primitives") + // sig, _ := priv.Sign(data) + // fmt.Println("{\n publicKey: Buffer.from(", strings.Replace(fmt.Sprint(pubkeyBytes), " ", ",", -1), "),") + // fmt.Println(" privateKey: Buffer.from(", strings.Replace(fmt.Sprint(privkeyBytes), " ", ",", -1), "),") + // fmt.Println(" data: Buffer.from(", strings.Replace(fmt.Sprint(data), " ", ",", -1), "),") + // fmt.Println(" signature: Buffer.from(", strings.Replace(fmt.Sprint(sig), " ", ",", -1), ")\n}") + // } // - // var pubkey = Array.from(fs.readFileSync('/tmp/pubkey_go.bin')) - // console.log(JSON.stringify(pubkey)) - verify: { + + // The legacy key unnecessarily appends the publickey. (It's already included) See https://github.com/libp2p/js-libp2p-crypto/issues/175 + redundantPubKey: { privateKey: Buffer.from([8, 1, 18, 96, 201, 208, 1, 110, 176, 16, 230, 37, 66, 184, 149, 252, 78, 56, 206, 136, 2, 38, 118, 152, 226, 197, 117, 200, 54, 189, 156, 218, 184, 7, 118, 57, 233, 49, 221, 97, 164, 158, 241, 129, 73, 166, 225, 255, 193, 118, 22, 84, 55, 15, 249, 168, 225, 180, 198, 191, 14, 75, 187, 243, 150, 91, 232, 37, 233, 49, 221, 97, 164, 158, 241, 129, 73, 166, 225, 255, 193, 118, 22, 84, 55, 15, 249, 168, 225, 180, 198, 191, 14, 75, 187, 243, 150, 91, 232, 37]), publicKey: Buffer.from([8, 1, 18, 32, 233, 49, 221, 97, 164, 158, 241, 129, 73, 166, 225, 255, 193, 118, 22, 84, 55, 15, 249, 168, 225, 180, 198, 191, 14, 75, 187, 243, 150, 91, 232, 37]), data: Buffer.from([104, 101, 108, 108, 111, 33, 32, 97, 110, 100, 32, 119, 101, 108, 99, 111, 109, 101, 32, 116, 111, 32, 115, 111, 109, 101, 32, 97, 119, 101, 115, 111, 109, 101, 32, 99, 114, 121, 112, 116, 111, 32, 112, 114, 105, 109, 105, 116, 105, 118, 101, 115]), signature: Buffer.from([7, 230, 175, 164, 228, 58, 78, 208, 62, 243, 73, 142, 83, 195, 176, 217, 166, 62, 41, 165, 168, 164, 75, 179, 163, 86, 102, 32, 18, 84, 150, 237, 39, 207, 213, 20, 134, 237, 50, 41, 176, 183, 229, 133, 38, 255, 42, 228, 68, 186, 100, 14, 175, 156, 243, 118, 125, 125, 120, 212, 124, 103, 252, 12]) + }, + verify: { + publicKey: Buffer.from([8, 1, 18, 32, 163, 176, 195, 47, 254, 208, 49, 5, 192, 102, 32, 63, 58, 202, 171, 153, 146, 164, 25, 212, 25, 91, 146, 26, 117, 165, 148, 6, 207, 90, 217, 126]), + privateKey: Buffer.from([8, 1, 18, 64, 232, 56, 175, 20, 240, 160, 19, 47, 92, 88, 115, 221, 164, 13, 36, 162, 158, 136, 247, 31, 29, 231, 76, 143, 12, 91, 193, 4, 88, 33, 67, 23, 163, 176, 195, 47, 254, 208, 49, 5, 192, 102, 32, 63, 58, 202, 171, 153, 146, 164, 25, 212, 25, 91, 146, 26, 117, 165, 148, 6, 207, 90, 217, 126]), + data: Buffer.from([104, 101, 108, 108, 111, 33, 32, 97, 110, 100, 32, 119, 101, 108, 99, 111, 109, 101, 32, 116, 111, 32, 115, 111, 109, 101, 32, 97, 119, 101, 115, 111, 109, 101, 32, 99, 114, 121, 112, 116, 111, 32, 112, 114, 105, 109, 105, 116, 105, 118, 101, 115]), + signature: Buffer.from([160, 125, 30, 62, 213, 189, 239, 92, 87, 76, 205, 169, 251, 149, 187, 57, 96, 85, 175, 213, 22, 132, 229, 60, 196, 18, 117, 194, 12, 174, 135, 31, 39, 168, 174, 103, 78, 55, 37, 222, 37, 172, 222, 239, 153, 63, 197, 152, 67, 167, 191, 215, 161, 212, 216, 163, 81, 77, 45, 228, 151, 79, 101, 1]) } } diff --git a/test/keys/ed25519.spec.js b/test/keys/ed25519.spec.js index bfedbec4..8a7d77cf 100644 --- a/test/keys/ed25519.spec.js +++ b/test/keys/ed25519.spec.js @@ -131,25 +131,28 @@ describe('ed25519', function () { describe('go interop', () => { // @ts-check - /** - * @type {PrivateKey} - */ - let privateKey - - before(async () => { - const key = await crypto.keys.unmarshalPrivateKey(fixtures.verify.privateKey) - privateKey = key - }) - it('verifies with data from go', async () => { const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey) const ok = await key.verify(fixtures.verify.data, fixtures.verify.signature) expect(ok).to.eql(true) }) + it('verifies with data from go with redundant public key', async () => { + const key = crypto.keys.unmarshalPublicKey(fixtures.redundantPubKey.publicKey) + const ok = await key.verify(fixtures.redundantPubKey.data, fixtures.redundantPubKey.signature) + expect(ok).to.eql(true) + }) + it('generates the same signature as go', async () => { - const sig = await privateKey.sign(fixtures.verify.data) + const key = await crypto.keys.unmarshalPrivateKey(fixtures.verify.privateKey) + const sig = await key.sign(fixtures.verify.data) expect(sig).to.eql(fixtures.verify.signature) }) + + it('generates the same signature as go with redundant public key', async () => { + const key = await crypto.keys.unmarshalPrivateKey(fixtures.redundantPubKey.privateKey) + const sig = await key.sign(fixtures.redundantPubKey.data) + expect(sig).to.eql(fixtures.redundantPubKey.signature) + }) }) }) diff --git a/test/keys/secp256k1.spec.js b/test/keys/secp256k1.spec.js index da245ab1..e1e3c979 100644 --- a/test/keys/secp256k1.spec.js +++ b/test/keys/secp256k1.spec.js @@ -31,7 +31,7 @@ describe('secp256k1 keys', () => { }) it('optionally accepts a `bits` argument when generating a key', async () => { - const _key = await secp256k1.generateKeyPair(256) + const _key = await secp256k1.generateKeyPair() expect(_key).to.be.an.instanceof(secp256k1.Secp256k1PrivateKey) }) @@ -71,7 +71,7 @@ describe('secp256k1 keys', () => { }) it('not equals other key', async () => { - const key2 = await secp256k1.generateKeyPair(256) + const key2 = await secp256k1.generateKeyPair() expect(key.equals(key2)).to.eql(false) expect(key2.equals(key)).to.eql(false) expect(key.public.equals(key2.public)).to.eql(false) diff --git a/test/util/index.js b/test/util/index.js index 7293d4f7..209a54c3 100644 --- a/test/util/index.js +++ b/test/util/index.js @@ -6,7 +6,7 @@ const expect = chai.expect // @ts-check /** - * @type {function(any, string): void} + * @type {function(any, string): Promise} */ const expectErrCode = async (p, code) => { try {