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