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) {
@ -51,7 +50,7 @@ it('Blowfish cipher test with test vectors from https://www.schneier.com/code/ve
for (let i = 0; i < testvectors.length; i++) { for (let i = 0; i < testvectors.length; i++) {
const res = test_bf(testvectors[i][1],testvectors[i][0],testvectors[i][2]); const res = test_bf(testvectors[i][1],testvectors[i][0],testvectors[i][2]);
expect(res, 'vector '+ i + '" with block ' + util.Uint8Array_to_hex(testvectors[i][0])+ expect(res, 'vector ' + i + '" with block ' + util.Uint8Array_to_hex(testvectors[i][0]) +
' and key ' + util.Uint8Array_to_hex(testvectors[i][1]) + ' and key ' + util.Uint8Array_to_hex(testvectors[i][1]) +
' should be ' + util.Uint8Array_to_hex(testvectors[i][2]), false); ' should be ' + util.Uint8Array_to_hex(testvectors[i][2]), false);
} }

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

@ -30,7 +30,7 @@ describe('API functional testing', function() {
0xee,0xc9,0xa4,0xcd,0x15,0xdc,0x1b,0x8d,0x64,0xc1,0x36,0x17,0xc4, 0xee,0xc9,0xa4,0xcd,0x15,0xdc,0x1b,0x8d,0x64,0xc1,0x36,0x17,0xc4,
0x8d,0x5e,0x99,0x7a,0x5b,0x9f,0x39,0xd0,0x00,0x6e,0xf9]), 0x8d,0x5e,0x99,0x7a,0x5b,0x9f,0x39,0xd0,0x00,0x6e,0xf9]),
new Uint8Array([0x00,0x11,0x01,0x00,0x01]) new Uint8Array([0x00,0x11,0x01,0x00,0x01])
]; ];
const RSAsecMPIstrs = [ const RSAsecMPIstrs = [
new Uint8Array([0x07,0xfe,0x23,0xff,0xce,0x45,0x6c,0x60,0x65,0x40,0x6e,0xae,0x35, new Uint8Array([0x07,0xfe,0x23,0xff,0xce,0x45,0x6c,0x60,0x65,0x40,0x6e,0xae,0x35,
0x10,0x56,0x60,0xee,0xab,0xfa,0x10,0x42,0xba,0xc7,0x04,0xaf,0x63, 0x10,0x56,0x60,0xee,0xab,0xfa,0x10,0x42,0xba,0xc7,0x04,0xaf,0x63,
@ -82,7 +82,7 @@ describe('API functional testing', function() {
0x51,0xe0,0x22,0xf0,0xff,0xa7,0x42,0xd4,0xde,0x0b,0x47,0x8f,0x2b, 0x51,0xe0,0x22,0xf0,0xff,0xa7,0x42,0xd4,0xde,0x0b,0x47,0x8f,0x2b,
0xf5,0x4d,0x04,0x32,0x91,0x89,0x4b,0x0e,0x05,0x8d,0x70,0xf9,0xbb, 0xf5,0x4d,0x04,0x32,0x91,0x89,0x4b,0x0e,0x05,0x8d,0x70,0xf9,0xbb,
0xe7,0xd6,0x76,0xea,0x0e,0x1a,0x90,0x30,0xf5,0x98,0x01,0xc5,0x73]) 0xe7,0xd6,0x76,0xea,0x0e,0x1a,0x90,0x30,0xf5,0x98,0x01,0xc5,0x73])
]; ];
const DSApubMPIstrs = [ const DSApubMPIstrs = [
new Uint8Array([0x08,0x00,0xa8,0x85,0x5c,0x28,0x05,0x94,0x03,0xbe,0x07,0x6c,0x13,0x3e,0x65, new Uint8Array([0x08,0x00,0xa8,0x85,0x5c,0x28,0x05,0x94,0x03,0xbe,0x07,0x6c,0x13,0x3e,0x65,
@ -142,12 +142,12 @@ describe('API functional testing', function() {
0x67,0x8d,0x9d,0x14,0xb6,0x9d,0x32,0x82,0xd0,0xb5,0xc6,0x57,0xf0,0x91,0xd9, 0x67,0x8d,0x9d,0x14,0xb6,0x9d,0x32,0x82,0xd0,0xb5,0xc6,0x57,0xf0,0x91,0xd9,
0xc3,0x26,0xae,0x9f,0xa9,0x67,0x49,0x96,0x5c,0x07,0x3e,0x47,0x5c,0xed,0x60, 0xc3,0x26,0xae,0x9f,0xa9,0x67,0x49,0x96,0x5c,0x07,0x3e,0x47,0x5c,0xed,0x60,
0x07,0xac,0x6a]) 0x07,0xac,0x6a])
]; ];
const DSAsecMPIstrs = [ const DSAsecMPIstrs = [
new Uint8Array([0x01,0x00,0x9b,0x58,0xa8,0xf4,0x04,0xb1,0xd5,0x14,0x09,0xe1,0xe1,0xa1,0x8a, new Uint8Array([0x01,0x00,0x9b,0x58,0xa8,0xf4,0x04,0xb1,0xd5,0x14,0x09,0xe1,0xe1,0xa1,0x8a,
0x0b,0xa3,0xc3,0xa3,0x66,0xaa,0x27,0x99,0x50,0x1c,0x4d,0xba,0x24,0xee,0xdf, 0x0b,0xa3,0xc3,0xa3,0x66,0xaa,0x27,0x99,0x50,0x1c,0x4d,0xba,0x24,0xee,0xdf,
0xdf,0xb8,0x8e,0x8e]) 0xdf,0xb8,0x8e,0x8e])
]; ];
const ElgamalpubMPIstrs = [ const ElgamalpubMPIstrs = [
new Uint8Array([0x08,0x00,0xea,0xcc,0xbe,0xe2,0xe4,0x5a,0x51,0x18,0x93,0xa1,0x12,0x2f,0x00, new Uint8Array([0x08,0x00,0xea,0xcc,0xbe,0xe2,0xe4,0x5a,0x51,0x18,0x93,0xa1,0x12,0x2f,0x00,
@ -187,13 +187,13 @@ describe('API functional testing', function() {
0xda,0xba,0x19,0xf3,0xcb,0x10,0xa0,0x6b,0xd0,0x2d,0xbe,0x40,0x42,0x7b,0x9b, 0xda,0xba,0x19,0xf3,0xcb,0x10,0xa0,0x6b,0xd0,0x2d,0xbe,0x40,0x42,0x7b,0x9b,
0x15,0xa4,0x2d,0xec,0xcf,0x09,0xd6,0xe3,0x92,0xc3,0x8d,0x65,0x6b,0x60,0x97, 0x15,0xa4,0x2d,0xec,0xcf,0x09,0xd6,0xe3,0x92,0xc3,0x8d,0x65,0x6b,0x60,0x97,
0xda,0x6b,0xca]) 0xda,0x6b,0xca])
]; ];
const ElgamalsecMPIstrs = [ const ElgamalsecMPIstrs = [
new Uint8Array([0x01,0x52,0x02,0x80,0x87,0xf6,0xe4,0x49,0xd7,0x2e,0x3e,0xfe,0x60,0xb9,0xa3, new Uint8Array([0x01,0x52,0x02,0x80,0x87,0xf6,0xe4,0x49,0xd7,0x2e,0x3e,0xfe,0x60,0xb9,0xa3,
0x2a,0xf0,0x67,0x58,0xe9,0xf6,0x47,0x83,0xde,0x7e,0xfb,0xbb,0xbd,0xdf,0x48, 0x2a,0xf0,0x67,0x58,0xe9,0xf6,0x47,0x83,0xde,0x7e,0xfb,0xbb,0xbd,0xdf,0x48,
0x12,0x1b,0x06,0x7d,0x13,0xbc,0x3b,0x49,0xf9,0x86,0xd4,0x53,0xed,0x2d,0x68]) 0x12,0x1b,0x06,0x7d,0x13,0xbc,0x3b,0x49,0xf9,0x86,0xd4,0x53,0xed,0x2d,0x68])
]; ];
const RSApubMPIs = []; const RSApubMPIs = [];
let i; let i;
@ -289,7 +289,7 @@ describe('API functional testing', function() {
function testAESGCM(plaintext, nativeDecrypt) { function testAESGCM(plaintext, nativeDecrypt) {
symmAlgos.forEach(function(algo) { symmAlgos.forEach(function(algo) {
if(algo.substr(0,3) === 'aes') { if (algo.substr(0,3) === 'aes') {
it(algo, async function() { it(algo, async function() {
const key = await crypto.generateSessionKey(algo); const key = await crypto.generateSessionKey(algo);
const iv = await crypto.random.getRandomBytes(crypto.gcm.ivLength); const iv = await crypto.random.getRandomBytes(crypto.gcm.ivLength);

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());
}));
}); });
}); });

View File

@ -5,7 +5,7 @@ const expect = require('chai').expect;
describe('PKCS5 padding', function() { describe('PKCS5 padding', function() {
function repeat(pattern, count) { function repeat(pattern, count) {
let result = ''; let result = '';
for (let k=0; k<count; ++k) { for (let k = 0; k < count; ++k) {
result += pattern; result += pattern;
} }
return result; return result;
@ -16,7 +16,7 @@ describe('PKCS5 padding', function() {
while (s.length < 16) { while (s.length < 16) {
const r = pkcs5.encode(s); const r = pkcs5.encode(s);
// 0..7 -> 8, 8..15 -> 16 // 0..7 -> 8, 8..15 -> 16
const l = Math.ceil((s.length+1)/8)*8; const l = Math.ceil((s.length + 1) / 8) * 8;
const c = l - s.length; const c = l - s.length;
expect(r.length).to.equal(l); expect(r.length).to.equal(l);
expect(c).is.at.least(1).is.at.most(8); expect(c).is.at.least(1).is.at.most(8);
@ -25,8 +25,8 @@ describe('PKCS5 padding', function() {
} }
}); });
it('Remove padding', function () { it('Remove padding', function () {
for (let k=1; k<=8; ++k) { for (let k = 1; k <= 8; ++k) {
const s = repeat(' ', 8-k); const s = repeat(' ', 8 - k);
const r = s + repeat(String.fromCharCode(k), k); const r = s + repeat(String.fromCharCode(k), k);
const t = pkcs5.decode(r); const t = pkcs5.decode(r);
expect(t).to.equal(s); expect(t).to.equal(s);