Pass around KDF params as object (#1104)
This commit is contained in:
parent
320efc2435
commit
35b0012f2f
|
@ -91,9 +91,9 @@ export default {
|
||||||
data = new type_mpi(pkcs5.encode(data));
|
data = new type_mpi(pkcs5.encode(data));
|
||||||
const oid = pub_params[0];
|
const oid = pub_params[0];
|
||||||
const Q = pub_params[1].toUint8Array();
|
const Q = pub_params[1].toUint8Array();
|
||||||
const kdf_params = pub_params[2];
|
const kdfParams = pub_params[2];
|
||||||
const { publicKey: V, wrappedKey: C } = await publicKey.elliptic.ecdh.encrypt(
|
const { publicKey: V, wrappedKey: C } = await publicKey.elliptic.ecdh.encrypt(
|
||||||
oid, kdf_params.cipher, kdf_params.hash, data, Q, fingerprint);
|
oid, kdfParams, data, Q, fingerprint);
|
||||||
return constructParams(types, [V, C]);
|
return constructParams(types, [V, C]);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -138,13 +138,13 @@ export default {
|
||||||
}
|
}
|
||||||
case enums.publicKey.ecdh: {
|
case enums.publicKey.ecdh: {
|
||||||
const oid = key_params[0];
|
const oid = key_params[0];
|
||||||
const kdf_params = key_params[2];
|
const kdfParams = key_params[2];
|
||||||
const V = data_params[0].toUint8Array();
|
const V = data_params[0].toUint8Array();
|
||||||
const C = data_params[1].data;
|
const C = data_params[1].data;
|
||||||
const Q = key_params[1].toUint8Array();
|
const Q = key_params[1].toUint8Array();
|
||||||
const d = key_params[3].toUint8Array();
|
const d = key_params[3].toUint8Array();
|
||||||
const result = new type_mpi(await publicKey.elliptic.ecdh.decrypt(
|
const result = new type_mpi(await publicKey.elliptic.ecdh.decrypt(
|
||||||
oid, kdf_params.cipher, kdf_params.hash, V, C, Q, d, fingerprint));
|
oid, kdfParams, V, C, Q, d, fingerprint));
|
||||||
return pkcs5.decode(result.toString());
|
return pkcs5.decode(result.toString());
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -285,7 +285,12 @@ export default {
|
||||||
});
|
});
|
||||||
case enums.publicKey.ecdh:
|
case enums.publicKey.ecdh:
|
||||||
return publicKey.elliptic.generate(oid).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,
|
||||||
|
{ hash: keyObject.hash, cipher: keyObject.cipher },
|
||||||
|
keyObject.d
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
default:
|
default:
|
||||||
throw new Error('Invalid public key algorithm.');
|
throw new Error('Invalid public key algorithm.');
|
||||||
|
|
|
@ -37,7 +37,6 @@ import aes_kw from '../../aes_kw';
|
||||||
import cipher from '../../cipher';
|
import cipher from '../../cipher';
|
||||||
import random from '../../random';
|
import random from '../../random';
|
||||||
import hash from '../../hash';
|
import hash from '../../hash';
|
||||||
import type_kdf_params from '../../../type/kdf_params';
|
|
||||||
import enums from '../../../enums';
|
import enums from '../../../enums';
|
||||||
import util from '../../../util';
|
import util from '../../../util';
|
||||||
import { keyFromPublic, keyFromPrivate, getIndutnyCurve } from './indutnyKey';
|
import { keyFromPublic, keyFromPrivate, getIndutnyCurve } from './indutnyKey';
|
||||||
|
@ -46,12 +45,11 @@ const webCrypto = util.getWebCrypto();
|
||||||
const nodeCrypto = util.getNodeCrypto();
|
const nodeCrypto = util.getNodeCrypto();
|
||||||
|
|
||||||
// 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, kdfParams, fingerprint) {
|
||||||
const kdf_params = new type_kdf_params([hash_algo, cipher_algo]);
|
|
||||||
return util.concatUint8Array([
|
return util.concatUint8Array([
|
||||||
oid.write(),
|
oid.write(),
|
||||||
new Uint8Array([public_algo]),
|
new Uint8Array([public_algo]),
|
||||||
kdf_params.write(),
|
kdfParams.write(),
|
||||||
util.str_to_Uint8Array("Anonymous Sender "),
|
util.str_to_Uint8Array("Anonymous Sender "),
|
||||||
fingerprint.subarray(0, 20)
|
fingerprint.subarray(0, 20)
|
||||||
]);
|
]);
|
||||||
|
@ -117,20 +115,19 @@ async function genPublicEphemeralKey(curve, Q) {
|
||||||
* Encrypt and wrap a session key
|
* Encrypt and wrap a session key
|
||||||
*
|
*
|
||||||
* @param {module:type/oid} oid Elliptic curve object identifier
|
* @param {module:type/oid} oid Elliptic curve object identifier
|
||||||
* @param {module:enums.symmetric} cipher_algo Symmetric cipher to use
|
* @param {module:type/kdf_params} kdfParams KDF params including cipher and algorithm to use
|
||||||
* @param {module:enums.hash} hash_algo Hash algorithm to use
|
|
||||||
* @param {module:type/mpi} m Value derived from session key (RFC 6637)
|
* @param {module:type/mpi} m Value derived from session key (RFC 6637)
|
||||||
* @param {Uint8Array} Q Recipient public key
|
* @param {Uint8Array} Q Recipient public key
|
||||||
* @param {String} fingerprint Recipient fingerprint
|
* @param {Uint8Array} fingerprint Recipient fingerprint
|
||||||
* @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>}
|
* @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>}
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async function encrypt(oid, cipher_algo, hash_algo, m, Q, fingerprint) {
|
async function encrypt(oid, kdfParams, m, Q, fingerprint) {
|
||||||
const curve = new Curve(oid);
|
const curve = new Curve(oid);
|
||||||
const { publicKey, sharedKey } = await genPublicEphemeralKey(curve, Q);
|
const { publicKey, sharedKey } = await genPublicEphemeralKey(curve, Q);
|
||||||
const param = buildEcdhParam(enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint);
|
const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint);
|
||||||
cipher_algo = enums.read(enums.symmetric, cipher_algo);
|
const cipher_algo = enums.read(enums.symmetric, kdfParams.cipher);
|
||||||
const Z = await kdf(hash_algo, sharedKey, cipher[cipher_algo].keySize, param);
|
const Z = await kdf(kdfParams.hash, sharedKey, cipher[cipher_algo].keySize, param);
|
||||||
const wrappedKey = aes_kw.wrap(Z, m.toString());
|
const wrappedKey = aes_kw.wrap(Z, m.toString());
|
||||||
return { publicKey, wrappedKey };
|
return { publicKey, wrappedKey };
|
||||||
}
|
}
|
||||||
|
@ -176,26 +173,25 @@ async function genPrivateEphemeralKey(curve, V, Q, d) {
|
||||||
* Decrypt and unwrap the value derived from session key
|
* Decrypt and unwrap the value derived from session key
|
||||||
*
|
*
|
||||||
* @param {module:type/oid} oid Elliptic curve object identifier
|
* @param {module:type/oid} oid Elliptic curve object identifier
|
||||||
* @param {module:enums.symmetric} cipher_algo Symmetric cipher to use
|
* @param {module:type/kdf_params} kdfParams KDF params including cipher and algorithm to use
|
||||||
* @param {module:enums.hash} hash_algo Hash algorithm to use
|
|
||||||
* @param {Uint8Array} V Public part of ephemeral key
|
* @param {Uint8Array} 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 {Uint8Array} Q Recipient public key
|
* @param {Uint8Array} Q Recipient public key
|
||||||
* @param {Uint8Array} d Recipient private key
|
* @param {Uint8Array} d Recipient private key
|
||||||
* @param {String} fingerprint Recipient fingerprint
|
* @param {Uint8Array} fingerprint Recipient fingerprint
|
||||||
* @returns {Promise<BN>} Value derived from session key
|
* @returns {Promise<BN>} Value derived from session key
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async function decrypt(oid, cipher_algo, hash_algo, V, C, Q, d, fingerprint) {
|
async function decrypt(oid, kdfParams, V, C, Q, d, fingerprint) {
|
||||||
const curve = new Curve(oid);
|
const curve = new Curve(oid);
|
||||||
const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d);
|
const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d);
|
||||||
const param = buildEcdhParam(enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint);
|
const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint);
|
||||||
cipher_algo = enums.read(enums.symmetric, cipher_algo);
|
const cipher_algo = enums.read(enums.symmetric, kdfParams.cipher);
|
||||||
let err;
|
let err;
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
try {
|
try {
|
||||||
// Work around old go crypto bug and old OpenPGP.js bug, respectively.
|
// Work around old go crypto bug and old OpenPGP.js bug, respectively.
|
||||||
const Z = await kdf(hash_algo, sharedKey, cipher[cipher_algo].keySize, param, i === 1, i === 2);
|
const Z = await kdf(kdfParams.hash, sharedKey, cipher[cipher_algo].keySize, param, i === 1, i === 2);
|
||||||
return new BN(aes_kw.unwrap(Z, C));
|
return new BN(aes_kw.unwrap(Z, C));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
err = e;
|
err = e;
|
||||||
|
|
|
@ -27,20 +27,19 @@
|
||||||
* @module type/kdf_params
|
* @module type/kdf_params
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import enums from '../enums.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {enums.hash} hash Hash algorithm
|
* @param {enums.hash} hash Hash algorithm
|
||||||
* @param {enums.symmetric} cipher Symmetric algorithm
|
* @param {enums.symmetric} cipher Symmetric algorithm
|
||||||
*/
|
*/
|
||||||
function KDFParams(data) {
|
function KDFParams(data) {
|
||||||
if (data && data.length === 2) {
|
if (data) {
|
||||||
this.hash = data[0];
|
const { hash, cipher } = data;
|
||||||
this.cipher = data[1];
|
this.hash = hash;
|
||||||
|
this.cipher = cipher;
|
||||||
} else {
|
} else {
|
||||||
this.hash = enums.hash.sha1;
|
this.hash = null;
|
||||||
this.cipher = enums.symmetric.aes128;
|
this.cipher = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +66,8 @@ KDFParams.prototype.write = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
KDFParams.fromClone = function (clone) {
|
KDFParams.fromClone = function (clone) {
|
||||||
return new KDFParams([clone.hash, clone.cipher]);
|
const { hash, cipher } = clone;
|
||||||
|
return new KDFParams({ hash, cipher });
|
||||||
};
|
};
|
||||||
|
|
||||||
export default KDFParams;
|
export default KDFParams;
|
||||||
|
|
|
@ -19,8 +19,7 @@ describe('ECDH key exchange @lightweight', function () {
|
||||||
const curve = new elliptic_curves.Curve(oid);
|
const curve = new elliptic_curves.Curve(oid);
|
||||||
return elliptic_curves.ecdh.decrypt(
|
return elliptic_curves.ecdh.decrypt(
|
||||||
new openpgp.OID(curve.oid),
|
new openpgp.OID(curve.oid),
|
||||||
cipher,
|
new openpgp.KDFParams({ cipher, hash }),
|
||||||
hash,
|
|
||||||
new Uint8Array(ephemeral),
|
new Uint8Array(ephemeral),
|
||||||
data,
|
data,
|
||||||
new Uint8Array(pub),
|
new Uint8Array(pub),
|
||||||
|
@ -136,8 +135,9 @@ describe('ECDH key exchange @lightweight', function () {
|
||||||
);
|
);
|
||||||
let cipher_algo = curveObj.cipher;
|
let cipher_algo = curveObj.cipher;
|
||||||
const hash_algo = curveObj.hash;
|
const hash_algo = curveObj.hash;
|
||||||
|
const kdfParams = new openpgp.KDFParams({ cipher: cipher_algo, hash: hash_algo });
|
||||||
const param = openpgp.crypto.publicKey.elliptic.ecdh.buildEcdhParam(
|
const param = openpgp.crypto.publicKey.elliptic.ecdh.buildEcdhParam(
|
||||||
openpgp.enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint
|
openpgp.enums.publicKey.ecdh, oid, kdfParams, fingerprint
|
||||||
);
|
);
|
||||||
cipher_algo = openpgp.enums.read(openpgp.enums.symmetric, cipher_algo);
|
cipher_algo = openpgp.enums.read(openpgp.enums.symmetric, cipher_algo);
|
||||||
const Z = await openpgp.crypto.publicKey.elliptic.ecdh.kdf(
|
const Z = await openpgp.crypto.publicKey.elliptic.ecdh.kdf(
|
||||||
|
@ -154,8 +154,9 @@ describe('ECDH key exchange @lightweight', function () {
|
||||||
);
|
);
|
||||||
let cipher_algo = curveObj.cipher;
|
let cipher_algo = curveObj.cipher;
|
||||||
const hash_algo = curveObj.hash;
|
const hash_algo = curveObj.hash;
|
||||||
|
const kdfParams = new openpgp.KDFParams({ cipher: cipher_algo, hash: hash_algo });
|
||||||
const param = openpgp.crypto.publicKey.elliptic.ecdh.buildEcdhParam(
|
const param = openpgp.crypto.publicKey.elliptic.ecdh.buildEcdhParam(
|
||||||
openpgp.enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint
|
openpgp.enums.publicKey.ecdh, oid, kdfParams, fingerprint
|
||||||
);
|
);
|
||||||
cipher_algo = openpgp.enums.read(openpgp.enums.symmetric, cipher_algo);
|
cipher_algo = openpgp.enums.read(openpgp.enums.symmetric, cipher_algo);
|
||||||
const Z = await openpgp.crypto.publicKey.elliptic.ecdh.kdf(
|
const Z = await openpgp.crypto.publicKey.elliptic.ecdh.kdf(
|
||||||
|
@ -186,8 +187,9 @@ describe('ECDH key exchange @lightweight', function () {
|
||||||
const sharedKey = result.sharedKey;
|
const sharedKey = result.sharedKey;
|
||||||
let cipher_algo = curveObj.cipher;
|
let cipher_algo = curveObj.cipher;
|
||||||
const hash_algo = curveObj.hash;
|
const hash_algo = curveObj.hash;
|
||||||
|
const kdfParams = new openpgp.KDFParams({ cipher: cipher_algo, hash: hash_algo });
|
||||||
const param = openpgp.crypto.publicKey.elliptic.ecdh.buildEcdhParam(
|
const param = openpgp.crypto.publicKey.elliptic.ecdh.buildEcdhParam(
|
||||||
openpgp.enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint
|
openpgp.enums.publicKey.ecdh, oid, kdfParams, fingerprint
|
||||||
);
|
);
|
||||||
cipher_algo = openpgp.enums.read(openpgp.enums.symmetric, cipher_algo);
|
cipher_algo = openpgp.enums.read(openpgp.enums.symmetric, cipher_algo);
|
||||||
const Z = await openpgp.crypto.publicKey.elliptic.ecdh.kdf(
|
const Z = await openpgp.crypto.publicKey.elliptic.ecdh.kdf(
|
||||||
|
|
Loading…
Reference in New Issue
Block a user