Parse and create ECDH packets
This commit is contained in:
parent
585a2bd69d
commit
38a53c1bb1
|
@ -21,6 +21,7 @@
|
||||||
* @requires crypto/cipher
|
* @requires crypto/cipher
|
||||||
* @requires crypto/public_key
|
* @requires crypto/public_key
|
||||||
* @requires crypto/random
|
* @requires crypto/random
|
||||||
|
* @requires type/ecdh_symkey
|
||||||
* @requires type/mpi
|
* @requires type/mpi
|
||||||
* @module crypto/crypto
|
* @module crypto/crypto
|
||||||
*/
|
*/
|
||||||
|
@ -30,8 +31,19 @@
|
||||||
import random from './random.js';
|
import random from './random.js';
|
||||||
import cipher from './cipher';
|
import cipher from './cipher';
|
||||||
import publicKey from './public_key';
|
import publicKey from './public_key';
|
||||||
|
import type_ecdh_symkey from '../type/ecdh_symkey.js';
|
||||||
import type_mpi from '../type/mpi.js';
|
import type_mpi from '../type/mpi.js';
|
||||||
|
|
||||||
|
function BigInteger2mpi(bn) {
|
||||||
|
var mpi = new type_mpi();
|
||||||
|
mpi.fromBigInteger(bn);
|
||||||
|
return mpi;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapResult(result) {
|
||||||
|
return result.map(BigInteger2mpi);
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/**
|
/**
|
||||||
* Encrypts data using the specified public key multiprecision integers
|
* Encrypts data using the specified public key multiprecision integers
|
||||||
|
@ -42,7 +54,7 @@ export default {
|
||||||
* @return {Array<module:type/mpi>} if RSA an module:type/mpi;
|
* @return {Array<module:type/mpi>} if RSA an module:type/mpi;
|
||||||
* if elgamal encryption an array of two module:type/mpi is returned; otherwise null
|
* if elgamal encryption an array of two module:type/mpi is returned; otherwise null
|
||||||
*/
|
*/
|
||||||
publicKeyEncrypt: function(algo, publicMPIs, data) {
|
publicKeyEncrypt: function(algo, publicMPIs, data, fingerprint) {
|
||||||
var result = (function() {
|
var result = (function() {
|
||||||
var m;
|
var m;
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
|
@ -52,7 +64,7 @@ export default {
|
||||||
var n = publicMPIs[0].toBigInteger();
|
var n = publicMPIs[0].toBigInteger();
|
||||||
var e = publicMPIs[1].toBigInteger();
|
var e = publicMPIs[1].toBigInteger();
|
||||||
m = data.toBigInteger();
|
m = data.toBigInteger();
|
||||||
return [rsa.encrypt(m, e, n)];
|
return mapResult([rsa.encrypt(m, e, n)]);
|
||||||
|
|
||||||
case 'elgamal':
|
case 'elgamal':
|
||||||
var elgamal = new publicKey.elgamal();
|
var elgamal = new publicKey.elgamal();
|
||||||
|
@ -60,18 +72,22 @@ export default {
|
||||||
var g = publicMPIs[1].toBigInteger();
|
var g = publicMPIs[1].toBigInteger();
|
||||||
var y = publicMPIs[2].toBigInteger();
|
var y = publicMPIs[2].toBigInteger();
|
||||||
m = data.toBigInteger();
|
m = data.toBigInteger();
|
||||||
return elgamal.encrypt(m, g, p, y);
|
return mapResult(elgamal.encrypt(m, g, p, y));
|
||||||
|
|
||||||
|
case 'ecdh':
|
||||||
|
var ecdh = publicKey.elliptic.ecdh;
|
||||||
|
var curve = publicMPIs[0];
|
||||||
|
var kdf_params = publicMPIs[2];
|
||||||
|
var R = publicMPIs[1].toBigInteger();
|
||||||
|
var res = ecdh.encrypt(curve.oid, kdf_params.cipher, kdf_params.hash, data, R, fingerprint);
|
||||||
|
return [BigInteger2mpi(res.V), new type_ecdh_symkey(res.C)];
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
return result.map(function(bn) {
|
return result;
|
||||||
var mpi = new type_mpi();
|
|
||||||
mpi.fromBigInteger(bn);
|
|
||||||
return mpi;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,7 +102,7 @@ export default {
|
||||||
* @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: function(algo, keyIntegers, dataIntegers) {
|
publicKeyDecrypt: function(algo, keyIntegers, dataIntegers, fingerprint) {
|
||||||
var p;
|
var p;
|
||||||
|
|
||||||
var bn = (function() {
|
var bn = (function() {
|
||||||
|
@ -111,6 +127,16 @@ export default {
|
||||||
var c2 = dataIntegers[1].toBigInteger();
|
var c2 = dataIntegers[1].toBigInteger();
|
||||||
p = keyIntegers[0].toBigInteger();
|
p = keyIntegers[0].toBigInteger();
|
||||||
return elgamal.decrypt(c1, c2, p, x);
|
return elgamal.decrypt(c1, c2, p, x);
|
||||||
|
|
||||||
|
case 'ecdh':
|
||||||
|
var ecdh = publicKey.elliptic.ecdh;
|
||||||
|
var curve = keyIntegers[0];
|
||||||
|
var kdf_params = keyIntegers[2];
|
||||||
|
var V = dataIntegers[0].toBigInteger();
|
||||||
|
var C = dataIntegers[1].data;
|
||||||
|
var r = keyIntegers[3].toBigInteger();
|
||||||
|
return ecdh.decrypt(curve.oid, kdf_params.cipher, kdf_params.hash, V, C, r, fingerprint);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -144,8 +170,9 @@ export default {
|
||||||
// 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 1;
|
return 1;
|
||||||
|
case 'ecdh':
|
||||||
case 'ecdsa':
|
case 'ecdsa':
|
||||||
// Algorithm-Specific Fields for ECDSA 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 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
|
@ -185,6 +212,13 @@ export default {
|
||||||
case 'ecdsa':
|
case 'ecdsa':
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
|
// Algorithm-Specific Fields for ECDH public keys:
|
||||||
|
// - OID of curve;
|
||||||
|
// - MPI of EC point representing public key.
|
||||||
|
// - variable-length field containing KDF parameters.
|
||||||
|
case 'ecdh':
|
||||||
|
return 3;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Error('Unknown algorithm.');
|
throw new Error('Unknown algorithm.');
|
||||||
}
|
}
|
||||||
|
@ -210,14 +244,6 @@ export default {
|
||||||
default:
|
default:
|
||||||
throw new Error('Unsupported algorithm for key generation.');
|
throw new Error('Unsupported algorithm for key generation.');
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapResult(result) {
|
|
||||||
return result.map(function(bn) {
|
|
||||||
var mpi = new type_mpi();
|
|
||||||
mpi.fromBigInteger(bn);
|
|
||||||
return mpi;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
* major versions. Consequently, this section is complex.
|
* major versions. Consequently, this section is complex.
|
||||||
* @requires crypto
|
* @requires crypto
|
||||||
* @requires enums
|
* @requires enums
|
||||||
|
* @requires type/kdf_params
|
||||||
* @requires type/keyid
|
* @requires type/keyid
|
||||||
* @requires type/mpi
|
* @requires type/mpi
|
||||||
* @requires type/oid
|
* @requires type/oid
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
|
|
||||||
import util from '../util.js';
|
import util from '../util.js';
|
||||||
import type_mpi from '../type/mpi.js';
|
import type_mpi from '../type/mpi.js';
|
||||||
|
import type_kdf_params from '../type/kdf_params.js';
|
||||||
import type_keyid from '../type/keyid.js';
|
import type_keyid from '../type/keyid.js';
|
||||||
import type_oid from '../type/oid.js';
|
import type_oid from '../type/oid.js';
|
||||||
import enums from '../enums.js';
|
import enums from '../enums.js';
|
||||||
|
@ -102,8 +104,10 @@ PublicKey.prototype.read = function (bytes) {
|
||||||
var p = 0;
|
var p = 0;
|
||||||
|
|
||||||
for (var i = 0; i < mpicount && p < bmpi.length; i++) {
|
for (var i = 0; i < mpicount && p < bmpi.length; i++) {
|
||||||
if (this.algorithm === 'ecdsa' && i === 0) {
|
if ((this.algorithm === 'ecdsa' || this.algorithm === 'ecdh') && i === 0) {
|
||||||
this.mpi[i] = new type_oid();
|
this.mpi[i] = new type_oid();
|
||||||
|
} else if (this.algorithm === 'ecdh' && i === 2) {
|
||||||
|
this.mpi[i] = new type_kdf_params();
|
||||||
} else {
|
} else {
|
||||||
this.mpi[i] = new type_mpi();
|
this.mpi[i] = new type_mpi();
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
* decrypt the message.
|
* decrypt the message.
|
||||||
* @requires crypto
|
* @requires crypto
|
||||||
* @requires enums
|
* @requires enums
|
||||||
|
* @requires type/ecdh_symkey
|
||||||
* @requires type/keyid
|
* @requires type/keyid
|
||||||
* @requires type/mpi
|
* @requires type/mpi
|
||||||
* @requires util
|
* @requires util
|
||||||
|
@ -41,6 +42,7 @@
|
||||||
|
|
||||||
import type_keyid from '../type/keyid.js';
|
import type_keyid from '../type/keyid.js';
|
||||||
import util from '../util.js';
|
import util from '../util.js';
|
||||||
|
import type_ecdh_symkey from '../type/ecdh_symkey.js';
|
||||||
import type_mpi from '../type/mpi.js';
|
import type_mpi from '../type/mpi.js';
|
||||||
import enums from '../enums.js';
|
import enums from '../enums.js';
|
||||||
import crypto from '../crypto';
|
import crypto from '../crypto';
|
||||||
|
@ -88,6 +90,9 @@ PublicKeyEncryptedSessionKey.prototype.read = function (bytes) {
|
||||||
case 'elgamal':
|
case 'elgamal':
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
|
case 'ecdh':
|
||||||
|
return 2;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Error("Invalid algorithm.");
|
throw new Error("Invalid algorithm.");
|
||||||
}
|
}
|
||||||
|
@ -96,7 +101,12 @@ PublicKeyEncryptedSessionKey.prototype.read = function (bytes) {
|
||||||
this.encrypted = [];
|
this.encrypted = [];
|
||||||
|
|
||||||
for (var j = 0; j < integerCount; j++) {
|
for (var j = 0; j < integerCount; j++) {
|
||||||
var mpi = new type_mpi();
|
var mpi;
|
||||||
|
if (this.publicKeyAlgorithm === 'ecdh' && j === 1) {
|
||||||
|
mpi = new type_ecdh_symkey();
|
||||||
|
} else {
|
||||||
|
mpi = new type_mpi();
|
||||||
|
}
|
||||||
i += mpi.read(bytes.subarray(i, bytes.length));
|
i += mpi.read(bytes.subarray(i, bytes.length));
|
||||||
this.encrypted.push(mpi);
|
this.encrypted.push(mpi);
|
||||||
}
|
}
|
||||||
|
@ -126,15 +136,21 @@ PublicKeyEncryptedSessionKey.prototype.encrypt = function (key) {
|
||||||
var checksum = util.calc_checksum(this.sessionKey);
|
var checksum = util.calc_checksum(this.sessionKey);
|
||||||
data += util.Uint8Array2str(util.writeNumber(checksum, 2));
|
data += util.Uint8Array2str(util.writeNumber(checksum, 2));
|
||||||
|
|
||||||
var mpi = new type_mpi();
|
var mpi;
|
||||||
|
if (this.publicKeyAlgorithm === 'ecdh') {
|
||||||
|
mpi = util.str2Uint8Array(crypto.pkcs5.addPadding(data));
|
||||||
|
} else {
|
||||||
|
mpi = new type_mpi();
|
||||||
mpi.fromBytes(crypto.pkcs1.eme.encode(
|
mpi.fromBytes(crypto.pkcs1.eme.encode(
|
||||||
data,
|
data,
|
||||||
key.mpi[0].byteLength()));
|
key.mpi[0].byteLength()));
|
||||||
|
}
|
||||||
|
|
||||||
this.encrypted = crypto.publicKeyEncrypt(
|
this.encrypted = crypto.publicKeyEncrypt(
|
||||||
this.publicKeyAlgorithm,
|
this.publicKeyAlgorithm,
|
||||||
key.mpi,
|
key.mpi,
|
||||||
mpi);
|
mpi,
|
||||||
|
key.fingerprint);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,11 +165,18 @@ PublicKeyEncryptedSessionKey.prototype.decrypt = function (key) {
|
||||||
var result = crypto.publicKeyDecrypt(
|
var result = crypto.publicKeyDecrypt(
|
||||||
this.publicKeyAlgorithm,
|
this.publicKeyAlgorithm,
|
||||||
key.mpi,
|
key.mpi,
|
||||||
this.encrypted).toBytes();
|
this.encrypted,
|
||||||
|
key.fingerprint).toBytes();
|
||||||
|
|
||||||
var checksum = util.readNumber(util.str2Uint8Array(result.substr(result.length - 2)));
|
var checksum;
|
||||||
|
var decoded;
|
||||||
var decoded = crypto.pkcs1.eme.decode(result);
|
if (this.publicKeyAlgorithm === 'ecdh') {
|
||||||
|
decoded = crypto.pkcs5.removePadding(result);
|
||||||
|
checksum = util.readNumber(util.str2Uint8Array(decoded.substr(decoded.length - 2)));
|
||||||
|
} else {
|
||||||
|
decoded = crypto.pkcs1.eme.decode(result);
|
||||||
|
checksum = util.readNumber(util.str2Uint8Array(result.substr(result.length - 2)));
|
||||||
|
}
|
||||||
|
|
||||||
key = util.str2Uint8Array(decoded.substring(1, decoded.length - 2));
|
key = util.str2Uint8Array(decoded.substring(1, decoded.length - 2));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user