Apply eslint to test/crypto folder (#1003)
This commit is contained in:
parent
bc16d157f0
commit
495fe1091c
|
@ -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,
|
||||||
|
|
|
@ -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
6
npm-shrinkwrap.json
generated
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
283
test/crypto/ecdh.js
Normal 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;
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -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;
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
102
test/crypto/elliptic_data.js
Normal file
102
test/crypto/elliptic_data.js
Normal 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;
|
|
@ -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');
|
||||||
});
|
});
|
||||||
|
|
|
@ -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');
|
||||||
});
|
});
|
||||||
|
|
|
@ -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');
|
||||||
|
|
|
@ -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());
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user