diff --git a/src/crypto/crypto.js b/src/crypto/crypto.js index 0c16a44d..fbd22cdd 100644 --- a/src/crypto/crypto.js +++ b/src/crypto/crypto.js @@ -45,11 +45,14 @@ function createType(data, type) { case 'oid': return new type_oid(data); case 'kdf': - return new type_kdf_params(data); + if (data) { + return new type_kdf_params(data[0], data[1]); + } + return new type_kdf_params(); case 'ecdh_symkey': return new type_ecdh_symkey(data); default: - return null; + throw new Error('Unknown type.'); } } @@ -280,12 +283,12 @@ export default { case 'ecdsa': return publicKey.elliptic.generate(curve).then(function (keyObject) { - return constructParams([keyObject.oid, keyObject.R, keyObject.r], types); + return constructParams([keyObject.oid, keyObject.Q, keyObject.d], types); }); case 'ecdh': return publicKey.elliptic.generate(curve).then(function (keyObject) { - return constructParams([keyObject.oid, keyObject.R, [keyObject.hash, keyObject.cipher], keyObject.r], types); + return constructParams([keyObject.oid, keyObject.Q, [keyObject.hash, keyObject.cipher], keyObject.d], types); }); default: @@ -294,6 +297,21 @@ export default { }, + getCloneFn: function(type) { + switch(type) { + case 'mpi': + return type_mpi.fromClone; + case 'oid': + return type_oid.fromClone; + case 'kdf': + return type_kdf_params.fromClone; + case 'ecdh_symkey': + return type_ecdh_symkey.fromClone; + default: + throw new Error('Unknown type.'); + } + }, + /** * generate random byte prefix as string for the specified algorithm * @param {module:enums.symmetric} algo Algorithm to use (see {@link http://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2}) diff --git a/src/crypto/public_key/elliptic/curves.js b/src/crypto/public_key/elliptic/curves.js index 7437ee11..8c6bd280 100644 --- a/src/crypto/public_key/elliptic/curves.js +++ b/src/crypto/public_key/elliptic/curves.js @@ -36,36 +36,47 @@ import util from '../../../util.js'; const curves = { p256: { oid: util.bin2str([0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07]), - bits: 256, + curveName: 'P-256', + hashName: 'SHA-256', hash: enums.hash.sha256, cipher: enums.symmetric.aes128, + nist: true }, p384: { oid: util.bin2str([0x2B, 0x81, 0x04, 0x00, 0x22]), - bits: 384, + curveName: 'P-384', + hashName: 'SHA-384', hash: enums.hash.sha384, cipher: enums.symmetric.aes192, + nist: true }, p521: { oid: util.bin2str([0x2B, 0x81, 0x04, 0x00, 0x23]), - bits: 521, + curveName: 'P-521', + hashName: 'SHA-512', hash: enums.hash.sha512, cipher: enums.symmetric.aes256, + nist: true }, secp256k1: { oid: util.bin2str([0x2B, 0x81, 0x04, 0x00, 0x0A]), - bits: 256, + curveName: 'SECP-256K1', + hashName: 'SHA-256', hash: enums.hash.sha256, cipher: enums.symmetric.aes128, + nist: false } }; -function Curve(name, {oid, hash, cipher}) { +function Curve(name, {oid, hash, cipher, curveName, hashName, nist}) { this.curve = new EC(name); this.name = name; this.oid = oid; this.hash = hash; this.cipher = cipher; + this.curveName= curveName; + this.hashName = hashName; + this.nist = nist; } Curve.prototype.keyFromPrivate = function (priv) { @@ -91,7 +102,10 @@ function get(oid_or_name) { return new Curve(name, { oid: curves[name].oid, hash: curves[name].hash, - cipher: curves[name].cipher + cipher: curves[name].cipher, + curveName: curves[name].curveName, + hashName: curves[name].hashName, + nist: curves[name].nist }); } } @@ -104,8 +118,8 @@ function generate(curve) { var keyPair = curve.genKeyPair(); resolve({ oid: curve.oid, - R: new BigInteger(keyPair.getPublic()), - r: new BigInteger(keyPair.getPrivate()), + Q: new BigInteger(keyPair.getPublic()), + d: new BigInteger(keyPair.getPrivate()), hash: curve.hash, cipher: curve.cipher }); diff --git a/src/crypto/public_key/elliptic/ecdh.js b/src/crypto/public_key/elliptic/ecdh.js index d1cf9f0c..d43392f2 100644 --- a/src/crypto/public_key/elliptic/ecdh.js +++ b/src/crypto/public_key/elliptic/ecdh.js @@ -73,18 +73,18 @@ function kdf(hash_algo, X, length, param) { * @param {Enums} cipher_algo Symmetric cipher to use * @param {Enums} hash_algo Hash to use * @param {Uint8Array} m Value derived from session key (RFC 6637) - * @param {BigInteger} R Recipient public key + * @param {BigInteger} Q Recipient public key * @param {String} fingerprint Recipient fingerprint * @return {{V: BigInteger, C: Uint8Array}} Returns ephemeral key and encoded session key */ -function encrypt(oid, cipher_algo, hash_algo, m, R, fingerprint) { +function encrypt(oid, cipher_algo, hash_algo, m, Q, fingerprint) { fingerprint = util.hex2Uint8Array(fingerprint); const param = buildEcdhParam(enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint); const curve = curves.get(oid); cipher_algo = enums.read(enums.symmetric, cipher_algo); const v = curve.genKeyPair(); - R = curve.keyFromPublic(R.toByteArray()); - const S = v.derive(R); + Q = curve.keyFromPublic(Q.toByteArray()); + const S = v.derive(Q); const Z = kdf(hash_algo, S, cipher[cipher_algo].keySize, param); const C = aes_kw.wrap(Z, m.toBytes()); return { @@ -101,18 +101,18 @@ function encrypt(oid, cipher_algo, hash_algo, m, R, fingerprint) { * @param {Enums} hash_algo Hash algorithm to use * @param {BigInteger} V Public part of ephemeral key * @param {Uint8Array} C Encrypted and wrapped value derived from session key - * @param {BigInteger} r Recipient private key + * @param {BigInteger} d Recipient private key * @param {String} fingerprint Recipient fingerprint * @return {Uint8Array} Value derived from session */ -function decrypt(oid, cipher_algo, hash_algo, V, C, r, fingerprint) { +function decrypt(oid, cipher_algo, hash_algo, V, C, d, fingerprint) { fingerprint = util.hex2Uint8Array(fingerprint); const param = buildEcdhParam(enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint); const curve = curves.get(oid); cipher_algo = enums.read(enums.symmetric, cipher_algo); V = curve.keyFromPublic(V.toByteArray()); - r = curve.keyFromPrivate(r.toByteArray()); - const S = r.derive(V); + d = curve.keyFromPrivate(d.toByteArray()); + const S = d.derive(V); const Z = kdf(hash_algo, S, cipher[cipher_algo].keySize, param); return new BigInteger(aes_kw.unwrap(Z, C)); } diff --git a/src/crypto/public_key/elliptic/ecdsa.js b/src/crypto/public_key/elliptic/ecdsa.js index b453efc8..37cba51c 100644 --- a/src/crypto/public_key/elliptic/ecdsa.js +++ b/src/crypto/public_key/elliptic/ecdsa.js @@ -31,14 +31,15 @@ import BigInteger from '../jsbn.js'; /** * Sign a message using the provided key * @param {String} oid Elliptic curve for the key + * @param {BigInteger} Q Public key used to sign * @param {enums.hash} hash_algo Hash algorithm used to sign * @param {Uint8Array} m Message to sign - * @param {BigInteger} w Private key used to sign +* @param {BigInteger} d Private key used to sign * @return {{r: BigInteger, s: BigInteger}} Signature of the message */ -function sign(oid, hash_algo, m, w) { +function sign(oid, hash_algo, m, d) { const curve = curves.get(oid); - const key = curve.keyFromPrivate(w.toByteArray()); + const key = curve.keyFromPrivate(d.toByteArray()); const signature = key.sign(m, hash_algo); return { r: new BigInteger(signature.r), @@ -52,11 +53,11 @@ function sign(oid, hash_algo, m, w) { * @param {enums.hash} hash_algo Hash algorithm used in the signature * @param {{r: BigInteger, s: BigInteger}} signature Signature to verify * @param {Uint8Array} m Message to verify - * @param {BigInteger} gw Public key used to verify the message + * @param {BigInteger} Q Public key used to verify the message */ -function verify(oid, hash_algo, signature, m, gw) { +function verify(oid, hash_algo, signature, m, Q) { const curve = curves.get(oid); - const key = curve.keyFromPublic(gw.toByteArray()); + const key = curve.keyFromPublic(Q.toByteArray()); return key.verify(m, {r: signature.r.toByteArray(), s: signature.s.toByteArray()}, hash_algo); } diff --git a/src/crypto/signature.js b/src/crypto/signature.js index 3638ad32..18ffd225 100644 --- a/src/crypto/signature.js +++ b/src/crypto/signature.js @@ -63,8 +63,8 @@ export default { 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); + const Q = publickey_MPIs[1].toBigInteger(); + return ecdsa.verify(curve.oid, hash_algo, {r: r, s: s}, m, Q); default: throw new Error('Invalid signature algorithm.'); } @@ -74,10 +74,7 @@ export default { * Create a signature on data using the specified algorithm * @param {module:enums.hash} hash_algo hash Algorithm to use (See {@link http://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) * @param {module:enums.publicKey} algo Asymmetric cipher algorithm to use (See {@link http://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1}) - * @param {Array} publicMPIs Public key multiprecision integers - * of the private key - * @param {Array} secretMPIs Private key multiprecision - * integers which is used to sign the data + * @param {Array} publicMPIs Public followed by Private key multiprecision algorithm-specific parameters * @param {Uint8Array} data Data to be signed * @return {Array} */ @@ -86,6 +83,7 @@ export default { data = util.Uint8Array2str(data); var m; + var d; switch (algo) { case 1: @@ -95,7 +93,7 @@ export default { case 3: // RSA Sign-Only [HAC] var rsa = new publicKey.rsa(); - var d = keyIntegers[2].toBigInteger(); + d = keyIntegers[2].toBigInteger(); var n = keyIntegers[0].toBigInteger(); m = pkcs1.emsa.encode(hash_algo, data, keyIntegers[0].byteLength()); @@ -111,7 +109,6 @@ export default { var x = keyIntegers[4].toBigInteger(); m = data; var result = dsa.sign(hash_algo, m, g, p, q, x); - return util.str2Uint8Array(result[0].toString() + result[1].toString()); case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC] @@ -119,11 +116,11 @@ export default { case 19: // ECDSA - const ecdsa = publicKey.elliptic.ecdsa; - const curve = keyIntegers[0]; - const w = keyIntegers[2].toBigInteger(); + var ecdsa = publicKey.elliptic.ecdsa; + var curve = keyIntegers[0]; + d = keyIntegers[2].toBigInteger(); m = data; - const signature = ecdsa.sign(curve.oid, hash_algo, m, w); + const signature = ecdsa.sign(curve.oid, hash_algo, m, d); return util.str2Uint8Array(signature.r.toMPI() + signature.s.toMPI()); default: