From 673151ec877631cb07a35d9091707224e2169ebd Mon Sep 17 00:00:00 2001 From: Ismael Bejarano Date: Fri, 12 Aug 2016 00:24:49 -0300 Subject: [PATCH] Read and write ECDSA packets --- src/crypto/crypto.js | 10 ++++++++++ src/crypto/signature.js | 19 +++++++++++++++++++ src/enums.js | 3 ++- src/key.js | 3 ++- src/packet/public_key.js | 9 +++++++-- src/packet/signature.js | 4 ++-- 6 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/crypto/crypto.js b/src/crypto/crypto.js index f6e17403..d877ea63 100644 --- a/src/crypto/crypto.js +++ b/src/crypto/crypto.js @@ -144,6 +144,10 @@ export default { // Algorithm-Specific Fields for DSA secret keys: // - MPI of DSA secret exponent x. return 1; + case 'ecdsa': + // Algorithm-Specific Fields for ECDSA secret keys: + // - MPI of an integer representing the secret key. + return 1; default: throw new Error('Unknown algorithm'); } @@ -175,6 +179,12 @@ export default { case 'dsa': return 4; + // Algorithm-Specific Fields for ECDSA public keys: + // - OID of curve; + // - MPI of EC point representing public key. + case 'ecdsa': + return 2; + default: throw new Error('Unknown algorithm.'); } diff --git a/src/crypto/signature.js b/src/crypto/signature.js index 6ab0ce9f..3638ad32 100644 --- a/src/crypto/signature.js +++ b/src/crypto/signature.js @@ -56,6 +56,15 @@ export default { m = data; var dopublic = dsa.verify(hash_algo, s1, s2, m, p, q, g, y); return dopublic.compareTo(s1) === 0; + case 19: + // ECDSA + const ecdsa = publicKey.elliptic.ecdsa; + const curve = publickey_MPIs[0]; + const r = msg_MPIs[0].toBigInteger(); + const s = msg_MPIs[1].toBigInteger(); + m = data; + const gw = publickey_MPIs[1].toBigInteger(); + return ecdsa.verify(curve.oid, hash_algo, {r: r, s: s}, m, gw); default: throw new Error('Invalid signature algorithm.'); } @@ -107,6 +116,16 @@ export default { case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC] throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.'); + + case 19: + // ECDSA + const ecdsa = publicKey.elliptic.ecdsa; + const curve = keyIntegers[0]; + const w = keyIntegers[2].toBigInteger(); + m = data; + const signature = ecdsa.sign(curve.oid, hash_algo, m, w); + return util.str2Uint8Array(signature.r.toMPI() + signature.s.toMPI()); + default: throw new Error('Invalid signature algorithm.'); } diff --git a/src/enums.js b/src/enums.js index 861f2f01..bee7b985 100644 --- a/src/enums.js +++ b/src/enums.js @@ -26,7 +26,8 @@ export default { rsa_encrypt: 2, rsa_sign: 3, elgamal: 16, - dsa: 17 + dsa: 17, + ecdsa: 19 }, /** {@link http://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2} diff --git a/src/key.js b/src/key.js index e93ffb30..75fcf772 100644 --- a/src/key.js +++ b/src/key.js @@ -339,7 +339,8 @@ function isValidEncryptionKeyPacket(keyPacket, signature) { function isValidSigningKeyPacket(keyPacket, signature) { return (keyPacket.algorithm === enums.read(enums.publicKey, enums.publicKey.dsa) || keyPacket.algorithm === enums.read(enums.publicKey, enums.publicKey.rsa_sign) || - keyPacket.algorithm === enums.read(enums.publicKey, enums.publicKey.rsa_encrypt_sign)) && + keyPacket.algorithm === enums.read(enums.publicKey, enums.publicKey.rsa_encrypt_sign) || + keyPacket.algorithm === enums.read(enums.publicKey, enums.publicKey.ecdsa)) && (!signature.keyFlags || (signature.keyFlags[0] & enums.keyFlags.sign_data) !== 0); } diff --git a/src/packet/public_key.js b/src/packet/public_key.js index 6542998b..9a083350 100644 --- a/src/packet/public_key.js +++ b/src/packet/public_key.js @@ -26,6 +26,7 @@ * @requires enums * @requires type/keyid * @requires type/mpi + * @requires type/oid * @requires util * @module packet/public_key */ @@ -35,6 +36,7 @@ import util from '../util.js'; import type_mpi from '../type/mpi.js'; import type_keyid from '../type/keyid.js'; +import type_oid from '../type/oid.js'; import enums from '../enums.js'; import crypto from '../crypto'; @@ -100,8 +102,11 @@ PublicKey.prototype.read = function (bytes) { var p = 0; for (var i = 0; i < mpicount && p < bmpi.length; i++) { - - this.mpi[i] = new type_mpi(); + if (this.algorithm === 'ecdsa' && i === 0) { + this.mpi[i] = new type_oid(); + } else { + this.mpi[i] = new type_mpi(); + } p += this.mpi[i].read(bmpi.subarray(p, bmpi.length)); diff --git a/src/packet/signature.js b/src/packet/signature.js index 25e545c9..b5f72d69 100644 --- a/src/packet/signature.js +++ b/src/packet/signature.js @@ -629,10 +629,10 @@ Signature.prototype.verify = function (key, data) { if (publicKeyAlgorithm > 0 && publicKeyAlgorithm < 4) { mpicount = 1; } - // Algorithm-Specific Fields for DSA signatures: + // Algorithm-Specific Fields for DSA and ECDSA signatures: // - MPI of DSA value r. // - MPI of DSA value s. - else if (publicKeyAlgorithm === 17) { + else if (publicKeyAlgorithm === 17 || publicKeyAlgorithm === 19) { mpicount = 2; }