Parse and create ECDH packets
This commit is contained in:
parent
585a2bd69d
commit
38a53c1bb1
|
@ -21,6 +21,7 @@
|
|||
* @requires crypto/cipher
|
||||
* @requires crypto/public_key
|
||||
* @requires crypto/random
|
||||
* @requires type/ecdh_symkey
|
||||
* @requires type/mpi
|
||||
* @module crypto/crypto
|
||||
*/
|
||||
|
@ -30,8 +31,19 @@
|
|||
import random from './random.js';
|
||||
import cipher from './cipher';
|
||||
import publicKey from './public_key';
|
||||
import type_ecdh_symkey from '../type/ecdh_symkey.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 {
|
||||
/**
|
||||
* 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;
|
||||
* 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 m;
|
||||
switch (algo) {
|
||||
|
@ -52,7 +64,7 @@ export default {
|
|||
var n = publicMPIs[0].toBigInteger();
|
||||
var e = publicMPIs[1].toBigInteger();
|
||||
m = data.toBigInteger();
|
||||
return [rsa.encrypt(m, e, n)];
|
||||
return mapResult([rsa.encrypt(m, e, n)]);
|
||||
|
||||
case 'elgamal':
|
||||
var elgamal = new publicKey.elgamal();
|
||||
|
@ -60,18 +72,22 @@ export default {
|
|||
var g = publicMPIs[1].toBigInteger();
|
||||
var y = publicMPIs[2].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:
|
||||
return [];
|
||||
}
|
||||
})();
|
||||
|
||||
return result.map(function(bn) {
|
||||
var mpi = new type_mpi();
|
||||
mpi.fromBigInteger(bn);
|
||||
return mpi;
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -86,7 +102,7 @@ export default {
|
|||
* @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 bn = (function() {
|
||||
|
@ -111,6 +127,16 @@ export default {
|
|||
var c2 = dataIntegers[1].toBigInteger();
|
||||
p = keyIntegers[0].toBigInteger();
|
||||
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:
|
||||
return null;
|
||||
}
|
||||
|
@ -144,8 +170,9 @@ export default {
|
|||
// Algorithm-Specific Fields for DSA secret keys:
|
||||
// - MPI of DSA secret exponent x.
|
||||
return 1;
|
||||
case 'ecdh':
|
||||
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.
|
||||
return 1;
|
||||
default:
|
||||
|
@ -185,6 +212,13 @@ export default {
|
|||
case 'ecdsa':
|
||||
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:
|
||||
throw new Error('Unknown algorithm.');
|
||||
}
|
||||
|
@ -210,14 +244,6 @@ export default {
|
|||
default:
|
||||
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.
|
||||
* @requires crypto
|
||||
* @requires enums
|
||||
* @requires type/kdf_params
|
||||
* @requires type/keyid
|
||||
* @requires type/mpi
|
||||
* @requires type/oid
|
||||
|
@ -35,6 +36,7 @@
|
|||
|
||||
import util from '../util.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_oid from '../type/oid.js';
|
||||
import enums from '../enums.js';
|
||||
|
@ -102,8 +104,10 @@ PublicKey.prototype.read = function (bytes) {
|
|||
var p = 0;
|
||||
|
||||
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();
|
||||
} else if (this.algorithm === 'ecdh' && i === 2) {
|
||||
this.mpi[i] = new type_kdf_params();
|
||||
} else {
|
||||
this.mpi[i] = new type_mpi();
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
* decrypt the message.
|
||||
* @requires crypto
|
||||
* @requires enums
|
||||
* @requires type/ecdh_symkey
|
||||
* @requires type/keyid
|
||||
* @requires type/mpi
|
||||
* @requires util
|
||||
|
@ -41,6 +42,7 @@
|
|||
|
||||
import type_keyid from '../type/keyid.js';
|
||||
import util from '../util.js';
|
||||
import type_ecdh_symkey from '../type/ecdh_symkey.js';
|
||||
import type_mpi from '../type/mpi.js';
|
||||
import enums from '../enums.js';
|
||||
import crypto from '../crypto';
|
||||
|
@ -88,6 +90,9 @@ PublicKeyEncryptedSessionKey.prototype.read = function (bytes) {
|
|||
case 'elgamal':
|
||||
return 2;
|
||||
|
||||
case 'ecdh':
|
||||
return 2;
|
||||
|
||||
default:
|
||||
throw new Error("Invalid algorithm.");
|
||||
}
|
||||
|
@ -96,7 +101,12 @@ PublicKeyEncryptedSessionKey.prototype.read = function (bytes) {
|
|||
this.encrypted = [];
|
||||
|
||||
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));
|
||||
this.encrypted.push(mpi);
|
||||
}
|
||||
|
@ -126,15 +136,21 @@ PublicKeyEncryptedSessionKey.prototype.encrypt = function (key) {
|
|||
var checksum = util.calc_checksum(this.sessionKey);
|
||||
data += util.Uint8Array2str(util.writeNumber(checksum, 2));
|
||||
|
||||
var mpi = new type_mpi();
|
||||
mpi.fromBytes(crypto.pkcs1.eme.encode(
|
||||
data,
|
||||
key.mpi[0].byteLength()));
|
||||
var mpi;
|
||||
if (this.publicKeyAlgorithm === 'ecdh') {
|
||||
mpi = util.str2Uint8Array(crypto.pkcs5.addPadding(data));
|
||||
} else {
|
||||
mpi = new type_mpi();
|
||||
mpi.fromBytes(crypto.pkcs1.eme.encode(
|
||||
data,
|
||||
key.mpi[0].byteLength()));
|
||||
}
|
||||
|
||||
this.encrypted = crypto.publicKeyEncrypt(
|
||||
this.publicKeyAlgorithm,
|
||||
key.mpi,
|
||||
mpi);
|
||||
mpi,
|
||||
key.fingerprint);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -149,11 +165,18 @@ PublicKeyEncryptedSessionKey.prototype.decrypt = function (key) {
|
|||
var result = crypto.publicKeyDecrypt(
|
||||
this.publicKeyAlgorithm,
|
||||
key.mpi,
|
||||
this.encrypted).toBytes();
|
||||
this.encrypted,
|
||||
key.fingerprint).toBytes();
|
||||
|
||||
var checksum = util.readNumber(util.str2Uint8Array(result.substr(result.length - 2)));
|
||||
|
||||
var decoded = crypto.pkcs1.eme.decode(result);
|
||||
var checksum;
|
||||
var decoded;
|
||||
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));
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user