diff --git a/src/crypto/crypto.js b/src/crypto/crypto.js index 53085d08..54fc6ceb 100644 --- a/src/crypto/crypto.js +++ b/src/crypto/crypto.js @@ -32,7 +32,7 @@ */ import BN from 'bn.js'; -import { RSA_RAW, BigNumber, Modulus } from 'asmcrypto.js'; +import { RSA_RAW } from 'asmcrypto.js'; import publicKey from './public_key'; import cipher from './cipher'; import random from './random'; @@ -62,15 +62,15 @@ export default { * @return {Array} encrypted session key parameters */ publicKeyEncrypt: async function(algo, publicParams, data, fingerprint) { + // TODO change algo to return enums const types = this.getEncSessionKeyParamTypes(algo); return (async function() { - let m; switch (algo) { case 'rsa_encrypt': case 'rsa_encrypt_sign': { const n = publicParams[0].toUint8Array(); const e = publicParams[1].toUint8Array(); - m = data.toUint8Array(); + const m = data.toUint8Array(); return constructParams(types, [new BN(RSA_RAW.encrypt(m, [n, e]))]); } case 'elgamal': { @@ -78,17 +78,15 @@ export default { const p = publicParams[0].toBigInteger(); const g = publicParams[1].toBigInteger(); const y = publicParams[2].toBigInteger(); - m = data.toBigInteger(); + const m = data.toBigInteger(); return constructParams(types, elgamal.encrypt(m, g, p, y)); } case 'ecdh': { - const { ecdh } = publicKey.elliptic; - const curve = publicParams[0]; + const oid = publicParams[0]; const kdf_params = publicParams[2]; - const R = publicParams[1].toBigInteger(); - const res = await ecdh.encrypt( - curve.oid, kdf_params.cipher, kdf_params.hash, data, R, fingerprint - ); + const Q = publicParams[1].toUint8Array(); + const res = await publicKey.elliptic.ecdh.encrypt( + oid, kdf_params.cipher, kdf_params.hash, data, Q, fingerprint); return constructParams(types, [res.V, res.C]); } default: @@ -106,9 +104,8 @@ export default { * @param {String} fingerprint Recipient fingerprint * @return {module:type/mpi} returns a big integer containing the decrypted data; otherwise null */ - publicKeyDecrypt: async function(algo, keyIntegers, dataIntegers, fingerprint) { - let p; + // TODO change algo to return enums return new type_mpi(await (async function() { switch (algo) { case 'rsa_encrypt_sign': @@ -120,13 +117,9 @@ export default { const p = keyIntegers[3].toUint8Array(); const q = keyIntegers[4].toUint8Array(); const u = keyIntegers[5].toUint8Array(); // q^-1 mod p - const dd = BigNumber.fromArrayBuffer(d); - const dp = new Modulus( - BigNumber.fromArrayBuffer(p).subtract(BigNumber.ONE) - ).reduce(dd).toBytes(); // d mod (p-1) - const dq = new Modulus( - BigNumber.fromArrayBuffer(q).subtract(BigNumber.ONE) - ).reduce(dd).toBytes(); // d mod (q-1) + const dd = new BN(d); + const dp = dd.mod(new BN(p).subn(1)).toArrayLike(Uint8Array); // d mod (p-1) + const dq = dd.mod(new BN(q).subn(1)).toArrayLike(Uint8Array); // d mod (q-1) return new BN(RSA_RAW.decrypt(c, [n, e, d, q, p, dq, dp, u]).slice(1)); // FIXME remove slice } case 'elgamal': { @@ -134,17 +127,17 @@ export default { const x = keyIntegers[3].toBigInteger(); const c1 = dataIntegers[0].toBigInteger(); const c2 = dataIntegers[1].toBigInteger(); - p = keyIntegers[0].toBigInteger(); + const p = keyIntegers[0].toBigInteger(); return elgamal.decrypt(c1, c2, p, x); } case 'ecdh': { - const { ecdh } = publicKey.elliptic; - const curve = keyIntegers[0]; + const oid = keyIntegers[0]; const kdf_params = keyIntegers[2]; - const V = dataIntegers[0].toBigInteger(); + const V = dataIntegers[0].toUint8Array(); const C = dataIntegers[1].data; - const r = keyIntegers[3].toBigInteger(); - return ecdh.decrypt(curve.oid, kdf_params.cipher, kdf_params.hash, V, C, r, fingerprint); + const d = keyIntegers[3].toUint8Array(); + return publicKey.elliptic.ecdh.decrypt( + oid, kdf_params.cipher, kdf_params.hash, V, C, d, fingerprint); } default: return null; @@ -259,16 +252,17 @@ export default { }, /** Generate algorithm-specific key parameters - * @param {String} algo The public key algorithm - * @return {Array} The array of parameters + * @param {String} algo The public key algorithm + * @param {Integer} bits Bit length for RSA keys + * @param {module:type/oid} oid Object identifier for ECC keys + * @return {Array} The array of parameters */ - generateParams: function(algo, bits, curve) { + generateParams: function(algo, bits, oid) { const types = this.getPubKeyParamTypes(algo).concat(this.getPrivKeyParamTypes(algo)); switch (algo) { case 'rsa_encrypt': case 'rsa_encrypt_sign': case 'rsa_sign': { - //remember "publicKey" refers to the crypto/public_key dir const rsa = new publicKey.rsa(); return rsa.generate(bits, "10001").then(function(keyObject) { return constructParams( @@ -278,11 +272,11 @@ export default { } case 'ecdsa': case 'eddsa': - return publicKey.elliptic.generate(curve).then(function (keyObject) { + return publicKey.elliptic.generate(oid).then(function (keyObject) { return constructParams(types, [keyObject.oid, keyObject.Q, keyObject.d]); }); case 'ecdh': - return publicKey.elliptic.generate(curve).then(function (keyObject) { + return publicKey.elliptic.generate(oid).then(function (keyObject) { return constructParams(types, [keyObject.oid, keyObject.Q, [keyObject.hash, keyObject.cipher], keyObject.d]); }); default: diff --git a/src/crypto/public_key/elliptic/curves.js b/src/crypto/public_key/elliptic/curves.js index dd9cbcfe..15a3ea8e 100644 --- a/src/crypto/public_key/elliptic/curves.js +++ b/src/crypto/public_key/elliptic/curves.js @@ -26,7 +26,7 @@ */ import { ec as EC, eddsa as EdDSA } from 'elliptic'; -import { KeyPair } from './key'; +import KeyPair from './key'; import BigInteger from '../jsbn'; import random from '../../random'; import enums from '../../../enums'; @@ -126,7 +126,7 @@ function Curve(name, params) { throw new Error('Unknown elliptic key type;'); } this.name = name; - this.oid = curves[name].oid; + this.oid = new OID(curves[name].oid); this.hash = params.hash; this.cipher = params.cipher; this.node = params.node && curves[name].node; @@ -202,14 +202,9 @@ function getPreferredHashAlgo(oid) { return curves[enums.write(enums.curve, oid.toHex())].hash; } +// TODO convert to export default {...} module.exports = { - Curve, - curves, - webCurves, - nodeCurves, - getPreferredHashAlgo, - generate, - get + Curve, curves, webCurves, nodeCurves, get, generate, getPreferredHashAlgo }; diff --git a/src/crypto/public_key/elliptic/ecdh.js b/src/crypto/public_key/elliptic/ecdh.js index 54f45928..2bcaeb1b 100644 --- a/src/crypto/public_key/elliptic/ecdh.js +++ b/src/crypto/public_key/elliptic/ecdh.js @@ -19,10 +19,9 @@ /** * @requires crypto/public_key/elliptic/curves - * @requires crypto/public_key/jsbn + * @requires crypto/aes_kw * @requires crypto/cipher * @requires crypto/hash - * @requires crypto/aes_kw * @requires type/oid * @requires type/kdf_params * @requires enums @@ -30,20 +29,18 @@ * @module crypto/public_key/elliptic/ecdh */ +import BN from 'bn.js'; import curves from './curves'; -import BigInteger from '../jsbn'; +import aes_kw from '../../aes_kw'; import cipher from '../../cipher'; import hash from '../../hash'; -import aes_kw from '../../aes_kw'; import type_kdf_params from '../../../type/kdf_params'; import type_oid from '../../../type/oid'; import enums from '../../../enums'; import util from '../../../util'; - // Build Param for ECDH algorithm (RFC 6637) function buildEcdhParam(public_algo, oid, cipher_algo, hash_algo, fingerprint) { - oid = new type_oid(oid); const kdf_params = new type_kdf_params([hash_algo, cipher_algo]); return util.concatUint8Array([ oid.write(), @@ -67,26 +64,26 @@ function kdf(hash_algo, X, length, param) { /** * Encrypt and wrap a session key * - * @param {String} oid OID of the curve to use - * @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} Q Recipient public key - * @param {String} fingerprint Recipient fingerprint - * @return {{V: BigInteger, C: Uint8Array}} Returns ephemeral key and encoded session key + * @param {module:type/oid} oid Elliptic curve object identifier + * @param {Enums} cipher_algo Symmetric cipher to use + * @param {Enums} hash_algo Hash algorithm to use + * @param {Uint8Array} m Value derived from session key (RFC 6637) + * @param {Uint8Array} Q Recipient public key + * @param {String} fingerprint Recipient fingerprint + * @return {{V: BN, C: BN}} Returns ephemeral key and encoded session key */ async 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); + const param = buildEcdhParam(enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint); cipher_algo = enums.read(enums.symmetric, cipher_algo); const v = await curve.genKeyPair(); - Q = curve.keyFromPublic(Q.toByteArray()); + Q = curve.keyFromPublic(Q); 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 { - V: new BigInteger(util.hexidump(v.getPublic()), 16), + V: new BN(v.getPublic()), C: C }; } @@ -94,30 +91,25 @@ async function encrypt(oid, cipher_algo, hash_algo, m, Q, fingerprint) { /** * Decrypt and unwrap the value derived from session key * - * @param {String} oid Curve OID - * @param {Enums} cipher_algo Symmetric cipher to use - * @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} d Recipient private key - * @param {String} fingerprint Recipient fingerprint - * @return {Uint8Array} Value derived from session + * @param {module:type/oid} oid Elliptic curve object identifier + * @param {Enums} cipher_algo Symmetric cipher to use + * @param {Enums} hash_algo Hash algorithm to use + * @param {BN} V Public part of ephemeral key + * @param {Uint8Array} C Encrypted and wrapped value derived from session key + * @param {Uint8Array} d Recipient private key + * @param {String} fingerprint Recipient fingerprint + * @return {Uint8Array} Value derived from session */ async 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); + const param = buildEcdhParam(enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint); cipher_algo = enums.read(enums.symmetric, cipher_algo); - V = curve.keyFromPublic(V.toByteArray()); - d = curve.keyFromPrivate(d.toByteArray()); + V = curve.keyFromPublic(V); + d = curve.keyFromPrivate(d); const S = d.derive(V); const Z = kdf(hash_algo, S, cipher[cipher_algo].keySize, param); - return new BigInteger(util.hexidump(aes_kw.unwrap(Z, C)), 16); + return new BN(aes_kw.unwrap(Z, C)); } -module.exports = { - buildEcdhParam: buildEcdhParam, - kdf: kdf, - encrypt: encrypt, - decrypt: decrypt -}; +export default { encrypt, decrypt }; diff --git a/src/crypto/public_key/elliptic/ecdsa.js b/src/crypto/public_key/elliptic/ecdsa.js index 6bc0d703..c94ebf45 100644 --- a/src/crypto/public_key/elliptic/ecdsa.js +++ b/src/crypto/public_key/elliptic/ecdsa.js @@ -20,7 +20,6 @@ /** * @requires util * @requires crypto/hash - * @requires crypto/public_key/jsbn * @requires crypto/public_key/elliptic/curves * @module crypto/public_key/elliptic/ecdsa */ @@ -28,44 +27,34 @@ import util from '../../../util'; import hash from '../../hash'; import curves from './curves'; -import BigInteger from '../jsbn'; /** * Sign a message using the provided key - * @param {String} oid Elliptic curve for the key - * @param {enums.hash} hash_algo Hash algorithm used to sign - * @param {Uint8Array} m Message to sign - * @param {BigInteger} d Private key used to sign - * @return {{r: BigInteger, s: BigInteger}} Signature of the message + * @param {module:type/oid} oid Elliptic curve object identifier + * @param {enums.hash} hash_algo Hash algorithm used to sign + * @param {Uint8Array} m Message to sign + * @param {Uint8Array} d Private key used to sign the message + * @return {{r: BN, s: BN}} Signature of the message */ async function sign(oid, hash_algo, m, d) { const curve = curves.get(oid); - const key = curve.keyFromPrivate(d.toByteArray()); - const signature = await key.sign(m, hash_algo); - return { - r: new BigInteger(util.hexidump(signature.r.toArray()), 16), - s: new BigInteger(util.hexidump(signature.s.toArray()), 16) - }; + const key = curve.keyFromPrivate(d); + return key.sign(m, hash_algo); } /** * Verifies if a signature is valid for a message - * @param {String} oid Elliptic curve for the key - * @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} Q Public key used to verify the message + * @param {module:type/oid} oid Elliptic curve object identifier + * @param {enums.hash} hash_algo Hash algorithm used in the signature + * @param {{r: BN, s: BN}} signature Signature to verify + * @param {Uint8Array} m Message to verify + * @param {Uint8Array} Q Public key used to verify the message * @return {Boolean} */ async function verify(oid, hash_algo, signature, m, Q) { const curve = curves.get(oid); - const key = curve.keyFromPublic(Q.toByteArray()); - return key.verify( - m, { r: signature.r.toByteArray(), s: signature.s.toByteArray() }, hash_algo - ); + const key = curve.keyFromPublic(Q); + return key.verify(m, signature, hash_algo); } -module.exports = { - sign: sign, - verify: verify -}; +export default { sign, verify }; diff --git a/src/crypto/public_key/elliptic/eddsa.js b/src/crypto/public_key/elliptic/eddsa.js index 6145b7cd..9282e327 100644 --- a/src/crypto/public_key/elliptic/eddsa.js +++ b/src/crypto/public_key/elliptic/eddsa.js @@ -30,45 +30,37 @@ import curves from './curves'; /** * Sign a message using the provided key - * @param {String} oid Elliptic curve for the key - * @param {enums.hash} hash_algo Hash algorithm used to sign - * @param {Uint8Array} m Message to sign - * @param {BigInteger} d Private key used to sign - * @return {{R: BN, S: BN}} Signature of the message + * @param {module:type/oid} oid Elliptic curve object identifier + * @param {enums.hash} hash_algo Hash algorithm used to sign + * @param {Uint8Array} m Message to sign + * @param {BN} d Private key used to sign + * @return {{R: Array, S: Array}} Signature of the message */ async function sign(oid, hash_algo, m, d) { const curve = curves.get(oid); - const key = curve.keyFromSecret(d.toByteArray()); + const key = curve.keyFromSecret(d.toArray('be', 32)); const signature = await key.sign(m, hash_algo); // EdDSA signature params are returned in little-endian format - return { - R: new BN(Array.from(signature.Rencoded()).reverse()), - S: new BN(Array.from(signature.Sencoded()).reverse()) - }; + return { R: signature.Rencoded(), S: signature.Sencoded() }; } /** * Verifies if a signature is valid for a message - * @param {String} oid Elliptic curve for the key - * @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} Q Public key used to verify the message + * @param {module:type/oid} oid Elliptic curve object identifier + * @param {enums.hash} hash_algo Hash algorithm used in the signature + * @param {{R: BN, S: BN}} signature Signature to verify the message + * @param {Uint8Array} m Message to verify + * @param {BN} Q Public key used to verify the message * @return {Boolean} */ async function verify(oid, hash_algo, signature, m, Q) { const curve = curves.get(oid); - const key = curve.keyFromPublic(Q.toByteArray()); + const key = curve.keyFromPublic(Q.toArray('be', 33)); // EdDSA signature params are expected in little-endian format - const R = Array.from(signature.R.toByteArray()).reverse(); - const S = Array.from(signature.S.toByteArray()).reverse(); return key.verify(m, { - R: [].concat(R, Array(curve.payloadSize - R.length).fill(0)), - S: [].concat(S, Array(curve.payloadSize - S.length).fill(0)) + R: signature.R.toArray('le', 32), + S: signature.S.toArray('le', 32) }, hash_algo); } -module.exports = { - sign: sign, - verify: verify -}; +export default { sign, verify }; diff --git a/src/crypto/public_key/elliptic/index.js b/src/crypto/public_key/elliptic/index.js index 35bfdb83..9599fc97 100644 --- a/src/crypto/public_key/elliptic/index.js +++ b/src/crypto/public_key/elliptic/index.js @@ -30,11 +30,6 @@ import ecdsa from './ecdsa'; import eddsa from './eddsa'; import ecdh from './ecdh'; -module.exports = { - ecdsa: ecdsa, - eddsa: eddsa, - ecdh: ecdh, - get: get, - generate: generate, - getPreferredHashAlgo: getPreferredHashAlgo +export default { + ecdh, ecdsa, eddsa, get, generate, getPreferredHashAlgo }; diff --git a/src/crypto/public_key/elliptic/key.js b/src/crypto/public_key/elliptic/key.js index 859e968b..3d9bc954 100644 --- a/src/crypto/public_key/elliptic/key.js +++ b/src/crypto/public_key/elliptic/key.js @@ -29,7 +29,7 @@ * @module crypto/public_key/elliptic/key */ -import curves from './curves'; +import { webCurves, nodeCurves } from './curves'; import BigInteger from '../jsbn'; import hash from '../../hash'; import util from '../../../util'; @@ -37,13 +37,7 @@ import enums from '../../../enums'; import base64 from '../../../encoding/base64'; const webCrypto = util.getWebCrypto(); -const { webCurves } = curves; const nodeCrypto = util.getNodeCrypto(); -const { nodeCurves } = curves; - -// const webCrypto = util.getWebCrypto(); -// const nodeCrypto = util.getNodeCrypto(); -// const { webCurves, nodeCurves } = curves; const jwkToPem = nodeCrypto ? require('jwk-to-pem') : undefined; const ECDSASignature = nodeCrypto ? @@ -54,16 +48,13 @@ const ECDSASignature = nodeCrypto ? ); }) : undefined; -function KeyPair(curve, options) { +export default function KeyPair(curve, options) { this.curve = curve; this.keyType = curve.curve.type === 'edwards' ? enums.publicKey.eddsa : enums.publicKey.ecdsa; this.keyPair = this.curve.keyPair(options); } KeyPair.prototype.sign = async function (message, hash_algo) { - if (util.isString(message)) { - message = util.str2Uint8Array(message); - } if (webCrypto && this.curve.web) { // If browser doesn't support a curve, we'll catch it try { @@ -79,9 +70,6 @@ KeyPair.prototype.sign = async function (message, hash_algo) { }; KeyPair.prototype.verify = async function (message, signature, hash_algo) { - if (util.isString(message)) { - message = util.str2Uint8Array(message); - } if (webCrypto && this.curve.web) { // If browser doesn't support a curve, we'll catch it try { @@ -115,10 +103,6 @@ KeyPair.prototype.getPrivate = function () { return this.keyPair.getPrivate().toArray(); }; -module.exports = { - KeyPair: KeyPair -}; - ////////////////////////// // // diff --git a/src/crypto/signature.js b/src/crypto/signature.js index 4136802c..bb4a10b3 100644 --- a/src/crypto/signature.js +++ b/src/crypto/signature.js @@ -22,15 +22,6 @@ export default { * @return {Boolean} true if signature (sig_data was equal to data over hash) */ verify: async function(algo, hash_algo, msg_MPIs, publickey_MPIs, data) { - let m; - let r; - let s; - let Q; - let curve; - let signature; - - data = util.Uint8Array2str(data); - switch (algo) { case 1: // RSA (Encrypt or Sign) [HAC] @@ -38,12 +29,11 @@ export default { // RSA Encrypt-Only [HAC] case 3: { // RSA Sign-Only [HAC] + const m = msg_MPIs[0].toUint8Array(); const n = publickey_MPIs[0].toUint8Array(); - const k = publickey_MPIs[0].byteLength(); const e = publickey_MPIs[1].toUint8Array(); - m = msg_MPIs[0].toUint8Array(); const EM = RSA_RAW.verify(m, [n, e]); - const EM2 = pkcs1.emsa.encode(hash_algo, data, k); + const EM2 = pkcs1.emsa.encode(hash_algo, util.Uint8Array2str(data), n.length); return util.hexidump(EM) === EM2; } case 16: { @@ -52,35 +42,27 @@ export default { } case 17: { // DSA (Digital Signature Algorithm) [FIPS186] [HAC] - const dsa = publicKey.dsa; - r = msg_MPIs[0].toBN(); - s = msg_MPIs[1].toBN(); + const r = msg_MPIs[0].toBN(); + const s = msg_MPIs[1].toBN(); const p = publickey_MPIs[0].toBN(); const q = publickey_MPIs[1].toBN(); const g = publickey_MPIs[2].toBN(); const y = publickey_MPIs[3].toBN(); - m = util.str2Uint8Array(data); - return dsa.verify(hash_algo, r, s, m, p, q, g, y); + return publicKey.dsa.verify(hash_algo, r, s, data, p, q, g, y); } case 19: { // ECDSA - const { ecdsa } = publicKey.elliptic; - [curve] = publickey_MPIs; - r = msg_MPIs[0].toBigInteger(); - s = msg_MPIs[1].toBigInteger(); - m = data; - Q = publickey_MPIs[1].toBigInteger(); - return ecdsa.verify(curve.oid, hash_algo, { r: r, s: s }, m, Q); + const oid = publickey_MPIs[0]; + const signature = { r: msg_MPIs[0].toUint8Array(), s: msg_MPIs[1].toUint8Array() }; + const Q = publickey_MPIs[1].toUint8Array(); + return publicKey.elliptic.ecdsa.verify(oid, hash_algo, signature, data, Q); } case 22: { // EdDSA - const { eddsa } = publicKey.elliptic; - [curve] = publickey_MPIs; - r = msg_MPIs[0].toBigInteger(); - s = msg_MPIs[1].toBigInteger(); - m = data; - Q = publickey_MPIs[1].toBigInteger(); - return eddsa.verify(curve.oid, hash_algo, { R: r, S: s }, m, Q); + const oid = publickey_MPIs[0]; + const signature = { R: msg_MPIs[0].toBN(), S: msg_MPIs[1].toBN() }; + const Q = publickey_MPIs[1].toBN(); + return publicKey.elliptic.eddsa.verify(oid, hash_algo, signature, data, Q); } default: throw new Error('Invalid signature algorithm.'); @@ -97,13 +79,6 @@ export default { */ sign: async function(algo, hash_algo, keyIntegers, data) { - data = util.Uint8Array2str(data); - - let m; - let d; - let curve; - let signature; - switch (algo) { case 1: // RSA (Encrypt or Sign) [HAC] @@ -112,21 +87,21 @@ export default { case 3: { // RSA Sign-Only [HAC] const n = keyIntegers[0].toUint8Array(); - const k = keyIntegers[0].byteLength(); const e = keyIntegers[1].toUint8Array(); - d = keyIntegers[2].toUint8Array(); - m = util.hex2Uint8Array('00'+pkcs1.emsa.encode(hash_algo, data, k)); // FIXME remove '00' + const d = keyIntegers[2].toUint8Array(); + data = util.Uint8Array2str(data); + const m = util.hex2Uint8Array( + '00'+pkcs1.emsa.encode(hash_algo, data, n.length) // FIXME remove '00' + ); return util.Uint8Array2MPI(RSA_RAW.sign(m, [n, e, d])); } case 17: { // DSA (Digital Signature Algorithm) [FIPS186] [HAC] - const dsa = publicKey.dsa; const p = keyIntegers[0].toBN(); const q = keyIntegers[1].toBN(); const g = keyIntegers[2].toBN(); const x = keyIntegers[4].toBN(); - m = util.str2Uint8Array(data); - signature = dsa.sign(hash_algo, m, g, p, q, x); + const signature = publicKey.dsa.sign(hash_algo, data, g, p, q, x); return util.concatUint8Array([ util.Uint8Array2MPI(signature.r.toArrayLike(Uint8Array)), util.Uint8Array2MPI(signature.s.toArrayLike(Uint8Array)) @@ -138,23 +113,22 @@ export default { } case 19: { // ECDSA - const { ecdsa } = publicKey.elliptic; - [curve] = keyIntegers; - d = keyIntegers[2].toBigInteger(); - m = data; - signature = await ecdsa.sign(curve.oid, hash_algo, m, d); - return util.str2Uint8Array(signature.r.toMPI() + signature.s.toMPI()); + const oid = keyIntegers[0]; + const d = keyIntegers[2].toUint8Array(); + const signature = await publicKey.elliptic.ecdsa.sign(oid, hash_algo, data, d); + return util.concatUint8Array([ + util.Uint8Array2MPI(signature.r.toArrayLike(Uint8Array)), + util.Uint8Array2MPI(signature.s.toArrayLike(Uint8Array)) + ]); } case 22: { // EdDSA - const { eddsa } = publicKey.elliptic; - [curve] = keyIntegers; - d = keyIntegers[2].toBigInteger(); - m = data; - signature = await eddsa.sign(curve.oid, hash_algo, m, d); + const oid = keyIntegers[0]; + const d = keyIntegers[2].toBN(); + const signature = await publicKey.elliptic.eddsa.sign(oid, hash_algo, data, d); return util.concatUint8Array([ - util.Uint8Array2MPI(signature.R.toArrayLike(Uint8Array, 'le', 32)), - util.Uint8Array2MPI(signature.S.toArrayLike(Uint8Array, 'le', 32)) + util.Uint8Array2MPI(Uint8Array.from(signature.R)), + util.Uint8Array2MPI(Uint8Array.from(signature.S)) ]); } default: diff --git a/src/type/oid.js b/src/type/oid.js index e4ba3e8b..88c75e25 100644 --- a/src/type/oid.js +++ b/src/type/oid.js @@ -31,7 +31,9 @@ module.exports = OID; * @constructor */ function OID(oid) { - if (typeof oid === 'undefined') { + if (oid instanceof OID) { + oid = oid.oid; + } else if (typeof oid === 'undefined') { oid = ''; } else if (util.isArray(oid)) { oid = util.bin2str(oid); diff --git a/test/crypto/elliptic.js b/test/crypto/elliptic.js index ef3b10d1..29adc473 100644 --- a/test/crypto/elliptic.js +++ b/test/crypto/elliptic.js @@ -9,7 +9,7 @@ const bin2bi = function (bytes) { const mpi = new openpgp.MPI(); bytes = openpgp.util.bin2str(bytes); mpi.fromBytes(bytes); - return mpi.toBigInteger(); + return mpi.toUint8Array(); // FIXME }; describe('Elliptic Curve Cryptography', function () { @@ -316,9 +316,9 @@ describe('Elliptic Curve Cryptography', function () { data = new Uint8Array(data); } return Promise.resolve().then(() => { - const ecdh = elliptic_curves.ecdh; - return ecdh.decrypt( - oid, + const curve = elliptic_curves.get(oid); + return elliptic_curves.ecdh.decrypt( + curve.oid, cipher, hash, bin2bi(ephemeral), diff --git a/test/general/x25519.js b/test/general/x25519.js index 7ed5f337..0e6534c2 100644 --- a/test/general/x25519.js +++ b/test/general/x25519.js @@ -235,9 +235,9 @@ describe('X25519 Cryptography', function () { const hi = firstKey.key; const primaryKey = hi.primaryKey; const subKey = hi.subKeys[0].subKey; - expect(primaryKey.params[0].oid).to.equal(elliptic.get('ed25519').oid); + expect(primaryKey.params[0].toHex()).to.equal(elliptic.get('ed25519').oid.toHex()); expect(primaryKey.algorithm).to.equal('eddsa'); - expect(subKey.params[0].oid).to.equal(elliptic.get('curve25519').oid); + expect(subKey.params[0].toHex()).to.equal(elliptic.get('curve25519').oid.toHex()); expect(subKey.algorithm).to.equal('ecdh'); // Self Certificate is valid @@ -255,9 +255,9 @@ describe('X25519 Cryptography', function () { }; return openpgp.generateKey(options).then(function (secondKey) { const bye = secondKey.key; - expect(bye.primaryKey.params[0].oid).to.equal(elliptic.get('ed25519').oid); + expect(bye.primaryKey.params[0].toHex()).to.equal(elliptic.get('ed25519').oid.toHex()); expect(bye.primaryKey.algorithm).to.equal('eddsa'); - expect(bye.subKeys[0].subKey.params[0].oid).to.equal(elliptic.get('curve25519').oid); + expect(bye.subKeys[0].subKey.params[0].toHex()).to.equal(elliptic.get('curve25519').oid.toHex()); expect(bye.subKeys[0].subKey.algorithm).to.equal('ecdh'); // Self Certificate is valid @@ -319,16 +319,16 @@ describe('X25519 Cryptography', function () { describe('Ed25519 Test Vectors from RFC8032', function () { // https://tools.ietf.org/html/rfc8032#section-7.1 const signature = openpgp.crypto.signature; - const curve = openpgp.crypto.publicKey.elliptic.get('ed25519'); + const curve = elliptic.get('ed25519'); const util = openpgp.util; function testVector(vector) { const S = curve.keyFromSecret(vector.SECRET_KEY); - const P = curve.keyFromPublic(vector.PUBLIC_KEY); + const P = curve.keyFromPublic('40'+vector.PUBLIC_KEY); expect(S.getPublic()).to.deep.equal(P.getPublic()); const data = util.str2Uint8Array(vector.MESSAGE); const keyIntegers = [ openpgp.OID.fromClone(curve), - new openpgp.MPI(util.hex2bin(vector.PUBLIC_KEY)), + new openpgp.MPI(util.hex2bin('40'+vector.PUBLIC_KEY)), new openpgp.MPI(util.hex2bin(vector.SECRET_KEY)) ]; const msg_MPIs = [