Apply eslint to test/crypto folder (#1003)

This commit is contained in:
Ilya Chesnokov 2019-11-19 20:29:32 +07:00 committed by Daniel Huigens
parent bc16d157f0
commit 495fe1091c
18 changed files with 818 additions and 776 deletions

View File

@ -8,6 +8,10 @@ module.exports = {
"node": true "node": true
}, },
"plugins": [
"chai-friendly"
],
"globals": { // TODO are all these necessary? "globals": { // TODO are all these necessary?
"console": true, "console": true,
"Promise": true, "Promise": true,
@ -230,7 +234,6 @@ module.exports = {
"defaultAssignment": true "defaultAssignment": true
} }
], ],
"no-unused-expressions": "error",
"no-use-before-define": "off", "no-use-before-define": "off",
"no-useless-call": "error", "no-useless-call": "error",
"no-useless-computed-key": "error", "no-useless-computed-key": "error",
@ -335,10 +338,11 @@ module.exports = {
"no-trailing-spaces": 2, "no-trailing-spaces": 2,
"no-mixed-operators": [ 2, {"groups": [["&", "|", "^", "~", "<<", ">>", ">>>"], ["&&", "||"]]}], "no-mixed-operators": [ 2, {"groups": [["&", "|", "^", "~", "<<", ">>", ">>>"], ["&&", "||"]]}],
"no-use-before-define": [ 2, { "functions": false, "classes": true, "variables": false }], "no-use-before-define": [ 2, { "functions": false, "classes": true, "variables": false }],
"no-unused-expressions": [ 2, { "allowShortCircuit": true } ],
"no-constant-condition": [ 2, { "checkLoops": false } ], "no-constant-condition": [ 2, { "checkLoops": false } ],
"new-cap": [ 2, { "properties": false, "capIsNewExceptionPattern": "CMAC|CBC|OMAC|CTR", "newIsCapExceptionPattern": "type|hash*"}], "new-cap": [ 2, { "properties": false, "capIsNewExceptionPattern": "CMAC|CBC|OMAC|CTR", "newIsCapExceptionPattern": "type|hash*"}],
"max-lines": [ 2, { "max": 550, "skipBlankLines": true, "skipComments": true } ], "max-lines": [ 2, { "max": 550, "skipBlankLines": true, "skipComments": true } ],
"no-unused-expressions": 0,
"chai-friendly/no-unused-expressions": [ 2, { "allowShortCircuit": true } ],
// Custom warnings: // Custom warnings:
"no-console": 1, "no-console": 1,

View File

@ -184,7 +184,7 @@ module.exports = function(grunt) {
} }
}, },
eslint: { eslint: {
target: ['src/**/*.js', './Gruntfile.js', 'test/crypto/rsa.js'], target: ['src/**/*.js', './Gruntfile.js', './eslintrc.js', 'test/crypto/**/*.js'],
options: { options: {
configFile: '.eslintrc.js', configFile: '.eslintrc.js',
fix: !!grunt.option('fix') fix: !!grunt.option('fix')

6
npm-shrinkwrap.json generated
View File

@ -2567,6 +2567,12 @@
"pkg-dir": "^1.0.0" "pkg-dir": "^1.0.0"
} }
}, },
"eslint-plugin-chai-friendly": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-chai-friendly/-/eslint-plugin-chai-friendly-0.5.0.tgz",
"integrity": "sha512-Pxe6z8C9fP0pn2X2nGFU/b3GBOCM/5FVus1hsMwJsXP3R7RiXFl7g0ksJbsc0GxiLyidTW4mEFk77qsNn7Tk7g==",
"dev": true
},
"eslint-plugin-import": { "eslint-plugin-import": {
"version": "2.8.0", "version": "2.8.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz",

View File

@ -50,6 +50,7 @@
"eslint-config-airbnb": "^16.1.0", "eslint-config-airbnb": "^16.1.0",
"eslint-config-airbnb-base": "^12.1.0", "eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-import": "^2.8.0", "eslint-plugin-import": "^2.8.0",
"eslint-plugin-chai-friendly": "^0.5.0",
"grunt": "^1.0.3", "grunt": "^1.0.3",
"grunt-browserify": "^5.3.0", "grunt-browserify": "^5.3.0",
"grunt-contrib-clean": "~1.1.0", "grunt-contrib-clean": "~1.1.0",

View File

@ -2,7 +2,6 @@ const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp
const chai = require('chai'); const chai = require('chai');
const { util } = openpgp;
const { expect } = chai; const { expect } = chai;
describe('AES Rijndael cipher test with test vectors from ecb_tbl.txt', function() { describe('AES Rijndael cipher test with test vectors from ecb_tbl.txt', function() {

View File

@ -3,7 +3,6 @@ const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp
const chai = require('chai'); const chai = require('chai');
const { util } = openpgp; const { util } = openpgp;
const BFencrypt = openpgp.crypto.cipher.blowfish;
const { expect } = chai; const { expect } = chai;
it('Blowfish cipher test with test vectors from https://www.schneier.com/code/vectors.txt', function(done) { it('Blowfish cipher test with test vectors from https://www.schneier.com/code/vectors.txt', function(done) {

View File

@ -6,7 +6,7 @@ const { util } = openpgp;
const { expect } = chai; const { expect } = chai;
it('Twofish with test vectors from https://www.schneier.com/code/ecb_ival.txt', function(done) { it('Twofish with test vectors from https://www.schneier.com/code/ecb_ival.txt', function(done) {
function TFencrypt(block, key) { function tfencrypt(block, key) {
const tf = new openpgp.crypto.cipher.twofish(util.str_to_Uint8Array(key)); const tf = new openpgp.crypto.cipher.twofish(util.str_to_Uint8Array(key));
return tf.encrypt(block); return tf.encrypt(block);
@ -38,34 +38,34 @@ it('Twofish with test vectors from https://www.schneier.com/code/ecb_ival.txt',
blk = start_short; blk = start_short;
key = util.Uint8Array_to_str(start); key = util.Uint8Array_to_str(start);
ct = testvectors[0]; ct = testvectors[0];
res = util.Uint8Array_to_str(TFencrypt(blk,key)); res = util.Uint8Array_to_str(tfencrypt(blk,key));
exp = util.Uint8Array_to_str(ct); exp = util.Uint8Array_to_str(ct);
} else if (i === 1) { } else if (i === 1) {
blk = testvectors[0]; blk = testvectors[0];
key = util.Uint8Array_to_str(start); key = util.Uint8Array_to_str(start);
ct = testvectors[1]; ct = testvectors[1];
res = util.Uint8Array_to_str(TFencrypt(blk,key)); res = util.Uint8Array_to_str(tfencrypt(blk,key));
exp = util.Uint8Array_to_str(ct); exp = util.Uint8Array_to_str(ct);
} else if (i === 2) { } else if (i === 2) {
blk = testvectors[i - 1]; blk = testvectors[i - 1];
key = util.Uint8Array_to_str(testvectors[i - 2].concat(start_short)); key = util.Uint8Array_to_str(testvectors[i - 2].concat(start_short));
ct = testvectors[i]; ct = testvectors[i];
res = util.Uint8Array_to_str(TFencrypt(blk,key)); res = util.Uint8Array_to_str(tfencrypt(blk,key));
exp = util.Uint8Array_to_str(ct); exp = util.Uint8Array_to_str(ct);
} else if (i < 10 || i > 46) { } else if (i < 10 || i > 46) {
blk = testvectors[i - 1]; blk = testvectors[i - 1];
key = util.Uint8Array_to_str(testvectors[i - 2].concat(testvectors[i - 3])); key = util.Uint8Array_to_str(testvectors[i - 2].concat(testvectors[i - 3]));
ct = testvectors[i]; ct = testvectors[i];
res = util.Uint8Array_to_str(TFencrypt(blk,key)); res = util.Uint8Array_to_str(tfencrypt(blk,key));
exp = util.Uint8Array_to_str(ct); exp = util.Uint8Array_to_str(ct);
} else { } else {
testvectors[i] = TFencrypt(testvectors[i-1],util.Uint8Array_to_str(testvectors[i-2].concat(testvectors[i-3]))); testvectors[i] = tfencrypt(testvectors[i - 1],util.Uint8Array_to_str(testvectors[i - 2].concat(testvectors[i - 3])));
continue; continue;
} }
expect(res, 'vector with block ' + util.Uint8Array_to_hex(blk) + expect(res, 'vector with block ' + util.Uint8Array_to_hex(blk) +
' with key ' + util.str_to_hex(key) + ' with key ' + util.str_to_hex(key) +
' should be ' + util.Uint8Array_to_hex(ct) + ' should be ' + util.Uint8Array_to_hex(ct) +
' but is ' + util.Uint8Array_to_hex(TFencrypt(blk,key))).to.equal(exp); ' but is ' + util.Uint8Array_to_hex(tfencrypt(blk,key))).to.equal(exp);
} }
done(); done();
}); });

View File

@ -11,7 +11,7 @@ const expect = chai.expect;
function testAESEAX() { function testAESEAX() {
it('Passes all test vectors', async function() { it('Passes all test vectors', async function() {
var vectors = [ const vectors = [
// From http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf ... // From http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf ...
{ {
msg: "", msg: "",
@ -82,17 +82,17 @@ function testAESEAX() {
nonce: "22E7ADD93CFC6393C57EC0B3C17D6B44", nonce: "22E7ADD93CFC6393C57EC0B3C17D6B44",
header: "126735FCC320D25A", header: "126735FCC320D25A",
ct: "CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E" ct: "CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E"
}, }
]; ];
const cipher = 'aes128'; const cipher = 'aes128';
for(const [i, vec] of vectors.entries()) { await Promise.all(vectors.map(async vec => {
const keyBytes = openpgp.util.hex_to_Uint8Array(vec.key), const keyBytes = openpgp.util.hex_to_Uint8Array(vec.key);
msgBytes = openpgp.util.hex_to_Uint8Array(vec.msg), const msgBytes = openpgp.util.hex_to_Uint8Array(vec.msg);
nonceBytes = openpgp.util.hex_to_Uint8Array(vec.nonce), const nonceBytes = openpgp.util.hex_to_Uint8Array(vec.nonce);
headerBytes = openpgp.util.hex_to_Uint8Array(vec.header), const headerBytes = openpgp.util.hex_to_Uint8Array(vec.header);
ctBytes = openpgp.util.hex_to_Uint8Array(vec.ct); const ctBytes = openpgp.util.hex_to_Uint8Array(vec.ct);
const eax = await openpgp.crypto.eax(cipher, keyBytes); const eax = await openpgp.crypto.eax(cipher, keyBytes);
@ -108,7 +108,7 @@ function testAESEAX() {
ct = await eax.encrypt(msgBytes, nonceBytes, headerBytes); ct = await eax.encrypt(msgBytes, nonceBytes, headerBytes);
ct[2] ^= 8; ct[2] ^= 8;
pt = eax.decrypt(ct, nonceBytes, headerBytes); pt = eax.decrypt(ct, nonceBytes, headerBytes);
await expect(pt).to.eventually.be.rejectedWith('Authentication tag mismatch') await expect(pt).to.eventually.be.rejectedWith('Authentication tag mismatch');
// testing without additional data // testing without additional data
ct = await eax.encrypt(msgBytes, nonceBytes, new Uint8Array()); ct = await eax.encrypt(msgBytes, nonceBytes, new Uint8Array());
@ -119,7 +119,7 @@ function testAESEAX() {
ct = await eax.encrypt(msgBytes, nonceBytes, openpgp.util.concatUint8Array([headerBytes, headerBytes, headerBytes])); ct = await eax.encrypt(msgBytes, nonceBytes, openpgp.util.concatUint8Array([headerBytes, headerBytes, headerBytes]));
pt = await eax.decrypt(ct, nonceBytes, openpgp.util.concatUint8Array([headerBytes, headerBytes, headerBytes])); pt = await eax.decrypt(ct, nonceBytes, openpgp.util.concatUint8Array([headerBytes, headerBytes, headerBytes]));
expect(openpgp.util.Uint8Array_to_hex(pt)).to.equal(vec.msg.toLowerCase()); expect(openpgp.util.Uint8Array_to_hex(pt)).to.equal(vec.msg.toLowerCase());
} }));
}); });
} }

283
test/crypto/ecdh.js Normal file
View File

@ -0,0 +1,283 @@
const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../../dist/openpgp');
const chai = require('chai');
const elliptic_data = require('./elliptic_data');
chai.use(require('chai-as-promised'));
const expect = chai.expect;
const key_data = elliptic_data.key_data;
/* eslint-disable no-invalid-this */
describe('ECDH key exchange @lightweight', function () {
const elliptic_curves = openpgp.crypto.publicKey.elliptic;
const decrypt_message = function (oid, hash, cipher, priv, pub, ephemeral, data, fingerprint) {
if (openpgp.util.isString(data)) {
data = openpgp.util.str_to_Uint8Array(data);
} else {
data = new Uint8Array(data);
}
return Promise.resolve().then(() => {
const curve = new elliptic_curves.Curve(oid);
return elliptic_curves.ecdh.decrypt(
new openpgp.OID(curve.oid),
cipher,
hash,
new Uint8Array(ephemeral),
data,
new Uint8Array(pub),
new Uint8Array(priv),
new Uint8Array(fingerprint)
);
});
};
const secp256k1_value = new Uint8Array([
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]);
const secp256k1_point = new Uint8Array([
0x04,
0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC,
0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07,
0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9,
0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,
0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65,
0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, 0xA8,
0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19,
0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, 0xB8
]);
const secp256k1_invalid_point = new Uint8Array([
0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]);
const secp256k1_data = new Uint8Array([
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]);
it('Invalid curve oid', function (done) {
expect(decrypt_message(
'', 2, 7, [], [], [], [], []
)).to.be.rejectedWith(Error, /Not valid curve/).notify(done);
});
it('Invalid ephemeral key', function (done) {
if (!openpgp.config.use_indutny_elliptic && !openpgp.util.getNodeCrypto()) {
this.skip();
}
expect(decrypt_message(
'secp256k1', 2, 7, [], [], [], [], []
)).to.be.rejectedWith(Error, /Private key is not valid for specified curve|Unknown point format/).notify(done);
});
it('Invalid elliptic public key', function (done) {
if (!openpgp.config.use_indutny_elliptic && !openpgp.util.getNodeCrypto()) {
this.skip();
}
expect(decrypt_message(
'secp256k1', 2, 7, secp256k1_value, secp256k1_point, secp256k1_invalid_point, secp256k1_data, []
)).to.be.rejectedWith(Error, /Public key is not valid for specified curve|Failed to translate Buffer to a EC_POINT|Invalid elliptic public key/).notify(done);
});
it('Invalid key data integrity', function (done) {
if (!openpgp.config.use_indutny_elliptic && !openpgp.util.getNodeCrypto()) {
this.skip();
}
expect(decrypt_message(
'secp256k1', 2, 7, secp256k1_value, secp256k1_point, secp256k1_point, secp256k1_data, []
)).to.be.rejectedWith(Error, /Key Data Integrity failed/).notify(done);
});
const Q1 = new Uint8Array([
64,
48, 226, 162, 114, 194, 194, 67, 214,
199, 10, 173, 22, 216, 240, 197, 202,
114, 49, 127, 107, 152, 58, 119, 48,
234, 194, 192, 66, 53, 165, 137, 93
]);
const d1 = new Uint8Array([
65, 200, 132, 198, 77, 86, 126, 196,
247, 169, 156, 201, 32, 52, 3, 198,
127, 144, 139, 47, 153, 239, 64, 235,
61, 7, 17, 214, 64, 211, 215, 80
]);
const Q2 = new Uint8Array([
64,
154, 115, 36, 108, 33, 153, 64, 184,
25, 139, 67, 25, 178, 194, 227, 53,
254, 40, 101, 213, 28, 121, 154, 62,
27, 99, 92, 126, 33, 223, 122, 91
]);
const d2 = new Uint8Array([
123, 99, 163, 24, 201, 87, 0, 9,
204, 21, 154, 5, 5, 5, 127, 157,
237, 95, 76, 117, 89, 250, 64, 178,
72, 69, 69, 58, 89, 228, 113, 112
]);
const fingerprint1 = new Uint8Array([
177, 183,
116, 123, 76, 133, 245, 212, 151, 243, 236,
71, 245, 86, 3, 168, 101, 74, 209, 105
]);
const fingerprint2 = new Uint8Array([
177, 83,
123, 123, 76, 133, 245, 212, 151, 243, 236,
71, 245, 86, 3, 168, 101, 74, 209, 105
]);
async function genPublicEphemeralKey(curve, Q, fingerprint) {
const curveObj = new openpgp.crypto.publicKey.elliptic.Curve(curve);
const oid = new openpgp.OID(curveObj.oid);
const { publicKey: V, sharedKey } = await openpgp.crypto.publicKey.elliptic.ecdh.genPublicEphemeralKey(
curveObj, Q
);
let cipher_algo = curveObj.cipher;
const hash_algo = curveObj.hash;
const param = openpgp.crypto.publicKey.elliptic.ecdh.buildEcdhParam(
openpgp.enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint
);
cipher_algo = openpgp.enums.read(openpgp.enums.symmetric, cipher_algo);
const Z = await openpgp.crypto.publicKey.elliptic.ecdh.kdf(
hash_algo, sharedKey, openpgp.crypto.cipher[cipher_algo].keySize, param, curveObj, false
);
return { V, Z };
}
async function genPrivateEphemeralKey(curve, V, Q, d, fingerprint) {
const curveObj = new openpgp.crypto.publicKey.elliptic.Curve(curve);
const oid = new openpgp.OID(curveObj.oid);
const { sharedKey } = await openpgp.crypto.publicKey.elliptic.ecdh.genPrivateEphemeralKey(
curveObj, V, Q, d
);
let cipher_algo = curveObj.cipher;
const hash_algo = curveObj.hash;
const param = openpgp.crypto.publicKey.elliptic.ecdh.buildEcdhParam(
openpgp.enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint
);
cipher_algo = openpgp.enums.read(openpgp.enums.symmetric, cipher_algo);
const Z = await openpgp.crypto.publicKey.elliptic.ecdh.kdf(
hash_algo, sharedKey, openpgp.crypto.cipher[cipher_algo].keySize, param, curveObj, false
);
return Z;
}
async function genPrivateEphemeralKeySpecific(fun, curve, V, Q, d, fingerprint) {
const curveObj = new openpgp.crypto.publicKey.elliptic.Curve(curve);
const oid = new openpgp.OID(curveObj.oid);
let result;
switch (fun) {
case 'webPrivateEphemeralKey': {
result = await openpgp.crypto.publicKey.elliptic.ecdh[fun](
curveObj, V, Q, d
);
break;
}
case 'nodePrivateEphemeralKey':
case 'ellipticPrivateEphemeralKey': {
result = await openpgp.crypto.publicKey.elliptic.ecdh[fun](
curveObj, V, d
);
break;
}
}
const sharedKey = result.sharedKey;
let cipher_algo = curveObj.cipher;
const hash_algo = curveObj.hash;
const param = openpgp.crypto.publicKey.elliptic.ecdh.buildEcdhParam(
openpgp.enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint
);
cipher_algo = openpgp.enums.read(openpgp.enums.symmetric, cipher_algo);
const Z = await openpgp.crypto.publicKey.elliptic.ecdh.kdf(
hash_algo, sharedKey, openpgp.crypto.cipher[cipher_algo].keySize, param, curveObj, false
);
return Z;
}
describe('ECDHE key generation', function () {
it('Invalid curve', function (done) {
if (!openpgp.config.use_indutny_elliptic && !openpgp.util.getNodeCrypto()) {
this.skip();
}
expect(genPublicEphemeralKey("secp256k1", Q1, fingerprint1)
).to.be.rejectedWith(Error, /Public key is not valid for specified curve|Failed to translate Buffer to a EC_POINT|Unknown point format/).notify(done);
});
it('Invalid public part of ephemeral key and private key', async function () {
const ECDHE_VZ1 = await genPublicEphemeralKey("curve25519", Q1, fingerprint1);
const ECDHE_Z12 = await genPrivateEphemeralKey("curve25519", ECDHE_VZ1.V, Q2, d2, fingerprint1);
expect(Array.from(ECDHE_Z12).join(' ') === Array.from(ECDHE_VZ1.Z).join(' ')).to.be.false;
});
it('Invalid fingerprint', async function () {
const ECDHE_VZ2 = await genPublicEphemeralKey("curve25519", Q2, fingerprint1);
const ECDHE_Z2 = await genPrivateEphemeralKey("curve25519", ECDHE_VZ2.V, Q2, d2, fingerprint2);
expect(Array.from(ECDHE_Z2).join(' ') === Array.from(ECDHE_VZ2.Z).join(' ')).to.be.false;
});
it('Different keys', async function () {
const ECDHE_VZ1 = await genPublicEphemeralKey("curve25519", Q1, fingerprint1);
const ECDHE_VZ2 = await genPublicEphemeralKey("curve25519", Q2, fingerprint1);
const ECDHE_Z1 = await genPrivateEphemeralKey("curve25519", ECDHE_VZ1.V, Q1, d1, fingerprint1);
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_VZ2.Z).join(' ')).to.be.false;
});
it('Successful exchange curve25519', async function () {
const ECDHE_VZ1 = await genPublicEphemeralKey("curve25519", Q1, fingerprint1);
const ECDHE_Z1 = await genPrivateEphemeralKey("curve25519", ECDHE_VZ1.V, Q1, d1, fingerprint1);
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_VZ1.Z).join(' ')).to.be.true;
});
it('Successful exchange NIST P256', async function () {
const ECDHE_VZ1 = await genPublicEphemeralKey("p256", key_data.p256.pub, fingerprint1);
const ECDHE_Z1 = await genPrivateEphemeralKey("p256", ECDHE_VZ1.V, key_data.p256.pub, key_data.p256.priv, fingerprint1);
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_VZ1.Z).join(' ')).to.be.true;
});
it('Successful exchange NIST P384', async function () {
const ECDHE_VZ1 = await genPublicEphemeralKey("p384", key_data.p384.pub, fingerprint1);
const ECDHE_Z1 = await genPrivateEphemeralKey("p384", ECDHE_VZ1.V, key_data.p384.pub, key_data.p384.priv, fingerprint1);
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_VZ1.Z).join(' ')).to.be.true;
});
it('Successful exchange NIST P521', async function () {
const ECDHE_VZ1 = await genPublicEphemeralKey("p521", key_data.p521.pub, fingerprint1);
const ECDHE_Z1 = await genPrivateEphemeralKey("p521", ECDHE_VZ1.V, key_data.p521.pub, key_data.p521.priv, fingerprint1);
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_VZ1.Z).join(' ')).to.be.true;
});
it('Comparing keys derived using webCrypto and elliptic', async function () {
const names = ["p256", "p384", "p521"];
if (!openpgp.util.getWebCrypto() || !openpgp.config.use_indutny_elliptic) {
// eslint-disable-next-line no-invalid-this
this.skip();
}
return Promise.all(names.map(async function (name) {
const curve = new elliptic_curves.Curve(name);
try {
await window.crypto.subtle.generateKey({
name: "ECDSA",
namedCurve: curve.web.web
}, false, ["sign", "verify"]);
} catch (err) {
openpgp.util.print_debug_error(err);
return;
}
const ECDHE_VZ1 = await genPublicEphemeralKey(name, key_data[name].pub, fingerprint1);
const ECDHE_Z1 = await genPrivateEphemeralKeySpecific('ellipticPrivateEphemeralKey', name, ECDHE_VZ1.V, key_data[name].pub, key_data[name].priv, fingerprint1);
const ECDHE_Z2 = await genPrivateEphemeralKeySpecific('webPrivateEphemeralKey', name, ECDHE_VZ1.V, key_data[name].pub, key_data[name].priv, fingerprint1);
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_VZ1.Z).join(' ')).to.be.true;
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_Z2).join(' ')).to.be.true;
}));
});
it('Comparing keys derived using nodeCrypto and elliptic', async function () {
const names = ["p256", "p384", "p521"];
if (!openpgp.util.getNodeCrypto() || !openpgp.config.use_indutny_elliptic) {
// eslint-disable-next-line no-invalid-this
this.skip();
}
return Promise.all(names.map(async function (name) {
const ECDHE_VZ1 = await genPublicEphemeralKey(name, key_data[name].pub, fingerprint1);
const ECDHE_Z1 = await genPrivateEphemeralKeySpecific('ellipticPrivateEphemeralKey', name, ECDHE_VZ1.V, key_data[name].pub, key_data[name].priv, fingerprint1);
const ECDHE_Z2 = await genPrivateEphemeralKeySpecific('nodePrivateEphemeralKey', name, ECDHE_VZ1.V, key_data[name].pub, key_data[name].priv, fingerprint1);
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_VZ1.Z).join(' ')).to.be.true;
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_Z2).join(' ')).to.be.true;
}));
});
});
});

