Various quickfixes and cleanups
This commit is contained in:
parent
b794956691
commit
605021af3b
|
@ -436,7 +436,7 @@ function des_removePadding(message, padding) {
|
||||||
|
|
||||||
// added by Recurity Labs
|
// added by Recurity Labs
|
||||||
|
|
||||||
function Des(key) {
|
function TripleDES(key) {
|
||||||
this.key = [];
|
this.key = [];
|
||||||
|
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
|
@ -458,13 +458,12 @@ function Des(key) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Des.keySize = Des.prototype.keySize = 24;
|
TripleDES.keySize = TripleDES.prototype.keySize = 24;
|
||||||
Des.blockSize = Des.prototype.blockSize = 8;
|
TripleDES.blockSize = TripleDES.prototype.blockSize = 8;
|
||||||
|
|
||||||
// This is "original" DES - Des is actually Triple DES.
|
// This is "original" DES
|
||||||
// This is only exported so we can unit test.
|
|
||||||
|
|
||||||
function OriginalDes(key) {
|
function DES(key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
|
|
||||||
this.encrypt = function(block, padding) {
|
this.encrypt = function(block, padding) {
|
||||||
|
@ -478,9 +477,4 @@ function OriginalDes(key) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default { DES, TripleDES };
|
||||||
/** @static */
|
|
||||||
des: Des,
|
|
||||||
/** @static */
|
|
||||||
originalDes: OriginalDes
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,26 +1,27 @@
|
||||||
/**
|
/**
|
||||||
* @requires crypto/cipher/aes
|
* @requires crypto/cipher/aes
|
||||||
* @requires crypto/cipher/blowfish
|
* @requires crypto/cipher/des
|
||||||
* @requires crypto/cipher/cast5
|
* @requires crypto/cipher/cast5
|
||||||
* @requires crypto/cipher/twofish
|
* @requires crypto/cipher/twofish
|
||||||
|
* @requires crypto/cipher/blowfish
|
||||||
* @module crypto/cipher
|
* @module crypto/cipher
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import aes from './aes.js';
|
import aes from './aes';
|
||||||
import desModule from './des.js';
|
import des from './des.js';
|
||||||
import cast5 from './cast5.js';
|
import cast5 from './cast5';
|
||||||
import twofish from './twofish.js';
|
import twofish from './twofish';
|
||||||
import blowfish from './blowfish.js';
|
import blowfish from './blowfish';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/** @see module:crypto/cipher/aes */
|
/** @see module:crypto/cipher/aes */
|
||||||
aes128: aes(128),
|
aes128: aes(128),
|
||||||
aes192: aes(192),
|
aes192: aes(192),
|
||||||
aes256: aes(256),
|
aes256: aes(256),
|
||||||
/** @see module:crypto/cipher/des.originalDes */
|
/** @see module:crypto/cipher/des~DES */
|
||||||
des: desModule.originalDes,
|
des: des.DES,
|
||||||
/** @see module:crypto/cipher/des.des */
|
/** @see module:crypto/cipher/des~TripleDES */
|
||||||
tripledes: desModule.des,
|
tripledes: des.TripleDES,
|
||||||
/** @see module:crypto/cipher/cast5 */
|
/** @see module:crypto/cipher/cast5 */
|
||||||
cast5: cast5,
|
cast5: cast5,
|
||||||
/** @see module:crypto/cipher/twofish */
|
/** @see module:crypto/cipher/twofish */
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @requires bn.js
|
* @requires bn.js
|
||||||
* @requires asmcrypto.js
|
|
||||||
* @requires crypto/public_key
|
* @requires crypto/public_key
|
||||||
* @requires crypto/cipher
|
* @requires crypto/cipher
|
||||||
* @requires crypto/random
|
* @requires crypto/random
|
||||||
|
@ -27,6 +26,7 @@
|
||||||
* @requires type/kdf_params
|
* @requires type/kdf_params
|
||||||
* @requires type/mpi
|
* @requires type/mpi
|
||||||
* @requires type/oid
|
* @requires type/oid
|
||||||
|
* @requires enums
|
||||||
* @requires util
|
* @requires util
|
||||||
* @module crypto/crypto
|
* @module crypto/crypto
|
||||||
*/
|
*/
|
||||||
|
@ -39,6 +39,7 @@ import type_ecdh_symkey from '../type/ecdh_symkey';
|
||||||
import type_kdf_params from '../type/kdf_params';
|
import type_kdf_params from '../type/kdf_params';
|
||||||
import type_mpi from '../type/mpi';
|
import type_mpi from '../type/mpi';
|
||||||
import type_oid from '../type/oid';
|
import type_oid from '../type/oid';
|
||||||
|
import enums from '../enums';
|
||||||
import util from '../util';
|
import util from '../util';
|
||||||
|
|
||||||
function constructParams(types, data) {
|
function constructParams(types, data) {
|
||||||
|
@ -52,39 +53,41 @@ function constructParams(types, data) {
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/**
|
/**
|
||||||
* Encrypts data using the specified public key multiprecision integers
|
* Encrypts data using specified algorithm and public key parameters.
|
||||||
* and the specified algorithm.
|
* See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms.
|
||||||
* @param {module:enums.publicKey} algo Algorithm to be used (See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1})
|
* @param {module:enums.publicKey} algo Public key algorithm
|
||||||
* @param {Array<module:type/mpi|module:type/oid|module:type/kdf_params|module:type/ecdh_symkey>} publicParams Algorithm dependent params
|
* @param {Array<module:type/mpi|
|
||||||
* @param {module:type/mpi} data Data to be encrypted as MPI
|
module:type/oid|
|
||||||
* @param {String} fingerprint Recipient fingerprint
|
module:type/kdf_params>} pub_params Algorithm-specific public key parameters
|
||||||
* @return {Array<module:type/mpi|module:type/oid|module:type/kdf_params|module:type/ecdh_symkey>} encrypted session key parameters
|
* @param {module:type/mpi} data Data to be encrypted as MPI
|
||||||
|
* @param {String} fingerprint Recipient fingerprint
|
||||||
|
* @return {Array<module:type/mpi|
|
||||||
|
module:type/ecdh_symkey>} encrypted session key parameters
|
||||||
*/
|
*/
|
||||||
publicKeyEncrypt: async function(algo, publicParams, data, fingerprint) {
|
publicKeyEncrypt: async function(algo, pub_params, data, fingerprint) {
|
||||||
// TODO change algo to return enums
|
|
||||||
const types = this.getEncSessionKeyParamTypes(algo);
|
const types = this.getEncSessionKeyParamTypes(algo);
|
||||||
return (async function() {
|
return (async function() {
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
case 'rsa_encrypt':
|
case enums.publicKey.rsa_encrypt:
|
||||||
case 'rsa_encrypt_sign': {
|
case enums.publicKey.rsa_encrypt_sign: {
|
||||||
const m = data.toUint8Array();
|
const m = data.toUint8Array();
|
||||||
const n = publicParams[0].toUint8Array();
|
const n = pub_params[0].toUint8Array();
|
||||||
const e = publicParams[1].toUint8Array();
|
const e = pub_params[1].toUint8Array();
|
||||||
const res = await publicKey.rsa.encrypt(m, n, e);
|
const res = await publicKey.rsa.encrypt(m, n, e);
|
||||||
return constructParams(types, [new BN(res)]);
|
return constructParams(types, [new BN(res)]);
|
||||||
}
|
}
|
||||||
case 'elgamal': {
|
case enums.publicKey.elgamal: {
|
||||||
const m = data.toBN();
|
const m = data.toBN();
|
||||||
const p = publicParams[0].toBN();
|
const p = pub_params[0].toBN();
|
||||||
const g = publicParams[1].toBN();
|
const g = pub_params[1].toBN();
|
||||||
const y = publicParams[2].toBN();
|
const y = pub_params[2].toBN();
|
||||||
const res = await publicKey.elgamal.encrypt(m, p, g, y);
|
const res = await publicKey.elgamal.encrypt(m, p, g, y);
|
||||||
return constructParams(types, [res.c1, res.c2]);
|
return constructParams(types, [res.c1, res.c2]);
|
||||||
}
|
}
|
||||||
case 'ecdh': {
|
case enums.publicKey.ecdh: {
|
||||||
const oid = publicParams[0];
|
const oid = pub_params[0];
|
||||||
const kdf_params = publicParams[2];
|
const Q = pub_params[1].toUint8Array();
|
||||||
const Q = publicParams[1].toUint8Array();
|
const kdf_params = pub_params[2];
|
||||||
const res = await publicKey.elliptic.ecdh.encrypt(
|
const res = await publicKey.elliptic.ecdh.encrypt(
|
||||||
oid, kdf_params.cipher, kdf_params.hash, data, Q, 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]);
|
||||||
|
@ -96,47 +99,50 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypts data using the specified public key multiprecision integers of the private key,
|
* Decrypts data using specified algorithm and private key parameters.
|
||||||
* the specified secretMPIs of the private key and the specified algorithm.
|
* See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms.
|
||||||
* @param {module:enums.publicKey} algo Algorithm to be used (See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1})
|
* @param {module:enums.publicKey} algo Public key algorithm
|
||||||
* @param {Array<module:type/mpi|module:type/oid|module:type/kdf_params>} keyIntegers Algorithm dependent params
|
* @param {Array<module:type/mpi|
|
||||||
* @param {Array<module:type/mpi|module:type/ecdh_symkey>} dataIntegers encrypted session key parameters
|
module:type/oid|
|
||||||
* @param {String} fingerprint Recipient fingerprint
|
module:type/kdf_params>} key_params Algorithm-specific public, private key parameters
|
||||||
* @return {module:type/mpi} returns a big integer containing the decrypted data; otherwise null
|
* @param {Array<module:type/mpi|
|
||||||
|
module:type/ecdh_symkey>}
|
||||||
|
data_params encrypted session key parameters
|
||||||
|
* @param {String} fingerprint Recipient fingerprint
|
||||||
|
* @return {module:type/mpi} An MPI containing the decrypted data
|
||||||
*/
|
*/
|
||||||
publicKeyDecrypt: async function(algo, keyIntegers, dataIntegers, fingerprint) {
|
publicKeyDecrypt: async function(algo, key_params, data_params, fingerprint) {
|
||||||
// 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 enums.publicKey.rsa_encrypt_sign:
|
||||||
case 'rsa_encrypt': {
|
case enums.publicKey.rsa_encrypt: {
|
||||||
const c = dataIntegers[0].toUint8Array();
|
const c = data_params[0].toUint8Array();
|
||||||
const n = keyIntegers[0].toUint8Array(); // pq
|
const n = key_params[0].toUint8Array(); // pq
|
||||||
const e = keyIntegers[1].toUint8Array();
|
const e = key_params[1].toUint8Array();
|
||||||
const d = keyIntegers[2].toUint8Array(); // de = 1 mod (p-1)(q-1)
|
const d = key_params[2].toUint8Array(); // de = 1 mod (p-1)(q-1)
|
||||||
const p = keyIntegers[3].toUint8Array();
|
const p = key_params[3].toUint8Array();
|
||||||
const q = keyIntegers[4].toUint8Array();
|
const q = key_params[4].toUint8Array();
|
||||||
const u = keyIntegers[5].toUint8Array(); // q^-1 mod p
|
const u = key_params[5].toUint8Array(); // q^-1 mod p
|
||||||
return publicKey.rsa.decrypt(c, n, e, d, p, q, u);
|
return publicKey.rsa.decrypt(c, n, e, d, p, q, u);
|
||||||
}
|
}
|
||||||
case 'elgamal': {
|
case enums.publicKey.elgamal: {
|
||||||
const c1 = dataIntegers[0].toBN();
|
const c1 = data_params[0].toBN();
|
||||||
const c2 = dataIntegers[1].toBN();
|
const c2 = data_params[1].toBN();
|
||||||
const p = keyIntegers[0].toBN();
|
const p = key_params[0].toBN();
|
||||||
const x = keyIntegers[3].toBN();
|
const x = key_params[3].toBN();
|
||||||
return publicKey.elgamal.decrypt(c1, c2, p, x);
|
return publicKey.elgamal.decrypt(c1, c2, p, x);
|
||||||
}
|
}
|
||||||
case 'ecdh': {
|
case enums.publicKey.ecdh: {
|
||||||
const oid = keyIntegers[0];
|
const oid = key_params[0];
|
||||||
const kdf_params = keyIntegers[2];
|
const kdf_params = key_params[2];
|
||||||
const V = dataIntegers[0].toUint8Array();
|
const V = data_params[0].toUint8Array();
|
||||||
const C = dataIntegers[1].data;
|
const C = data_params[1].data;
|
||||||
const d = keyIntegers[3].toUint8Array();
|
const d = key_params[3].toUint8Array();
|
||||||
return publicKey.elliptic.ecdh.decrypt(
|
return publicKey.elliptic.ecdh.decrypt(
|
||||||
oid, kdf_params.cipher, kdf_params.hash, V, C, d, fingerprint);
|
oid, kdf_params.cipher, kdf_params.hash, V, C, d, fingerprint);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return null;
|
throw new Error('Invalid public key encryption algorithm.');
|
||||||
}
|
}
|
||||||
}()));
|
}()));
|
||||||
},
|
},
|
||||||
|
@ -147,31 +153,31 @@ export default {
|
||||||
*/
|
*/
|
||||||
getPrivKeyParamTypes: function(algo) {
|
getPrivKeyParamTypes: function(algo) {
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
case 'rsa_encrypt':
|
case enums.publicKey.rsa_encrypt:
|
||||||
case 'rsa_encrypt_sign':
|
case enums.publicKey.rsa_encrypt_sign:
|
||||||
case 'rsa_sign':
|
case enums.publicKey.rsa_sign:
|
||||||
// Algorithm-Specific Fields for RSA secret keys:
|
// Algorithm-Specific Fields for RSA secret keys:
|
||||||
// - multiprecision integer (MPI) of RSA secret exponent d.
|
// - multiprecision integer (MPI) of RSA secret exponent d.
|
||||||
// - MPI of RSA secret prime value p.
|
// - MPI of RSA secret prime value p.
|
||||||
// - MPI of RSA secret prime value q (p < q).
|
// - MPI of RSA secret prime value q (p < q).
|
||||||
// - MPI of u, the multiplicative inverse of p, mod q.
|
// - MPI of u, the multiplicative inverse of p, mod q.
|
||||||
return [type_mpi, type_mpi, type_mpi, type_mpi];
|
return [type_mpi, type_mpi, type_mpi, type_mpi];
|
||||||
case 'elgamal':
|
case enums.publicKey.elgamal:
|
||||||
// Algorithm-Specific Fields for Elgamal secret keys:
|
// Algorithm-Specific Fields for Elgamal secret keys:
|
||||||
// - MPI of Elgamal secret exponent x.
|
// - MPI of Elgamal secret exponent x.
|
||||||
return [type_mpi];
|
return [type_mpi];
|
||||||
case 'dsa':
|
case enums.publicKey.dsa:
|
||||||
// Algorithm-Specific Fields for DSA secret keys:
|
// Algorithm-Specific Fields for DSA secret keys:
|
||||||
// - MPI of DSA secret exponent x.
|
// - MPI of DSA secret exponent x.
|
||||||
return [type_mpi];
|
return [type_mpi];
|
||||||
case 'ecdh':
|
case enums.publicKey.ecdh:
|
||||||
case 'ecdsa':
|
case enums.publicKey.ecdsa:
|
||||||
case 'eddsa':
|
case enums.publicKey.eddsa:
|
||||||
// Algorithm-Specific Fields for ECDSA or ECDH secret keys:
|
// Algorithm-Specific Fields for ECDSA or ECDH secret keys:
|
||||||
// - MPI of an integer representing the secret key.
|
// - MPI of an integer representing the secret key.
|
||||||
return [type_mpi];
|
return [type_mpi];
|
||||||
default:
|
default:
|
||||||
throw new Error('Unknown algorithm');
|
throw new Error('Invalid public key encryption algorithm.');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -184,37 +190,37 @@ export default {
|
||||||
// - a multiprecision integer (MPI) of RSA public modulus n;
|
// - a multiprecision integer (MPI) of RSA public modulus n;
|
||||||
// - an MPI of RSA public encryption exponent e.
|
// - an MPI of RSA public encryption exponent e.
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
case 'rsa_encrypt':
|
case enums.publicKey.rsa_encrypt:
|
||||||
case 'rsa_encrypt_sign':
|
case enums.publicKey.rsa_encrypt_sign:
|
||||||
case 'rsa_sign':
|
case enums.publicKey.rsa_sign:
|
||||||
return [type_mpi, type_mpi];
|
return [type_mpi, type_mpi];
|
||||||
// Algorithm-Specific Fields for Elgamal public keys:
|
// Algorithm-Specific Fields for Elgamal public keys:
|
||||||
// - MPI of Elgamal prime p;
|
// - MPI of Elgamal prime p;
|
||||||
// - MPI of Elgamal group generator g;
|
// - MPI of Elgamal group generator g;
|
||||||
// - MPI of Elgamal public key value y (= g**x mod p where x is secret).
|
// - MPI of Elgamal public key value y (= g**x mod p where x is secret).
|
||||||
case 'elgamal':
|
case enums.publicKey.elgamal:
|
||||||
return [type_mpi, type_mpi, type_mpi];
|
return [type_mpi, type_mpi, type_mpi];
|
||||||
// Algorithm-Specific Fields for DSA public keys:
|
// Algorithm-Specific Fields for DSA public keys:
|
||||||
// - MPI of DSA prime p;
|
// - MPI of DSA prime p;
|
||||||
// - MPI of DSA group order q (q is a prime divisor of p-1);
|
// - MPI of DSA group order q (q is a prime divisor of p-1);
|
||||||
// - MPI of DSA group generator g;
|
// - MPI of DSA group generator g;
|
||||||
// - MPI of DSA public-key value y (= g**x mod p where x is secret).
|
// - MPI of DSA public-key value y (= g**x mod p where x is secret).
|
||||||
case 'dsa':
|
case enums.publicKey.dsa:
|
||||||
return [type_mpi, type_mpi, type_mpi, type_mpi];
|
return [type_mpi, type_mpi, type_mpi, type_mpi];
|
||||||
// Algorithm-Specific Fields for ECDSA/EdDSA public keys:
|
// Algorithm-Specific Fields for ECDSA/EdDSA public keys:
|
||||||
// - OID of curve;
|
// - OID of curve;
|
||||||
// - MPI of EC point representing public key.
|
// - MPI of EC point representing public key.
|
||||||
case 'ecdsa':
|
case enums.publicKey.ecdsa:
|
||||||
case 'eddsa':
|
case enums.publicKey.eddsa:
|
||||||
return [type_oid, type_mpi];
|
return [type_oid, type_mpi];
|
||||||
// Algorithm-Specific Fields for ECDH public keys:
|
// Algorithm-Specific Fields for ECDH public keys:
|
||||||
// - OID of curve;
|
// - OID of curve;
|
||||||
// - MPI of EC point representing public key.
|
// - MPI of EC point representing public key.
|
||||||
// - KDF: variable-length field containing KDF parameters.
|
// - KDF: variable-length field containing KDF parameters.
|
||||||
case 'ecdh':
|
case enums.publicKey.ecdh:
|
||||||
return [type_oid, type_mpi, type_kdf_params];
|
return [type_oid, type_mpi, type_kdf_params];
|
||||||
default:
|
default:
|
||||||
throw new Error('Unknown algorithm.');
|
throw new Error('Invalid public key encryption algorithm.');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -226,24 +232,24 @@ export default {
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
// Algorithm-Specific Fields for RSA encrypted session keys:
|
// Algorithm-Specific Fields for RSA encrypted session keys:
|
||||||
// - MPI of RSA encrypted value m**e mod n.
|
// - MPI of RSA encrypted value m**e mod n.
|
||||||
case 'rsa_encrypt':
|
case enums.publicKey.rsa_encrypt:
|
||||||
case 'rsa_encrypt_sign':
|
case enums.publicKey.rsa_encrypt_sign:
|
||||||
return [type_mpi];
|
return [type_mpi];
|
||||||
|
|
||||||
// Algorithm-Specific Fields for Elgamal encrypted session keys:
|
// Algorithm-Specific Fields for Elgamal encrypted session keys:
|
||||||
// - MPI of Elgamal value g**k mod p
|
// - MPI of Elgamal value g**k mod p
|
||||||
// - MPI of Elgamal value m * y**k mod p
|
// - MPI of Elgamal value m * y**k mod p
|
||||||
case 'elgamal':
|
case enums.publicKey.elgamal:
|
||||||
return [type_mpi, type_mpi];
|
return [type_mpi, type_mpi];
|
||||||
|
|
||||||
// Algorithm-Specific Fields for ECDH encrypted session keys:
|
// Algorithm-Specific Fields for ECDH encrypted session keys:
|
||||||
// - MPI containing the ephemeral key used to establish the shared secret
|
// - MPI containing the ephemeral key used to establish the shared secret
|
||||||
// - ECDH Symmetric Key
|
// - ECDH Symmetric Key
|
||||||
case 'ecdh':
|
case enums.publicKey.ecdh:
|
||||||
return [type_mpi, type_ecdh_symkey];
|
return [type_mpi, type_ecdh_symkey];
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Error('Unknown algorithm.');
|
throw new Error('Invalid public key encryption algorithm.');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -254,35 +260,39 @@ export default {
|
||||||
* @return {Array} The array of parameters
|
* @return {Array} The array of parameters
|
||||||
*/
|
*/
|
||||||
generateParams: function(algo, bits, oid) {
|
generateParams: function(algo, bits, oid) {
|
||||||
const types = this.getPubKeyParamTypes(algo).concat(this.getPrivKeyParamTypes(algo));
|
const types = [].concat(this.getPubKeyParamTypes(algo), this.getPrivKeyParamTypes(algo));
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
case 'rsa_encrypt':
|
case enums.publicKey.rsa_encrypt:
|
||||||
case 'rsa_encrypt_sign':
|
case enums.publicKey.rsa_encrypt_sign:
|
||||||
case 'rsa_sign': {
|
case enums.publicKey.rsa_sign: {
|
||||||
return publicKey.rsa.generate(bits, "10001").then(function(keyObject) {
|
return publicKey.rsa.generate(bits, "10001").then(function(keyObject) {
|
||||||
return constructParams(
|
return constructParams(
|
||||||
types, [keyObject.n, keyObject.ee, keyObject.d, keyObject.p, keyObject.q, keyObject.u]
|
types, [keyObject.n, keyObject.ee, keyObject.d, keyObject.p, keyObject.q, keyObject.u]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
case 'ecdsa':
|
case enums.publicKey.dsa:
|
||||||
case 'eddsa':
|
case enums.publicKey.elgamal:
|
||||||
|
throw new Error('Unsupported algorithm for key generation.');
|
||||||
|
case enums.publicKey.ecdsa:
|
||||||
|
case enums.publicKey.eddsa:
|
||||||
return publicKey.elliptic.generate(oid).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 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, [keyObject.hash, keyObject.cipher], keyObject.d]);
|
||||||
});
|
});
|
||||||
default:
|
default:
|
||||||
throw new Error('Unsupported algorithm for key generation.');
|
throw new Error('Invalid public key encryption algorithm.');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* generate random byte prefix as string for the specified algorithm
|
* Generates a random byte prefix for the specified algorithm
|
||||||
* @param {module:enums.symmetric} algo Algorithm to use (see {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2})
|
* See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms.
|
||||||
* @return {Uint8Array} Random bytes with length equal to the block
|
* @param {module:enums.symmetric} algo Symmetric encryption algorithm
|
||||||
|
* @return {Uint8Array} Random bytes with length equal to the block
|
||||||
* size of the cipher
|
* size of the cipher
|
||||||
*/
|
*/
|
||||||
getPrefixRandom: function(algo) {
|
getPrefixRandom: function(algo) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import pkcs5 from './pkcs5.js';
|
||||||
import crypto from './crypto.js';
|
import crypto from './crypto.js';
|
||||||
import aes_kw from './aes_kw.js';
|
import aes_kw from './aes_kw.js';
|
||||||
|
|
||||||
|
// TODO move cfb and gcm to cipher
|
||||||
const mod = {
|
const mod = {
|
||||||
/** @see module:crypto/cipher */
|
/** @see module:crypto/cipher */
|
||||||
cipher: cipher,
|
cipher: cipher,
|
||||||
|
|
|
@ -48,7 +48,4 @@ function decode(msg) {
|
||||||
throw new Error('Invalid padding');
|
throw new Error('Invalid padding');
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default { encode, decode };
|
||||||
encode,
|
|
||||||
decode
|
|
||||||
};
|
|
||||||
|
|
|
@ -63,7 +63,6 @@ export default {
|
||||||
// of leftmost bits equal to the number of bits of q. This (possibly
|
// of leftmost bits equal to the number of bits of q. This (possibly
|
||||||
// truncated) hash function result is treated as a number and used
|
// truncated) hash function result is treated as a number and used
|
||||||
// directly in the DSA signature algorithm.
|
// directly in the DSA signature algorithm.
|
||||||
// TODO rewrite getLeftNBits to work with Uint8Arrays
|
|
||||||
const h = new BN(
|
const h = new BN(
|
||||||
util.str2Uint8Array(
|
util.str2Uint8Array(
|
||||||
util.getLeftNBits(
|
util.getLeftNBits(
|
||||||
|
|
|
@ -1,67 +1,60 @@
|
||||||
/**
|
/**
|
||||||
* @requires asmcrypto.js
|
|
||||||
* @requires crypto/public_key
|
* @requires crypto/public_key
|
||||||
* @requires crypto/pkcs1
|
* @requires crypto/pkcs1
|
||||||
|
* @requires enums
|
||||||
* @requires util
|
* @requires util
|
||||||
* @module crypto/signature
|
* @module crypto/signature
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// FIXME wrap rsa.js around this
|
|
||||||
import publicKey from './public_key';
|
import publicKey from './public_key';
|
||||||
import pkcs1 from './pkcs1';
|
import pkcs1 from './pkcs1';
|
||||||
|
import enums from '../enums';
|
||||||
import util from '../util';
|
import util from '../util';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/**
|
/**
|
||||||
*
|
* Verifies the signature provided for data using specified algorithms and public key parameters.
|
||||||
* @param {module:enums.publicKey} algo public Key algorithm
|
* See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1}
|
||||||
* @param {module:enums.hash} hash_algo Hash algorithm
|
* and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}
|
||||||
* @param {Array<module:type/mpi>} msg_MPIs Signature multiprecision integers
|
* for public key and hash algorithms.
|
||||||
* @param {Array<module:type/mpi>} publickey_MPIs Public key multiprecision integers
|
* @param {module:enums.publicKey} algo Public key algorithm
|
||||||
* @param {Uint8Array} data Data on where the signature was computed on.
|
* @param {module:enums.hash} hash_algo Hash algorithm
|
||||||
* @return {Boolean} true if signature (sig_data was equal to data over hash)
|
* @param {Array<module:type/mpi>} msg_MPIs Algorithm-specific signature parameters
|
||||||
|
* @param {Array<module:type/mpi>} pub_MPIs Algorithm-specific public key parameters
|
||||||
|
* @param {Uint8Array} data Data for which the signature was created
|
||||||
|
* @return {Boolean} True if signature is valid
|
||||||
*/
|
*/
|
||||||
verify: async function(algo, hash_algo, msg_MPIs, publickey_MPIs, data) {
|
verify: async function(algo, hash_algo, msg_MPIs, pub_MPIs, data) {
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
case 1:
|
case enums.publicKey.rsa_encrypt_sign:
|
||||||
// RSA (Encrypt or Sign) [HAC]
|
case enums.publicKey.rsa_encrypt:
|
||||||
case 2:
|
case enums.publicKey.rsa_sign: {
|
||||||
// RSA Encrypt-Only [HAC]
|
|
||||||
case 3: {
|
|
||||||
// RSA Sign-Only [HAC]
|
|
||||||
const m = msg_MPIs[0].toUint8Array();
|
const m = msg_MPIs[0].toUint8Array();
|
||||||
const n = publickey_MPIs[0].toUint8Array();
|
const n = pub_MPIs[0].toUint8Array();
|
||||||
const e = publickey_MPIs[1].toUint8Array();
|
const e = pub_MPIs[1].toUint8Array();
|
||||||
const EM = publicKey.rsa.verify(m, n, e);
|
const EM = publicKey.rsa.verify(m, n, e);
|
||||||
const EM2 = pkcs1.emsa.encode(hash_algo, util.Uint8Array2str(data), n.length);
|
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 enums.publicKey.dsa: {
|
||||||
// Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
|
|
||||||
throw new Error("signing with Elgamal is not defined in the OpenPGP standard.");
|
|
||||||
}
|
|
||||||
case 17: {
|
|
||||||
// DSA (Digital Signature Algorithm) [FIPS186] [HAC]
|
|
||||||
const r = msg_MPIs[0].toBN();
|
const r = msg_MPIs[0].toBN();
|
||||||
const s = msg_MPIs[1].toBN();
|
const s = msg_MPIs[1].toBN();
|
||||||
const p = publickey_MPIs[0].toBN();
|
const p = pub_MPIs[0].toBN();
|
||||||
const q = publickey_MPIs[1].toBN();
|
const q = pub_MPIs[1].toBN();
|
||||||
const g = publickey_MPIs[2].toBN();
|
const g = pub_MPIs[2].toBN();
|
||||||
const y = publickey_MPIs[3].toBN();
|
const y = pub_MPIs[3].toBN();
|
||||||
return publicKey.dsa.verify(hash_algo, r, s, data, p, q, g, y);
|
return publicKey.dsa.verify(hash_algo, r, s, data, p, q, g, y);
|
||||||
}
|
}
|
||||||
case 19: {
|
case enums.publicKey.ecdsa: {
|
||||||
// ECDSA
|
const oid = pub_MPIs[0];
|
||||||
const oid = publickey_MPIs[0];
|
|
||||||
const signature = { r: msg_MPIs[0].toUint8Array(), s: msg_MPIs[1].toUint8Array() };
|
const signature = { r: msg_MPIs[0].toUint8Array(), s: msg_MPIs[1].toUint8Array() };
|
||||||
const Q = publickey_MPIs[1].toUint8Array();
|
const Q = pub_MPIs[1].toUint8Array();
|
||||||
return publicKey.elliptic.ecdsa.verify(oid, hash_algo, signature, data, Q);
|
return publicKey.elliptic.ecdsa.verify(oid, hash_algo, signature, data, Q);
|
||||||
}
|
}
|
||||||
case 22: {
|
case enums.publicKey.eddsa: {
|
||||||
// EdDSA
|
const oid = pub_MPIs[0];
|
||||||
const oid = publickey_MPIs[0];
|
|
||||||
const signature = { R: msg_MPIs[0].toBN(), S: msg_MPIs[1].toBN() };
|
const signature = { R: msg_MPIs[0].toBN(), S: msg_MPIs[1].toBN() };
|
||||||
const Q = publickey_MPIs[1].toBN();
|
const Q = pub_MPIs[1].toBN();
|
||||||
return publicKey.elliptic.eddsa.verify(oid, hash_algo, signature, data, Q);
|
return publicKey.elliptic.eddsa.verify(oid, hash_algo, signature, data, Q);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -70,25 +63,24 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a signature on data using the specified algorithm
|
* Creates a signature on data using specified algorithms and private key parameters.
|
||||||
* @param {module:enums.publicKey} algo Asymmetric cipher algorithm to use (See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1})
|
* See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1}
|
||||||
* @param {module:enums.hash} hash_algo hash Algorithm to use (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4})
|
* and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}
|
||||||
* @param {Array<module:type/mpi>} keyIntegers Public followed by Private key multiprecision algorithm-specific parameters
|
* for public key and hash algorithms.
|
||||||
* @param {Uint8Array} data Data to be signed
|
* @param {module:enums.publicKey} algo Public key algorithm
|
||||||
* @return {Array<module:type/mpi>}
|
* @param {module:enums.hash} hash_algo Hash algorithm
|
||||||
|
* @param {Array<module:type/mpi>} key_params Algorithm-specific public and private key parameters
|
||||||
|
* @param {Uint8Array} data Data to be signed
|
||||||
|
* @return {Uint8Array} Signature
|
||||||
*/
|
*/
|
||||||
sign: async function(algo, hash_algo, keyIntegers, data) {
|
sign: async function(algo, hash_algo, key_params, data) {
|
||||||
|
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
case 1:
|
case enums.publicKey.rsa_encrypt_sign:
|
||||||
// RSA (Encrypt or Sign) [HAC]
|
case enums.publicKey.rsa_encrypt:
|
||||||
case 2:
|
case enums.publicKey.rsa_sign: {
|
||||||
// RSA Encrypt-Only [HAC]
|
const n = key_params[0].toUint8Array();
|
||||||
case 3: {
|
const e = key_params[1].toUint8Array();
|
||||||
// RSA Sign-Only [HAC]
|
const d = key_params[2].toUint8Array();
|
||||||
const n = keyIntegers[0].toUint8Array();
|
|
||||||
const e = keyIntegers[1].toUint8Array();
|
|
||||||
const d = keyIntegers[2].toUint8Array();
|
|
||||||
data = util.Uint8Array2str(data);
|
data = util.Uint8Array2str(data);
|
||||||
const m = util.hex2Uint8Array(
|
const m = util.hex2Uint8Array(
|
||||||
'00'+pkcs1.emsa.encode(hash_algo, data, n.length) // FIXME remove '00'
|
'00'+pkcs1.emsa.encode(hash_algo, data, n.length) // FIXME remove '00'
|
||||||
|
@ -96,36 +88,32 @@ export default {
|
||||||
const signature = publicKey.rsa.sign(m, n, e, d);
|
const signature = publicKey.rsa.sign(m, n, e, d);
|
||||||
return util.Uint8Array2MPI(signature);
|
return util.Uint8Array2MPI(signature);
|
||||||
}
|
}
|
||||||
case 17: {
|
case enums.publicKey.dsa: {
|
||||||
// DSA (Digital Signature Algorithm) [FIPS186] [HAC]
|
const p = key_params[0].toBN();
|
||||||
const p = keyIntegers[0].toBN();
|
const q = key_params[1].toBN();
|
||||||
const q = keyIntegers[1].toBN();
|
const g = key_params[2].toBN();
|
||||||
const g = keyIntegers[2].toBN();
|
const x = key_params[4].toBN();
|
||||||
const x = keyIntegers[4].toBN();
|
|
||||||
const signature = publicKey.dsa.sign(hash_algo, data, g, p, q, x);
|
const signature = publicKey.dsa.sign(hash_algo, data, 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))
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
case 16: {
|
case enums.publicKey.elgamal: {
|
||||||
// Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
|
|
||||||
throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.');
|
throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.');
|
||||||
}
|
}
|
||||||
case 19: {
|
case enums.publicKey.ecdsa: {
|
||||||
// ECDSA
|
const oid = key_params[0];
|
||||||
const oid = keyIntegers[0];
|
const d = key_params[2].toUint8Array();
|
||||||
const d = keyIntegers[2].toUint8Array();
|
|
||||||
const signature = await publicKey.elliptic.ecdsa.sign(oid, hash_algo, data, d);
|
const signature = await publicKey.elliptic.ecdsa.sign(oid, hash_algo, data, d);
|
||||||
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))
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
case 22: {
|
case enums.publicKey.eddsa: {
|
||||||
// EdDSA
|
const oid = key_params[0];
|
||||||
const oid = keyIntegers[0];
|
const d = key_params[2].toBN();
|
||||||
const d = keyIntegers[2].toBN();
|
|
||||||
const signature = await publicKey.elliptic.eddsa.sign(oid, hash_algo, data, d);
|
const signature = await publicKey.elliptic.eddsa.sign(oid, hash_algo, data, d);
|
||||||
return util.concatUint8Array([
|
return util.concatUint8Array([
|
||||||
util.Uint8Array2MPI(Uint8Array.from(signature.R)),
|
util.Uint8Array2MPI(Uint8Array.from(signature.R)),
|
||||||
|
|
|
@ -72,13 +72,22 @@ export default {
|
||||||
* @readonly
|
* @readonly
|
||||||
*/
|
*/
|
||||||
publicKey: {
|
publicKey: {
|
||||||
|
/** RSA (Encrypt or Sign) [HAC] */
|
||||||
rsa_encrypt_sign: 1,
|
rsa_encrypt_sign: 1,
|
||||||
|
/** RSA (Encrypt only) [HAC] */
|
||||||
rsa_encrypt: 2,
|
rsa_encrypt: 2,
|
||||||
|
/** RSA (Sign only) [HAC] */
|
||||||
rsa_sign: 3,
|
rsa_sign: 3,
|
||||||
|
/** Elgamal (Encrypt only) [ELGAMAL] [HAC] */
|
||||||
elgamal: 16,
|
elgamal: 16,
|
||||||
|
/** DSA (Sign only) [FIPS186] [HAC] */
|
||||||
dsa: 17,
|
dsa: 17,
|
||||||
|
/** ECDH (Encrypt only) [RFC6637] */
|
||||||
ecdh: 18,
|
ecdh: 18,
|
||||||
|
/** ECDSA (Sign only) [RFC6637] */
|
||||||
ecdsa: 19,
|
ecdsa: 19,
|
||||||
|
/** EdDSA (Sign only)
|
||||||
|
* [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */
|
||||||
eddsa: 22
|
eddsa: 22
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
14
src/key.js
14
src/key.js
|
@ -16,21 +16,21 @@
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @requires config
|
|
||||||
* @requires crypto
|
|
||||||
* @requires encoding/armor
|
* @requires encoding/armor
|
||||||
|
* @requires crypto
|
||||||
|
* @requires packet
|
||||||
|
* @requires config
|
||||||
* @requires enums
|
* @requires enums
|
||||||
* @requires util
|
* @requires util
|
||||||
* @requires packet
|
|
||||||
* @module key
|
* @module key
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import config from './config';
|
|
||||||
import crypto from './crypto';
|
|
||||||
import armor from './encoding/armor';
|
import armor from './encoding/armor';
|
||||||
|
import crypto from './crypto';
|
||||||
|
import packet from './packet';
|
||||||
|
import config from './config';
|
||||||
import enums from './enums';
|
import enums from './enums';
|
||||||
import util from './util';
|
import util from './util';
|
||||||
import packet from './packet';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
|
@ -209,7 +209,7 @@ Key.prototype.getKeyIds = function() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns array containing first key packet for given key ID or all key packets in the case of a wildcard ID
|
* Returns array containing first key packet for given key ID or all key packets in the case of a wildcard ID
|
||||||
* @param {type/keyid>} keyIds
|
* @param {type/keyid} keyId
|
||||||
* @return {(module:packet/public_subkey|module:packet/public_key|
|
* @return {(module:packet/public_subkey|module:packet/public_key|
|
||||||
* module:packet/secret_subkey|module:packet/secret_key|null)}
|
* module:packet/secret_subkey|module:packet/secret_key|null)}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -393,7 +393,7 @@ export function encryptSessionKey({ data, algorithm, publicKeys, passwords, wild
|
||||||
* Decrypt symmetric session keys with a private key or password. Either a private key or
|
* Decrypt symmetric session keys with a private key or password. Either a private key or
|
||||||
* a password must be specified.
|
* a password must be specified.
|
||||||
* @param {Message} message a message object containing the encrypted session key packets
|
* @param {Message} message a message object containing the encrypted session key packets
|
||||||
* @param {Key|Array<Key} privateKeys (optional) private keys with decrypted secret key data
|
* @param {Key|Array<Key>} privateKeys (optional) private keys with decrypted secret key data
|
||||||
* @param {String|Array<String>} passwords (optional) passwords to decrypt the session key
|
* @param {String|Array<String>} passwords (optional) passwords to decrypt the session key
|
||||||
* @return {Promise<Object|undefined>} Array of decrypted session key, algorithm pairs in form:
|
* @return {Promise<Object|undefined>} Array of decrypted session key, algorithm pairs in form:
|
||||||
* { data:Uint8Array, algorithm:String }
|
* { data:Uint8Array, algorithm:String }
|
||||||
|
|
|
@ -85,8 +85,8 @@ PublicKey.prototype.read = function (bytes) {
|
||||||
|
|
||||||
// - A one-octet number denoting the public-key algorithm of this key.
|
// - A one-octet number denoting the public-key algorithm of this key.
|
||||||
this.algorithm = enums.read(enums.publicKey, bytes[pos++]);
|
this.algorithm = enums.read(enums.publicKey, bytes[pos++]);
|
||||||
|
const algo = enums.write(enums.publicKey, this.algorithm);
|
||||||
const types = crypto.getPubKeyParamTypes(this.algorithm);
|
const types = crypto.getPubKeyParamTypes(algo);
|
||||||
this.params = crypto.constructParams(types);
|
this.params = crypto.constructParams(types);
|
||||||
|
|
||||||
const b = bytes.subarray(pos, bytes.length);
|
const b = bytes.subarray(pos, bytes.length);
|
||||||
|
@ -123,10 +123,10 @@ PublicKey.prototype.write = function () {
|
||||||
if (this.version === 3) {
|
if (this.version === 3) {
|
||||||
arr.push(util.writeNumber(this.expirationTimeV3, 2));
|
arr.push(util.writeNumber(this.expirationTimeV3, 2));
|
||||||
}
|
}
|
||||||
arr.push(new Uint8Array([enums.write(enums.publicKey, this.algorithm)]));
|
// Algorithm-specific params
|
||||||
|
const algo = enums.write(enums.publicKey, this.algorithm);
|
||||||
const paramCount = crypto.getPubKeyParamTypes(this.algorithm).length;
|
const paramCount = crypto.getPubKeyParamTypes(algo).length;
|
||||||
|
arr.push(new Uint8Array([algo]));
|
||||||
for (let i = 0; i < paramCount; i++) {
|
for (let i = 0; i < paramCount; i++) {
|
||||||
arr.push(this.params[i].write());
|
arr.push(this.params[i].write());
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,8 @@ PublicKey.prototype.getFingerprint = function () {
|
||||||
toHash = this.writeOld();
|
toHash = this.writeOld();
|
||||||
this.fingerprint = util.Uint8Array2str(crypto.hash.sha1(toHash));
|
this.fingerprint = util.Uint8Array2str(crypto.hash.sha1(toHash));
|
||||||
} else if (this.version === 3) {
|
} else if (this.version === 3) {
|
||||||
const paramCount = crypto.getPubKeyParamTypes(this.algorithm).length;
|
const algo = enums.write(enums.publicKey, this.algorithm);
|
||||||
|
const paramCount = crypto.getPubKeyParamTypes(algo).length;
|
||||||
for (let i = 0; i < paramCount; i++) {
|
for (let i = 0; i < paramCount; i++) {
|
||||||
toHash += this.params[i].toString();
|
toHash += this.params[i].toString();
|
||||||
}
|
}
|
||||||
|
@ -192,7 +193,7 @@ PublicKey.prototype.getFingerprint = function () {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns algorithm information
|
* Returns algorithm information
|
||||||
* @return {Promise<Object} An object of the form {algorithm: String, bits:int, curve:String}
|
* @return {Promise<Object>} An object of the form {algorithm: String, bits:int, curve:String}
|
||||||
*/
|
*/
|
||||||
PublicKey.prototype.getAlgorithmInfo = function () {
|
PublicKey.prototype.getAlgorithmInfo = function () {
|
||||||
const result = {};
|
const result = {};
|
||||||
|
@ -209,7 +210,8 @@ PublicKey.prototype.getAlgorithmInfo = function () {
|
||||||
* Fix custom types after cloning
|
* Fix custom types after cloning
|
||||||
*/
|
*/
|
||||||
PublicKey.prototype.postCloneTypeFix = function() {
|
PublicKey.prototype.postCloneTypeFix = function() {
|
||||||
const types = crypto.getPubKeyParamTypes(this.algorithm);
|
const algo = enums.write(enums.publicKey, this.algorithm);
|
||||||
|
const types = crypto.getPubKeyParamTypes(algo);
|
||||||
for (let i = 0; i < types.length; i++) {
|
for (let i = 0; i < types.length; i++) {
|
||||||
const param = this.params[i];
|
const param = this.params[i];
|
||||||
this.params[i] = types[i].fromClone(param);
|
this.params[i] = types[i].fromClone(param);
|
||||||
|
|
|
@ -75,7 +75,8 @@ PublicKeyEncryptedSessionKey.prototype.read = function (bytes) {
|
||||||
|
|
||||||
let i = 10;
|
let i = 10;
|
||||||
|
|
||||||
const types = crypto.getEncSessionKeyParamTypes(this.publicKeyAlgorithm);
|
const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm);
|
||||||
|
const types = crypto.getEncSessionKeyParamTypes(algo);
|
||||||
this.encrypted = crypto.constructParams(types);
|
this.encrypted = crypto.constructParams(types);
|
||||||
|
|
||||||
for (let j = 0; j < types.length; j++) {
|
for (let j = 0; j < types.length; j++) {
|
||||||
|
@ -106,18 +107,15 @@ PublicKeyEncryptedSessionKey.prototype.encrypt = async function (key) {
|
||||||
data += util.Uint8Array2str(util.writeNumber(checksum, 2));
|
data += util.Uint8Array2str(util.writeNumber(checksum, 2));
|
||||||
|
|
||||||
let toEncrypt;
|
let toEncrypt;
|
||||||
if (this.publicKeyAlgorithm === 'ecdh') {
|
const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm);
|
||||||
|
if (algo === enums.publicKey.ecdh) {
|
||||||
toEncrypt = new type_mpi(crypto.pkcs5.encode(data));
|
toEncrypt = new type_mpi(crypto.pkcs5.encode(data));
|
||||||
} else {
|
} else {
|
||||||
toEncrypt = new type_mpi(crypto.pkcs1.eme.encode(data, key.params[0].byteLength()));
|
toEncrypt = new type_mpi(crypto.pkcs1.eme.encode(data, key.params[0].byteLength()));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.encrypted = await crypto.publicKeyEncrypt(
|
this.encrypted = await crypto.publicKeyEncrypt(
|
||||||
this.publicKeyAlgorithm,
|
algo, key.params, toEncrypt, key.fingerprint);
|
||||||
key.params,
|
|
||||||
toEncrypt,
|
|
||||||
key.fingerprint
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -129,21 +127,18 @@ PublicKeyEncryptedSessionKey.prototype.encrypt = async function (key) {
|
||||||
* @return {String} The unencrypted session key
|
* @return {String} The unencrypted session key
|
||||||
*/
|
*/
|
||||||
PublicKeyEncryptedSessionKey.prototype.decrypt = async function (key) {
|
PublicKeyEncryptedSessionKey.prototype.decrypt = async function (key) {
|
||||||
const result = (await crypto.publicKeyDecrypt(
|
const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm);
|
||||||
this.publicKeyAlgorithm,
|
const result = await crypto.publicKeyDecrypt(
|
||||||
key.params,
|
algo, key.params, this.encrypted, key.fingerprint);
|
||||||
this.encrypted,
|
|
||||||
key.fingerprint
|
|
||||||
)).toString();
|
|
||||||
|
|
||||||
let checksum;
|
let checksum;
|
||||||
let decoded;
|
let decoded;
|
||||||
if (this.publicKeyAlgorithm === 'ecdh') {
|
if (algo === enums.publicKey.ecdh) {
|
||||||
decoded = crypto.pkcs5.decode(result);
|
decoded = crypto.pkcs5.decode(result.toString());
|
||||||
checksum = util.readNumber(util.str2Uint8Array(decoded.substr(decoded.length - 2)));
|
checksum = util.readNumber(util.str2Uint8Array(decoded.substr(decoded.length - 2)));
|
||||||
} else {
|
} else {
|
||||||
decoded = crypto.pkcs1.eme.decode(result);
|
decoded = crypto.pkcs1.eme.decode(result.toString());
|
||||||
checksum = util.readNumber(util.str2Uint8Array(result.substr(result.length - 2)));
|
checksum = util.readNumber(result.toUint8Array().slice(result.byteLength() - 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
key = util.str2Uint8Array(decoded.substring(1, decoded.length - 2));
|
key = util.str2Uint8Array(decoded.substring(1, decoded.length - 2));
|
||||||
|
@ -161,7 +156,8 @@ PublicKeyEncryptedSessionKey.prototype.decrypt = async function (key) {
|
||||||
*/
|
*/
|
||||||
PublicKeyEncryptedSessionKey.prototype.postCloneTypeFix = function() {
|
PublicKeyEncryptedSessionKey.prototype.postCloneTypeFix = function() {
|
||||||
this.publicKeyId = type_keyid.fromClone(this.publicKeyId);
|
this.publicKeyId = type_keyid.fromClone(this.publicKeyId);
|
||||||
const types = crypto.getEncSessionKeyParamTypes(this.publicKeyAlgorithm);
|
const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm);
|
||||||
|
const types = crypto.getEncSessionKeyParamTypes(algo);
|
||||||
for (let i = 0; i < this.encrypted.length; i++) {
|
for (let i = 0; i < this.encrypted.length; i++) {
|
||||||
this.encrypted[i] = types[i].fromClone(this.encrypted[i]);
|
this.encrypted[i] = types[i].fromClone(this.encrypted[i]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,8 @@ function parse_cleartext_params(hash_algorithm, cleartext, algorithm) {
|
||||||
return new Error("Hash mismatch.");
|
return new Error("Hash mismatch.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const types = crypto.getPrivKeyParamTypes(algorithm);
|
const algo = enums.write(enums.publicKey, algorithm);
|
||||||
|
const types = crypto.getPrivKeyParamTypes(algo);
|
||||||
const params = crypto.constructParams(types);
|
const params = crypto.constructParams(types);
|
||||||
let p = 0;
|
let p = 0;
|
||||||
|
|
||||||
|
@ -100,7 +101,8 @@ function parse_cleartext_params(hash_algorithm, cleartext, algorithm) {
|
||||||
|
|
||||||
function write_cleartext_params(hash_algorithm, algorithm, params) {
|
function write_cleartext_params(hash_algorithm, algorithm, params) {
|
||||||
const arr = [];
|
const arr = [];
|
||||||
const numPublicParams = crypto.getPubKeyParamTypes(algorithm).length;
|
const algo = enums.write(enums.publicKey, algorithm);
|
||||||
|
const numPublicParams = crypto.getPubKeyParamTypes(algo).length;
|
||||||
|
|
||||||
for (let i = numPublicParams; i < params.length; i++) {
|
for (let i = numPublicParams; i < params.length; i++) {
|
||||||
arr.push(params[i].write());
|
arr.push(params[i].write());
|
||||||
|
@ -269,8 +271,8 @@ SecretKey.prototype.decrypt = function (passphrase) {
|
||||||
|
|
||||||
SecretKey.prototype.generate = function (bits, curve) {
|
SecretKey.prototype.generate = function (bits, curve) {
|
||||||
const that = this;
|
const that = this;
|
||||||
|
const algo = enums.write(enums.publicKey, that.algorithm);
|
||||||
return crypto.generateParams(that.algorithm, bits, curve).then(function(params) {
|
return crypto.generateParams(algo, bits, curve).then(function(params) {
|
||||||
that.params = params;
|
that.params = params;
|
||||||
that.isDecrypted = true;
|
that.isDecrypted = true;
|
||||||
});
|
});
|
||||||
|
@ -283,7 +285,8 @@ SecretKey.prototype.clearPrivateParams = function () {
|
||||||
if (!this.encrypted) {
|
if (!this.encrypted) {
|
||||||
throw new Error('If secret key is not encrypted, clearing private params is irreversible.');
|
throw new Error('If secret key is not encrypted, clearing private params is irreversible.');
|
||||||
}
|
}
|
||||||
this.params = this.params.slice(0, crypto.getPubKeyParamTypes(this.algorithm).length);
|
const algo = enums.write(enums.publicKey, this.algorithm);
|
||||||
|
this.params = this.params.slice(0, crypto.getPubKeyParamTypes(algo).length);
|
||||||
this.isDecrypted = false;
|
this.isDecrypted = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -291,7 +294,8 @@ SecretKey.prototype.clearPrivateParams = function () {
|
||||||
* Fix custom types after cloning
|
* Fix custom types after cloning
|
||||||
*/
|
*/
|
||||||
SecretKey.prototype.postCloneTypeFix = function() {
|
SecretKey.prototype.postCloneTypeFix = function() {
|
||||||
const types = crypto.getPubKeyParamTypes(this.algorithm).concat(crypto.getPrivKeyParamTypes(this.algorithm));
|
const algo = enums.write(enums.publicKey, this.algorithm);
|
||||||
|
const types = [].concat(crypto.getPubKeyParamTypes(algo), crypto.getPrivKeyParamTypes(algo));
|
||||||
for (let i = 0; i < this.params.length; i++) {
|
for (let i = 0; i < this.params.length; i++) {
|
||||||
const param = this.params[i];
|
const param = this.params[i];
|
||||||
this.params[i] = types[i].fromClone(param);
|
this.params[i] = types[i].fromClone(param);
|
||||||
|
|
|
@ -446,6 +446,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// TODO rewrite getLeftNBits to work with Uint8Arrays
|
||||||
getLeftNBits: function (string, bitcount) {
|
getLeftNBits: function (string, bitcount) {
|
||||||
const rest = bitcount % 8;
|
const rest = bitcount % 8;
|
||||||
if (rest === 0) {
|
if (rest === 0) {
|
||||||
|
|
|
@ -381,11 +381,11 @@ describe('API functional testing', function() {
|
||||||
const RSAUnencryptedData = new openpgp.MPI();
|
const RSAUnencryptedData = new openpgp.MPI();
|
||||||
RSAUnencryptedData.fromBytes(crypto.pkcs1.eme.encode(symmKey, RSApubMPIs[0].byteLength()));
|
RSAUnencryptedData.fromBytes(crypto.pkcs1.eme.encode(symmKey, RSApubMPIs[0].byteLength()));
|
||||||
return crypto.publicKeyEncrypt(
|
return crypto.publicKeyEncrypt(
|
||||||
"rsa_encrypt_sign", RSApubMPIs, RSAUnencryptedData
|
1, RSApubMPIs, RSAUnencryptedData
|
||||||
).then(RSAEncryptedData => {
|
).then(RSAEncryptedData => {
|
||||||
|
|
||||||
return crypto.publicKeyDecrypt(
|
return crypto.publicKeyDecrypt(
|
||||||
"rsa_encrypt_sign", RSApubMPIs.concat(RSAsecMPIs), RSAEncryptedData
|
1, RSApubMPIs.concat(RSAsecMPIs), RSAEncryptedData
|
||||||
).then(data => {
|
).then(data => {
|
||||||
data = data.write();
|
data = data.write();
|
||||||
data = util.Uint8Array2str(data.subarray(2, data.length));
|
data = util.Uint8Array2str(data.subarray(2, data.length));
|
||||||
|
@ -402,11 +402,11 @@ describe('API functional testing', function() {
|
||||||
ElgamalUnencryptedData.fromBytes(crypto.pkcs1.eme.encode(symmKey, ElgamalpubMPIs[0].byteLength()));
|
ElgamalUnencryptedData.fromBytes(crypto.pkcs1.eme.encode(symmKey, ElgamalpubMPIs[0].byteLength()));
|
||||||
|
|
||||||
return crypto.publicKeyEncrypt(
|
return crypto.publicKeyEncrypt(
|
||||||
"elgamal", ElgamalpubMPIs, ElgamalUnencryptedData
|
16, ElgamalpubMPIs, ElgamalUnencryptedData
|
||||||
).then(ElgamalEncryptedData => {
|
).then(ElgamalEncryptedData => {
|
||||||
|
|
||||||
return crypto.publicKeyDecrypt(
|
return crypto.publicKeyDecrypt(
|
||||||
"elgamal", ElgamalpubMPIs.concat(ElgamalsecMPIs), ElgamalEncryptedData
|
16, ElgamalpubMPIs.concat(ElgamalsecMPIs), ElgamalEncryptedData
|
||||||
).then(data => {
|
).then(data => {
|
||||||
data = data.write();
|
data = data.write();
|
||||||
data = util.Uint8Array2str(data.subarray(2, data.length));
|
data = util.Uint8Array2str(data.subarray(2, data.length));
|
||||||
|
|
Loading…
Reference in New Issue
Block a user