View File

@ -1,107 +1,16 @@
const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../../dist/openpgp'); const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../../dist/openpgp');
const chai = require('chai'); const chai = require('chai');
const elliptic_data = require('./elliptic_data');
chai.use(require('chai-as-promised')); chai.use(require('chai-as-promised'));
const expect = chai.expect; const expect = chai.expect;
const key_data = elliptic_data.key_data;
/* eslint-disable no-invalid-this */
describe('Elliptic Curve Cryptography @lightweight', function () { describe('Elliptic Curve Cryptography @lightweight', function () {
const elliptic_curves = openpgp.crypto.publicKey.elliptic; const elliptic_curves = openpgp.crypto.publicKey.elliptic;
const key_data = {
p256: {
priv: new Uint8Array([
0x2B, 0x48, 0x2B, 0xE9, 0x88, 0x74, 0xE9, 0x49,
0x1F, 0x89, 0xCC, 0xFF, 0x0A, 0x26, 0x05, 0xA2,
0x3C, 0x2A, 0x35, 0x25, 0x26, 0x11, 0xD7, 0xEA,
0xA1, 0xED, 0x29, 0x95, 0xB5, 0xE1, 0x5F, 0x1D
]),
pub: new Uint8Array([
0x04,
0x80, 0x2C, 0x40, 0x76, 0x31, 0x20, 0xB6, 0x9B,
0x48, 0x3B, 0x05, 0xEB, 0x6C, 0x1E, 0x3F, 0x49,
0x84, 0xF7, 0xD2, 0xAD, 0x16, 0xA1, 0x6F, 0x62,
0xFD, 0xCA, 0xEC, 0xB4, 0xA0, 0xBD, 0x4C, 0x1A,
0x6F, 0xAA, 0xE7, 0xFD, 0xC4, 0x7D, 0x89, 0xCC,
0x06, 0xCA, 0xFE, 0xAE, 0xCD, 0x0E, 0x9E, 0x62,
0x57, 0xA4, 0xC3, 0xE7, 0x5E, 0x69, 0x10, 0xEE,
0x67, 0xC2, 0x09, 0xF9, 0xEF, 0xE7, 0x9E, 0x56
])
},
p384: {
priv: new Uint8Array([
0xB5, 0x38, 0xDA, 0xF3, 0x77, 0x58, 0x3F, 0x94,
0x5B, 0xC2, 0xCA, 0xC6, 0xA9, 0xFC, 0xAA, 0x3F,
0x97, 0xB0, 0x54, 0x26, 0x10, 0xB4, 0xEC, 0x2A,
0xA7, 0xC1, 0xA3, 0x4B, 0xC0, 0xBD, 0xFE, 0x3E,
0xF1, 0xBE, 0x76, 0xCB, 0xE8, 0xAB, 0x3B, 0xBD,
0xB6, 0x84, 0xC7, 0x8B, 0x91, 0x2F, 0x76, 0x8B
]),
pub: new Uint8Array([
0x04,
0x44, 0x83, 0xA0, 0x3E, 0x5B, 0x0A, 0x0D, 0x9B,
0xA0, 0x06, 0xDF, 0x38, 0xC7, 0x64, 0xCD, 0x62,
0x7D, 0x5E, 0x3D, 0x3B, 0x50, 0xF5, 0x06, 0xC7,
0xF7, 0x9B, 0xF0, 0xDE, 0xB1, 0x0C, 0x64, 0x74,
0x0D, 0x03, 0x67, 0x24, 0xA0, 0xFF, 0xD1, 0x3D,
0x03, 0x96, 0x48, 0xE7, 0x73, 0x5E, 0xF1, 0xC0,
0x62, 0xCC, 0x33, 0x5A, 0x2A, 0x66, 0xA7, 0xAB,
0xCA, 0x77, 0x52, 0xB8, 0xCD, 0xB5, 0x91, 0x16,
0xAF, 0x42, 0xBB, 0x79, 0x0A, 0x59, 0x51, 0x68,
0x8E, 0xEA, 0x32, 0x7D, 0x4A, 0x4A, 0xBB, 0x26,
0x13, 0xFB, 0x95, 0xC0, 0xB1, 0xA4, 0x54, 0xCA,
0xFA, 0x85, 0x8A, 0x4B, 0x58, 0x7C, 0x61, 0x39])
},
p521: {
priv: new Uint8Array([
0x00, 0xBB, 0x35, 0x27, 0xBC, 0xD6, 0x7E, 0x35,
0xD5, 0xC5, 0x99, 0xC9, 0xB4, 0x6C, 0xEE, 0xDE,
0x79, 0x2D, 0x77, 0xBD, 0x0A, 0x08, 0x9A, 0xC2,
0x21, 0xF8, 0x35, 0x1C, 0x49, 0x5C, 0x40, 0x11,
0xAC, 0x95, 0x2A, 0xEE, 0x91, 0x3A, 0x60, 0x5A,
0x25, 0x5A, 0x95, 0x38, 0xDC, 0xEB, 0x59, 0x8E,
0x33, 0xAD, 0xC0, 0x0B, 0x56, 0xB1, 0x06, 0x8C,
0x57, 0x48, 0xA3, 0x73, 0xDB, 0xE0, 0x19, 0x50,
0x2E, 0x79
]),
pub: new Uint8Array([
0x04,
0x01, 0x0D, 0xD5, 0xCA, 0xD8, 0xB0, 0xEF, 0x9F,
0x2B, 0x7E, 0x58, 0x99, 0xDE, 0x05, 0xF6, 0xF6,
0x64, 0x6B, 0xCD, 0x59, 0x2E, 0x39, 0xB8, 0x82,
0xB3, 0x13, 0xE6, 0x7D, 0x50, 0x85, 0xC3, 0xFA,
0x93, 0xA5, 0x3F, 0x92, 0x85, 0x42, 0x36, 0xC0,
0x83, 0xC9, 0xA4, 0x38, 0xB3, 0xD1, 0x99, 0xDA,
0xE1, 0x02, 0x37, 0x7A, 0x3A, 0xC2, 0xB4, 0x55,
0xEC, 0x1C, 0x0F, 0x00, 0x97, 0xFC, 0x75, 0x93,
0xFE, 0x87, 0x00, 0x7D, 0xBE, 0x1A, 0xF5, 0xF9,
0x57, 0x5C, 0xF2, 0x50, 0x2D, 0x14, 0x32, 0xEE,
0x9B, 0xBE, 0xB3, 0x0E, 0x12, 0x2F, 0xF8, 0x85,
0x11, 0x1A, 0x4F, 0x88, 0x50, 0xA4, 0xDB, 0x37,
0xA6, 0x53, 0x5C, 0xB7, 0x87, 0xA6, 0x06, 0x21,
0x15, 0xCC, 0x12, 0xC0, 0x1C, 0x83, 0x6F, 0x7B,
0x5A, 0x8A, 0x36, 0x4E, 0x46, 0x9E, 0x54, 0x3F,
0xE2, 0xF7, 0xED, 0x63, 0xC9, 0x92, 0xA4, 0x38,
0x2B, 0x9C, 0xE2, 0xB7])
},
secp256k1: {
priv: new Uint8Array([
0x9E, 0xB0, 0x30, 0xD6, 0xE1, 0xCE, 0xAA, 0x0B,
0x7B, 0x8F, 0xDE, 0x5D, 0x91, 0x4D, 0xDC, 0xA0,
0xAD, 0x05, 0xAB, 0x8F, 0x87, 0x9B, 0x57, 0x48,
0xAE, 0x8A, 0xE0, 0xF9, 0x39, 0xBD, 0x24, 0x00
]),
pub: new Uint8Array([
0x04,
0xA8, 0x02, 0x35, 0x2C, 0xB7, 0x24, 0x95, 0x51,
0x0A, 0x65, 0x26, 0x7D, 0xDF, 0xEA, 0x64, 0xB3,
0xA8, 0xE1, 0x4F, 0xDD, 0x12, 0x84, 0x7E, 0x59,
0xDB, 0x81, 0x0F, 0x89, 0xED, 0xFB, 0x29, 0xFB,
0x07, 0x60, 0x29, 0x7D, 0x39, 0x8F, 0xB8, 0x68,
0xF0, 0xFD, 0xA6, 0x67, 0x83, 0x55, 0x75, 0x7D,
0xB8, 0xFD, 0x0B, 0xDF, 0x76, 0xCE, 0xBC, 0x95,
0x4B, 0x92, 0x26, 0xFC, 0xAA, 0x7A, 0x7C, 0x3F])
}
};
const signature_data = { const signature_data = {
priv: new Uint8Array([ priv: new Uint8Array([
0x14, 0x2B, 0xE2, 0xB7, 0x4D, 0xBD, 0x1B, 0x22, 0x14, 0x2B, 0xE2, 0xB7, 0x4D, 0xBD, 0x1B, 0x22,
@ -118,7 +27,8 @@ describe('Elliptic Curve Cryptography @lightweight', function () {
0xDA, 0x4E, 0x8F, 0xCE, 0x04, 0xBE, 0xE2, 0xC3, 0xDA, 0x4E, 0x8F, 0xCE, 0x04, 0xBE, 0xE2, 0xC3,
0x82, 0x0B, 0x21, 0x4C, 0xBC, 0xED, 0x0E, 0xE2, 0x82, 0x0B, 0x21, 0x4C, 0xBC, 0xED, 0x0E, 0xE2,
0xF1, 0x14, 0x33, 0x9A, 0x86, 0x5F, 0xC6, 0xF9, 0xF1, 0x14, 0x33, 0x9A, 0x86, 0x5F, 0xC6, 0xF9,
0x8E, 0x95, 0x24, 0x10, 0x1F, 0x0F, 0x13, 0xE4]), 0x8E, 0x95, 0x24, 0x10, 0x1F, 0x0F, 0x13, 0xE4
]),
message: new Uint8Array([ message: new Uint8Array([
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
@ -146,9 +56,12 @@ describe('Elliptic Curve Cryptography @lightweight', function () {
}; };
describe('Basic Operations', function () { describe('Basic Operations', function () {
it('Creating curve from name or oid', function (done) { it('Creating curve from name or oid', function (done) {
for (let name_or_oid in openpgp.enums.curves) { Object.keys(openpgp.enums.curve).forEach(function(name_or_oid) {
expect(new elliptic_curves.Curve(name_or_oid)).to.exist; expect(new elliptic_curves.Curve(name_or_oid)).to.exist;
} });
Object.values(openpgp.enums.curve).forEach(function(name_or_oid) {
expect(new elliptic_curves.Curve(name_or_oid)).to.exist;
});
done(); done();
}); });
it('Creating KeyPair', function () { it('Creating KeyPair', function () {
@ -211,12 +124,6 @@ describe('Elliptic Curve Cryptography @lightweight', function () {
new elliptic_curves.Curve(oid), { r: new Uint8Array(r), s: new Uint8Array(s) }, await openpgp.crypto.hash.digest(hash, message), new Uint8Array(pub) new elliptic_curves.Curve(oid), { r: new Uint8Array(r), s: new Uint8Array(s) }, await openpgp.crypto.hash.digest(hash, message), new Uint8Array(pub)
); );
}; };
const secp256k1_dummy_value = new Uint8Array([
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]);
const secp256k1_point = new Uint8Array([ const secp256k1_point = new Uint8Array([
0x04, 0x04,
0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC,
@ -226,7 +133,8 @@ describe('Elliptic Curve Cryptography @lightweight', function () {
0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65, 0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65,
0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, 0xA8, 0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, 0xA8,
0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19, 0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19,
0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, 0xB8]); 0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, 0xB8
]);
const secp256k1_invalid_point = new Uint8Array([ const secp256k1_invalid_point = new Uint8Array([
0x04, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -236,13 +144,15 @@ describe('Elliptic Curve Cryptography @lightweight', function () {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]);
const secp256k1_invalid_point_format = new Uint8Array([ const secp256k1_invalid_point_format = new Uint8Array([
0x04, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]);
it('Invalid curve oid', function () { it('Invalid curve oid', function () {
return Promise.all([ return Promise.all([
expect(verify_signature( expect(verify_signature(
@ -338,267 +248,4 @@ describe('Elliptic Curve Cryptography @lightweight', function () {
}); });
}); });
}); });
describe('ECDH key exchange', function () {
const decrypt_message = function (oid, hash, cipher, priv, pub, ephemeral, data, fingerprint) {
if (openpgp.util.isString(data)) {
data = openpgp.util.str_to_Uint8Array(data);
} else {
data = new Uint8Array(data);
}
return Promise.resolve().then(() => {
const curve = new elliptic_curves.Curve(oid);
return elliptic_curves.ecdh.decrypt(
new openpgp.OID(curve.oid),
cipher,
hash,
new Uint8Array(ephemeral),
data,
new Uint8Array(pub),
new Uint8Array(priv),
new Uint8Array(fingerprint)
);
});
};
const secp256k1_value = new Uint8Array([
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]);
const secp256k1_point = new Uint8Array([
0x04,
0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC,
0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07,
0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9,
0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,
0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65,
0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, 0xA8,
0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19,
0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, 0xB8]);
const secp256k1_invalid_point = new Uint8Array([
0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
const secp256k1_data = new Uint8Array([
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]);
it('Invalid curve oid', function (done) {
expect(decrypt_message(
'', 2, 7, [], [], [], [], []
)).to.be.rejectedWith(Error, /Not valid curve/).notify(done);
});
it('Invalid ephemeral key', function (done) {
if (!openpgp.config.use_indutny_elliptic && !openpgp.util.getNodeCrypto()) {
this.skip();
}
expect(decrypt_message(
'secp256k1', 2, 7, [], [], [], [], []
)).to.be.rejectedWith(Error, /Private key is not valid for specified curve|Unknown point format/).notify(done);
});
it('Invalid elliptic public key', function (done) {
if (!openpgp.config.use_indutny_elliptic && !openpgp.util.getNodeCrypto()) {
this.skip();
}
expect(decrypt_message(
'secp256k1', 2, 7, secp256k1_value, secp256k1_point, secp256k1_invalid_point, secp256k1_data, []
)).to.be.rejectedWith(Error, /Public key is not valid for specified curve|Failed to translate Buffer to a EC_POINT|Invalid elliptic public key/).notify(done);
});
it('Invalid key data integrity', function (done) {
if (!openpgp.config.use_indutny_elliptic && !openpgp.util.getNodeCrypto()) {
this.skip();
}
expect(decrypt_message(
'secp256k1', 2, 7, secp256k1_value, secp256k1_point, secp256k1_point, secp256k1_data, []
)).to.be.rejectedWith(Error, /Key Data Integrity failed/).notify(done);
});
});
const Q1 = new Uint8Array([
64,
48, 226, 162, 114, 194, 194, 67, 214,
199, 10, 173, 22, 216, 240, 197, 202,
114, 49, 127, 107, 152, 58, 119, 48,
234, 194, 192, 66, 53, 165, 137, 93 ]);
const d1 = new Uint8Array ([
65, 200, 132, 198, 77, 86, 126, 196,
247, 169, 156, 201, 32, 52, 3, 198,
127, 144, 139, 47, 153, 239, 64, 235,
61, 7, 17, 214, 64, 211, 215, 80 ]);
const Q2 = new Uint8Array([
64,
154, 115, 36, 108, 33, 153, 64, 184,
25, 139, 67, 25, 178, 194, 227, 53,
254, 40, 101, 213, 28, 121, 154, 62,
27, 99, 92, 126, 33, 223, 122, 91 ]);
const d2 = new Uint8Array([
123, 99, 163, 24, 201, 87, 0, 9,
204, 21, 154, 5, 5, 5, 127, 157,
237, 95, 76, 117, 89, 250, 64, 178,
72, 69, 69, 58, 89, 228, 113, 112 ]);
const fingerprint1 = new Uint8Array([
177, 183,
116, 123, 76, 133, 245, 212, 151, 243, 236,
71, 245, 86, 3, 168, 101, 74, 209, 105 ]);
const fingerprint2 = new Uint8Array([
177, 83,
123, 123, 76, 133, 245, 212, 151, 243, 236,
71, 245, 86, 3, 168, 101, 74, 209, 105 ]);
async function genPublicEphemeralKey(curve, Q, fingerprint) {
const curveObj = new openpgp.crypto.publicKey.elliptic.Curve(curve);
const oid = new openpgp.OID(curveObj.oid);
const { publicKey: V, sharedKey } = await openpgp.crypto.publicKey.elliptic.ecdh.genPublicEphemeralKey(
curveObj, Q
);
let cipher_algo = curveObj.cipher;
const hash_algo = curveObj.hash;
const param = openpgp.crypto.publicKey.elliptic.ecdh.buildEcdhParam(
openpgp.enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint
);
cipher_algo = openpgp.enums.read(openpgp.enums.symmetric, cipher_algo);
const Z = await openpgp.crypto.publicKey.elliptic.ecdh.kdf(
hash_algo, sharedKey, openpgp.crypto.cipher[cipher_algo].keySize, param, curveObj, false
);
return { V, Z };
}
async function genPrivateEphemeralKey(curve, V, Q, d, fingerprint) {
const curveObj = new openpgp.crypto.publicKey.elliptic.Curve(curve);
const oid = new openpgp.OID(curveObj.oid);
const { sharedKey } = await openpgp.crypto.publicKey.elliptic.ecdh.genPrivateEphemeralKey(
curveObj, V, Q, d
);
let cipher_algo = curveObj.cipher;
const hash_algo = curveObj.hash;
const param = openpgp.crypto.publicKey.elliptic.ecdh.buildEcdhParam(
openpgp.enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint
);
cipher_algo = openpgp.enums.read(openpgp.enums.symmetric, cipher_algo);
const Z = await openpgp.crypto.publicKey.elliptic.ecdh.kdf(
hash_algo, sharedKey, openpgp.crypto.cipher[cipher_algo].keySize, param, curveObj, false
);
return Z;
}
async function genPrivateEphemeralKeySpecific(fun, curve, V, Q, d, fingerprint) {
const curveObj = new openpgp.crypto.publicKey.elliptic.Curve(curve);
const oid = new openpgp.OID(curveObj.oid);
let result;
switch (fun) {
case 'webPrivateEphemeralKey': {
result = await openpgp.crypto.publicKey.elliptic.ecdh[fun](
curveObj, V, Q, d
);
break;
}
case 'nodePrivateEphemeralKey':
case 'ellipticPrivateEphemeralKey': {
result = await openpgp.crypto.publicKey.elliptic.ecdh[fun](
curveObj, V, d
);
break;
}
}
const sharedKey = result.sharedKey;
let cipher_algo = curveObj.cipher;
const hash_algo = curveObj.hash;
const param = openpgp.crypto.publicKey.elliptic.ecdh.buildEcdhParam(
openpgp.enums.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint
);
cipher_algo = openpgp.enums.read(openpgp.enums.symmetric, cipher_algo);
const Z = await openpgp.crypto.publicKey.elliptic.ecdh.kdf(
hash_algo, sharedKey, openpgp.crypto.cipher[cipher_algo].keySize, param, curveObj, false
);
return Z;
}
describe('ECDHE key generation', function () {
it('Invalid curve', function (done) {
if (!openpgp.config.use_indutny_elliptic && !openpgp.util.getNodeCrypto()) {
this.skip();
}
expect(genPublicEphemeralKey("secp256k1", Q1, fingerprint1)
).to.be.rejectedWith(Error, /Public key is not valid for specified curve|Failed to translate Buffer to a EC_POINT|Unknown point format/).notify(done);
});
it('Invalid public part of ephemeral key and private key', async function () {
const ECDHE_VZ1 = await genPublicEphemeralKey("curve25519", Q1, fingerprint1);
const ECDHE_Z12 = await genPrivateEphemeralKey("curve25519", ECDHE_VZ1.V, Q2, d2, fingerprint1);
expect(Array.from(ECDHE_Z12).join(' ') === Array.from(ECDHE_VZ1.Z).join(' ')).to.be.false;
});
it('Invalid fingerprint', async function () {
const ECDHE_VZ2 = await genPublicEphemeralKey("curve25519", Q2, fingerprint1);
const ECDHE_Z2 = await genPrivateEphemeralKey("curve25519", ECDHE_VZ2.V, Q2, d2, fingerprint2);
expect(Array.from(ECDHE_Z2).join(' ') === Array.from(ECDHE_VZ2.Z).join(' ')).to.be.false;
});
it('Different keys', async function () {
const ECDHE_VZ1 = await genPublicEphemeralKey("curve25519", Q1, fingerprint1);
const ECDHE_VZ2 = await genPublicEphemeralKey("curve25519", Q2, fingerprint1);
const ECDHE_Z1 = await genPrivateEphemeralKey("curve25519", ECDHE_VZ1.V, Q1, d1, fingerprint1);
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_VZ2.Z).join(' ')).to.be.false;
});
it('Successful exchange curve25519', async function () {
const ECDHE_VZ1 = await genPublicEphemeralKey("curve25519", Q1, fingerprint1);
const ECDHE_Z1 = await genPrivateEphemeralKey("curve25519", ECDHE_VZ1.V, Q1, d1, fingerprint1);
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_VZ1.Z).join(' ')).to.be.true;
});
it('Successful exchange NIST P256', async function () {
const ECDHE_VZ1 = await genPublicEphemeralKey("p256", key_data.p256.pub, fingerprint1);
const ECDHE_Z1 = await genPrivateEphemeralKey("p256", ECDHE_VZ1.V, key_data.p256.pub, key_data.p256.priv, fingerprint1);
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_VZ1.Z).join(' ')).to.be.true;
});
it('Successful exchange NIST P384', async function () {
const ECDHE_VZ1 = await genPublicEphemeralKey("p384", key_data.p384.pub, fingerprint1);
const ECDHE_Z1 = await genPrivateEphemeralKey("p384", ECDHE_VZ1.V, key_data.p384.pub, key_data.p384.priv, fingerprint1);
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_VZ1.Z).join(' ')).to.be.true;
});
it('Successful exchange NIST P521', async function () {
const ECDHE_VZ1 = await genPublicEphemeralKey("p521", key_data.p521.pub, fingerprint1);
const ECDHE_Z1 = await genPrivateEphemeralKey("p521", ECDHE_VZ1.V, key_data.p521.pub, key_data.p521.priv, fingerprint1);
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_VZ1.Z).join(' ')).to.be.true;
});
it('Comparing keys derived using webCrypto and elliptic', async function () {
const names = ["p256", "p384", "p521"];
if (!openpgp.util.getWebCrypto() || !openpgp.config.use_indutny_elliptic) {
this.skip();
}
return Promise.all(names.map(async function (name) {
const curve = new elliptic_curves.Curve(name);
try {
await window.crypto.subtle.generateKey({
name: "ECDSA",
namedCurve: curve.web.web
}, false, ["sign", "verify"]);
} catch(err) {
openpgp.util.print_debug_error(err);
return;
}
const ECDHE_VZ1 = await genPublicEphemeralKey(name, key_data[name].pub, fingerprint1);
const ECDHE_Z1 = await genPrivateEphemeralKeySpecific('ellipticPrivateEphemeralKey', name, ECDHE_VZ1.V, key_data[name].pub, key_data[name].priv, fingerprint1);
const ECDHE_Z2 = await genPrivateEphemeralKeySpecific('webPrivateEphemeralKey', name, ECDHE_VZ1.V, key_data[name].pub, key_data[name].priv, fingerprint1);
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_VZ1.Z).join(' ')).to.be.true;
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_Z2).join(' ')).to.be.true;
}));
});
it('Comparing keys derived using nodeCrypto and elliptic', async function () {
const names = ["p256", "p384", "p521"];
if (!openpgp.util.getNodeCrypto() || !openpgp.config.use_indutny_elliptic) {
this.skip();
}
return Promise.all(names.map(async function (name) {
const ECDHE_VZ1 = await genPublicEphemeralKey(name, key_data[name].pub, fingerprint1);
const ECDHE_Z1 = await genPrivateEphemeralKeySpecific('ellipticPrivateEphemeralKey', name, ECDHE_VZ1.V, key_data[name].pub, key_data[name].priv, fingerprint1);
const ECDHE_Z2 = await genPrivateEphemeralKeySpecific('nodePrivateEphemeralKey', name, ECDHE_VZ1.V, key_data[name].pub, key_data[name].priv, fingerprint1);
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_VZ1.Z).join(' ')).to.be.true;
expect(Array.from(ECDHE_Z1).join(' ') === Array.from(ECDHE_Z2).join(' ')).to.be.true;
}));
});
});
}); });

View File

@ -0,0 +1,102 @@
const elliptic_data = {
key_data: {
p256: {
priv: new Uint8Array([
0x2B, 0x48, 0x2B, 0xE9, 0x88, 0x74, 0xE9, 0x49,
0x1F, 0x89, 0xCC, 0xFF, 0x0A, 0x26, 0x05, 0xA2,
0x3C, 0x2A, 0x35, 0x25, 0x26, 0x11, 0xD7, 0xEA,
0xA1, 0xED, 0x29, 0x95, 0xB5, 0xE1, 0x5F, 0x1D
]),
pub: new Uint8Array([
0x04,
0x80, 0x2C, 0x40, 0x76, 0x31, 0x20, 0xB6, 0x9B,
0x48, 0x3B, 0x05, 0xEB, 0x6C, 0x1E, 0x3F, 0x49,
0x84, 0xF7, 0xD2, 0xAD, 0x16, 0xA1, 0x6F, 0x62,
0xFD, 0xCA, 0xEC, 0xB4, 0xA0, 0xBD, 0x4C, 0x1A,
0x6F, 0xAA, 0xE7, 0xFD, 0xC4, 0x7D, 0x89, 0xCC,
0x06, 0xCA, 0xFE, 0xAE, 0xCD, 0x0E, 0x9E, 0x62,
0x57, 0xA4, 0xC3, 0xE7, 0x5E, 0x69, 0x10, 0xEE,
0x67, 0xC2, 0x09, 0xF9, 0xEF, 0xE7, 0x9E, 0x56
])
},
p384: {
priv: new Uint8Array([
0xB5, 0x38, 0xDA, 0xF3, 0x77, 0x58, 0x3F, 0x94,
0x5B, 0xC2, 0xCA, 0xC6, 0xA9, 0xFC, 0xAA, 0x3F,
0x97, 0xB0, 0x54, 0x26, 0x10, 0xB4, 0xEC, 0x2A,
0xA7, 0xC1, 0xA3, 0x4B, 0xC0, 0xBD, 0xFE, 0x3E,
0xF1, 0xBE, 0x76, 0xCB, 0xE8, 0xAB, 0x3B, 0xBD,
0xB6, 0x84, 0xC7, 0x8B, 0x91, 0x2F, 0x76, 0x8B
]),
pub: new Uint8Array([
0x04,
0x44, 0x83, 0xA0, 0x3E, 0x5B, 0x0A, 0x0D, 0x9B,
0xA0, 0x06, 0xDF, 0x38, 0xC7, 0x64, 0xCD, 0x62,
0x7D, 0x5E, 0x3D, 0x3B, 0x50, 0xF5, 0x06, 0xC7,
0xF7, 0x9B, 0xF0, 0xDE, 0xB1, 0x0C, 0x64, 0x74,
0x0D, 0x03, 0x67, 0x24, 0xA0, 0xFF, 0xD1, 0x3D,
0x03, 0x96, 0x48, 0xE7, 0x73, 0x5E, 0xF1, 0xC0,
0x62, 0xCC, 0x33, 0x5A, 0x2A, 0x66, 0xA7, 0xAB,
0xCA, 0x77, 0x52, 0xB8, 0xCD, 0xB5, 0x91, 0x16,
0xAF, 0x42, 0xBB, 0x79, 0x0A, 0x59, 0x51, 0x68,
0x8E, 0xEA, 0x32, 0x7D, 0x4A, 0x4A, 0xBB, 0x26,
0x13, 0xFB, 0x95, 0xC0, 0xB1, 0xA4, 0x54, 0xCA,
0xFA, 0x85, 0x8A, 0x4B, 0x58, 0x7C, 0x61, 0x39
])
},
p521: {
priv: new Uint8Array([
0x00, 0xBB, 0x35, 0x27, 0xBC, 0xD6, 0x7E, 0x35,
0xD5, 0xC5, 0x99, 0xC9, 0xB4, 0x6C, 0xEE, 0xDE,
0x79, 0x2D, 0x77, 0xBD, 0x0A, 0x08, 0x9A, 0xC2,
0x21, 0xF8, 0x35, 0x1C, 0x49, 0x5C, 0x40, 0x11,
0xAC, 0x95, 0x2A, 0xEE, 0x91, 0x3A, 0x60, 0x5A,
0x25, 0x5A, 0x95, 0x38, 0xDC, 0xEB, 0x59, 0x8E,
0x33, 0xAD, 0xC0, 0x0B, 0x56, 0xB1, 0x06, 0x8C,
0x57, 0x48, 0xA3, 0x73, 0xDB, 0xE0, 0x19, 0x50,
0x2E, 0x79
]),
pub: new Uint8Array([
0x04,
0x01, 0x0D, 0xD5, 0xCA, 0xD8, 0xB0, 0xEF, 0x9F,
0x2B, 0x7E, 0x58, 0x99, 0xDE, 0x05, 0xF6, 0xF6,
0x64, 0x6B, 0xCD, 0x59, 0x2E, 0x39, 0xB8, 0x82,
0xB3, 0x13, 0xE6, 0x7D, 0x50, 0x85, 0xC3, 0xFA,
0x93, 0xA5, 0x3F, 0x92, 0x85, 0x42, 0x36, 0xC0,
0x83, 0xC9, 0xA4, 0x38, 0xB3, 0xD1, 0x99, 0xDA,
0xE1, 0x02, 0x37, 0x7A, 0x3A, 0xC2, 0xB4, 0x55,
0xEC, 0x1C, 0x0F, 0x00, 0x97, 0xFC, 0x75, 0x93,
0xFE, 0x87, 0x00, 0x7D, 0xBE, 0x1A, 0xF5, 0xF9,
0x57, 0x5C, 0xF2, 0x50, 0x2D, 0x14, 0x32, 0xEE,
0x9B, 0xBE, 0xB3, 0x0E, 0x12, 0x2F, 0xF8, 0x85,
0x11, 0x1A, 0x4F, 0x88, 0x50, 0xA4, 0xDB, 0x37,
0xA6, 0x53, 0x5C, 0xB7, 0x87, 0xA6, 0x06, 0x21,
0x15, 0xCC, 0x12, 0xC0, 0x1C, 0x83, 0x6F, 0x7B,
0x5A, 0x8A, 0x36, 0x4E, 0x46, 0x9E, 0x54, 0x3F,
0xE2, 0xF7, 0xED, 0x63, 0xC9, 0x92, 0xA4, 0x38,
0x2B, 0x9C, 0xE2, 0xB7
])
},
secp256k1: {
priv: new Uint8Array([
0x9E, 0xB0, 0x30, 0xD6, 0xE1, 0xCE, 0xAA, 0x0B,
0x7B, 0x8F, 0xDE, 0x5D, 0x91, 0x4D, 0xDC, 0xA0,
0xAD, 0x05, 0xAB, 0x8F, 0x87, 0x9B, 0x57, 0x48,
0xAE, 0x8A, 0xE0, 0xF9, 0x39, 0xBD, 0x24, 0x00
]),
pub: new Uint8Array([
0x04,
0xA8, 0x02, 0x35, 0x2C, 0xB7, 0x24, 0x95, 0x51,
0x0A, 0x65, 0x26, 0x7D, 0xDF, 0xEA, 0x64, 0xB3,
0xA8, 0xE1, 0x4F, 0xDD, 0x12, 0x84, 0x7E, 0x59,
0xDB, 0x81, 0x0F, 0x89, 0xED, 0xFB, 0x29, 0xFB,
0x07, 0x60, 0x29, 0x7D, 0x39, 0x8F, 0xB8, 0x68,
0xF0, 0xFD, 0xA6, 0x67, 0x83, 0x55, 0x75, 0x7D,
0xB8, 0xFD, 0x0B, 0xDF, 0x76, 0xCE, 0xBC, 0x95,
0x4B, 0x92, 0x26, 0xFC, 0xAA, 0x7A, 0x7C, 0x3F
])
}
}
};
module.exports = elliptic_data;

View File

@ -3,14 +3,14 @@ const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp
const chai = require('chai'); const chai = require('chai');
const { util } = openpgp; const { util } = openpgp;
const MD5 = openpgp.crypto.hash.md5; const md5 = openpgp.crypto.hash.md5;
const { expect } = chai; const { expect } = chai;
it('MD5 with test vectors from RFC 1321', async function() { it('MD5 with test vectors from RFC 1321', async function() {
expect(util.str_to_hex(util.Uint8Array_to_str(await MD5(util.str_to_Uint8Array(''))), 'MD5("") = d41d8cd98f00b204e9800998ecf8427e')).to.equal('d41d8cd98f00b204e9800998ecf8427e'); expect(util.str_to_hex(util.Uint8Array_to_str(await md5(util.str_to_Uint8Array(''))), 'MD5("") = d41d8cd98f00b204e9800998ecf8427e')).to.equal('d41d8cd98f00b204e9800998ecf8427e');
expect(util.str_to_hex(util.Uint8Array_to_str(await MD5(util.str_to_Uint8Array('abc'))), 'MD5("a") = 0cc175b9c0f1b6a831c399e269772661')).to.equal('900150983cd24fb0d6963f7d28e17f72'); expect(util.str_to_hex(util.Uint8Array_to_str(await md5(util.str_to_Uint8Array('abc'))), 'MD5("a") = 0cc175b9c0f1b6a831c399e269772661')).to.equal('900150983cd24fb0d6963f7d28e17f72');
expect(util.str_to_hex(util.Uint8Array_to_str(await MD5(util.str_to_Uint8Array('message digest'))), 'MD5("message digest") = f96b697d7cb7938d525a2f31aaf161d0')).to.equal('f96b697d7cb7938d525a2f31aaf161d0'); expect(util.str_to_hex(util.Uint8Array_to_str(await md5(util.str_to_Uint8Array('message digest'))), 'MD5("message digest") = f96b697d7cb7938d525a2f31aaf161d0')).to.equal('f96b697d7cb7938d525a2f31aaf161d0');
expect(util.str_to_hex(util.Uint8Array_to_str(await MD5(util.str_to_Uint8Array('abcdefghijklmnopqrstuvwxyz'))), 'MD5("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b')).to.equal('c3fcd3d76192e4007dfb496cca67e13b'); expect(util.str_to_hex(util.Uint8Array_to_str(await md5(util.str_to_Uint8Array('abcdefghijklmnopqrstuvwxyz'))), 'MD5("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b')).to.equal('c3fcd3d76192e4007dfb496cca67e13b');
expect(util.str_to_hex(util.Uint8Array_to_str(await MD5(util.str_to_Uint8Array('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'))), 'MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f')).to.equal('d174ab98d277d9f5a5611c2c9f419d9f'); expect(util.str_to_hex(util.Uint8Array_to_str(await md5(util.str_to_Uint8Array('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'))), 'MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f')).to.equal('d174ab98d277d9f5a5611c2c9f419d9f');
expect(util.str_to_hex(util.Uint8Array_to_str(await MD5(util.str_to_Uint8Array('12345678901234567890123456789012345678901234567890123456789012345678901234567890'))), 'MD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a')).to.equal('57edf4a22be3c955ac49da2e2107b67a'); expect(util.str_to_hex(util.Uint8Array_to_str(await md5(util.str_to_Uint8Array('12345678901234567890123456789012345678901234567890123456789012345678901234567890'))), 'MD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a')).to.equal('57edf4a22be3c955ac49da2e2107b67a');
}); });

View File

@ -3,12 +3,12 @@ const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp
const chai = require('chai'); const chai = require('chai');
const { util } = openpgp; const { util } = openpgp;
const RMDstring = openpgp.crypto.hash.ripemd; const rmdString = openpgp.crypto.hash.ripemd;
const { expect } = chai; const { expect } = chai;
it("RIPE-MD 160 bits with test vectors from https://homes.esat.kuleuven.be/~bosselae/ripemd160.html", async function() { it("RIPE-MD 160 bits with test vectors from https://homes.esat.kuleuven.be/~bosselae/ripemd160.html", async function() {
expect(util.str_to_hex(util.Uint8Array_to_str(await RMDstring(util.str_to_Uint8Array(''))), 'RMDstring("") = 9c1185a5c5e9fc54612808977ee8f548b2258d31')).to.equal('9c1185a5c5e9fc54612808977ee8f548b2258d31'); expect(util.str_to_hex(util.Uint8Array_to_str(await rmdString(util.str_to_Uint8Array(''))), 'RMDstring("") = 9c1185a5c5e9fc54612808977ee8f548b2258d31')).to.equal('9c1185a5c5e9fc54612808977ee8f548b2258d31');
expect(util.str_to_hex(util.Uint8Array_to_str(await RMDstring(util.str_to_Uint8Array('a'))), 'RMDstring("a") = 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe')).to.equal('0bdc9d2d256b3ee9daae347be6f4dc835a467ffe'); expect(util.str_to_hex(util.Uint8Array_to_str(await rmdString(util.str_to_Uint8Array('a'))), 'RMDstring("a") = 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe')).to.equal('0bdc9d2d256b3ee9daae347be6f4dc835a467ffe');
expect(util.str_to_hex(util.Uint8Array_to_str(await RMDstring(util.str_to_Uint8Array('abc'))), 'RMDstring("abc") = 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc')).to.equal('8eb208f7e05d987a9b044a8e98c6b087f15a0bfc'); expect(util.str_to_hex(util.Uint8Array_to_str(await rmdString(util.str_to_Uint8Array('abc'))), 'RMDstring("abc") = 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc')).to.equal('8eb208f7e05d987a9b044a8e98c6b087f15a0bfc');
expect(util.str_to_hex(util.Uint8Array_to_str(await RMDstring(util.str_to_Uint8Array('message digest'))), 'RMDstring("message digest") = 5d0689ef49d2fae572b881b123a85ffa21595f36')).to.equal('5d0689ef49d2fae572b881b123a85ffa21595f36'); expect(util.str_to_hex(util.Uint8Array_to_str(await rmdString(util.str_to_Uint8Array('message digest'))), 'RMDstring("message digest") = 5d0689ef49d2fae572b881b123a85ffa21595f36')).to.equal('5d0689ef49d2fae572b881b123a85ffa21595f36');
}); });

View File

@ -4,6 +4,7 @@ describe('Crypto', function () {
require('./random.js'); require('./random.js');
require('./crypto.js'); require('./crypto.js');
require('./elliptic.js'); require('./elliptic.js');
require('./ecdh.js');
require('./pkcs5.js'); require('./pkcs5.js');
require('./aes_kw.js'); require('./aes_kw.js');
require('./eax.js'); require('./eax.js');

View File

@ -14,7 +14,7 @@ describe('Symmetric AES-OCB', function() {
const K = '000102030405060708090A0B0C0D0E0F'; const K = '000102030405060708090A0B0C0D0E0F';
const keyBytes = openpgp.util.hex_to_Uint8Array(K); const keyBytes = openpgp.util.hex_to_Uint8Array(K);
var vectors = [ const vectors = [
// From https://tools.ietf.org/html/rfc7253#appendix-A // From https://tools.ietf.org/html/rfc7253#appendix-A
{ {
N: 'BBAA99887766554433221100', N: 'BBAA99887766554433221100',
@ -116,11 +116,11 @@ describe('Symmetric AES-OCB', function() {
const cipher = 'aes128'; const cipher = 'aes128';
for(const [i, vec] of vectors.entries()) { await Promise.all(vectors.map(async vec => {
const msgBytes = openpgp.util.hex_to_Uint8Array(vec.P), const msgBytes = openpgp.util.hex_to_Uint8Array(vec.P);
nonceBytes = openpgp.util.hex_to_Uint8Array(vec.N), const nonceBytes = openpgp.util.hex_to_Uint8Array(vec.N);
headerBytes = openpgp.util.hex_to_Uint8Array(vec.A), const headerBytes = openpgp.util.hex_to_Uint8Array(vec.A);
ctBytes = openpgp.util.hex_to_Uint8Array(vec.C); const ctBytes = openpgp.util.hex_to_Uint8Array(vec.C);
const ocb = await openpgp.crypto.ocb(cipher, keyBytes); const ocb = await openpgp.crypto.ocb(cipher, keyBytes);
@ -136,7 +136,7 @@ describe('Symmetric AES-OCB', function() {
ct = await ocb.encrypt(msgBytes, nonceBytes, headerBytes); ct = await ocb.encrypt(msgBytes, nonceBytes, headerBytes);
ct[2] ^= 8; ct[2] ^= 8;
pt = ocb.decrypt(ct, nonceBytes, headerBytes); pt = ocb.decrypt(ct, nonceBytes, headerBytes);
await expect(pt).to.eventually.be.rejectedWith('Authentication tag mismatch') await expect(pt).to.eventually.be.rejectedWith('Authentication tag mismatch');
// testing without additional data // testing without additional data
ct = await ocb.encrypt(msgBytes, nonceBytes, new Uint8Array()); ct = await ocb.encrypt(msgBytes, nonceBytes, new Uint8Array());
@ -147,37 +147,37 @@ describe('Symmetric AES-OCB', function() {
ct = await ocb.encrypt(msgBytes, nonceBytes, openpgp.util.concatUint8Array([headerBytes, headerBytes, headerBytes])); ct = await ocb.encrypt(msgBytes, nonceBytes, openpgp.util.concatUint8Array([headerBytes, headerBytes, headerBytes]));
pt = await ocb.decrypt(ct, nonceBytes, openpgp.util.concatUint8Array([headerBytes, headerBytes, headerBytes])); pt = await ocb.decrypt(ct, nonceBytes, openpgp.util.concatUint8Array([headerBytes, headerBytes, headerBytes]));
expect(openpgp.util.Uint8Array_to_hex(pt)).to.equal(vec.P.toLowerCase()); expect(openpgp.util.Uint8Array_to_hex(pt)).to.equal(vec.P.toLowerCase());
} }));
}); });
it('Different key size test vectors', async function() { it('Different key size test vectors', async function() {
const TAGLEN = 128; const taglen = 128;
const outputs = { const outputs = {
128: '67E944D23256C5E0B6C61FA22FDF1EA2', 128: '67E944D23256C5E0B6C61FA22FDF1EA2',
192: 'F673F2C3E7174AAE7BAE986CA9F29E17', 192: 'F673F2C3E7174AAE7BAE986CA9F29E17',
256: 'D90EB8E9C977C88B79DD793D7FFA161C' 256: 'D90EB8E9C977C88B79DD793D7FFA161C'
}; };
const keylens = [128, 192, 256];
await Promise.all(keylens.map(async keylen => {
const k = new Uint8Array(keylen / 8);
k[k.length - 1] = taglen;
for (const KEYLEN of [128, 192, 256]) { const ocb = await openpgp.crypto.ocb('aes' + keylen, k);
const K = new Uint8Array(KEYLEN / 8);
K[K.length - 1] = TAGLEN;
const ocb = await openpgp.crypto.ocb('aes' + KEYLEN, K); const c = [];
let n;
const C = [];
let N;
for (let i = 0; i < 128; i++) { for (let i = 0; i < 128; i++) {
const S = new Uint8Array(i); const s = new Uint8Array(i);
N = openpgp.util.concatUint8Array([new Uint8Array(8), openpgp.util.writeNumber(3 * i + 1, 4)]); n = openpgp.util.concatUint8Array([new Uint8Array(8), openpgp.util.writeNumber(3 * i + 1, 4)]);
C.push(await ocb.encrypt(S, N, S)); c.push(await ocb.encrypt(s, n, s));
N = openpgp.util.concatUint8Array([new Uint8Array(8), openpgp.util.writeNumber(3 * i + 2, 4)]); n = openpgp.util.concatUint8Array([new Uint8Array(8), openpgp.util.writeNumber(3 * i + 2, 4)]);
C.push(await ocb.encrypt(S, N, new Uint8Array())); c.push(await ocb.encrypt(s, n, new Uint8Array()));
N = openpgp.util.concatUint8Array([new Uint8Array(8), openpgp.util.writeNumber(3 * i + 3, 4)]); n = openpgp.util.concatUint8Array([new Uint8Array(8), openpgp.util.writeNumber(3 * i + 3, 4)]);
C.push(await ocb.encrypt(new Uint8Array(), N, S)); c.push(await ocb.encrypt(new Uint8Array(), n, s));
}
N = openpgp.util.concatUint8Array([new Uint8Array(8), openpgp.util.writeNumber(385, 4)]);
const output = await ocb.encrypt(new Uint8Array(), N, openpgp.util.concatUint8Array(C));
expect(openpgp.util.Uint8Array_to_hex(output)).to.equal(outputs[KEYLEN].toLowerCase());
} }
n = openpgp.util.concatUint8Array([new Uint8Array(8), openpgp.util.writeNumber(385, 4)]);
const output = await ocb.encrypt(new Uint8Array(), n, openpgp.util.concatUint8Array(c));
expect(openpgp.util.Uint8Array_to_hex(output)).to.equal(outputs[keylen].toLowerCase());
}));
}); });
}); });