Cleanup and unit test gcm.js
This commit is contained in:
parent
49faca83c5
commit
8aa15b66a9
|
@ -23,12 +23,14 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import util from '../util.js';
|
import util from '../util.js';
|
||||||
|
import config from '../config';
|
||||||
import asmCrypto from 'asmcrypto-lite';
|
import asmCrypto from 'asmcrypto-lite';
|
||||||
const webCrypto = util.getWebCrypto();
|
const webCrypto = util.getWebCrypto();
|
||||||
const nodeCrypto = util.getNodeCrypto();
|
const nodeCrypto = util.getNodeCrypto();
|
||||||
const Buffer = util.getNodeBuffer();
|
const Buffer = util.getNodeBuffer();
|
||||||
|
|
||||||
export const ivLength = 12;
|
export const ivLength = 12;
|
||||||
|
const ALGO = 'AES-GCM';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt plaintext input.
|
* Encrypt plaintext input.
|
||||||
|
@ -40,26 +42,18 @@ export const ivLength = 12;
|
||||||
*/
|
*/
|
||||||
export function encrypt(cipher, plaintext, key, iv) {
|
export function encrypt(cipher, plaintext, key, iv) {
|
||||||
if (cipher.substr(0,3) !== 'aes') {
|
if (cipher.substr(0,3) !== 'aes') {
|
||||||
return Promise.reject(new Error('Invalid cipher for GCM mode'));
|
return Promise.reject(new Error('GCM mode supports only AES cipher'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (webCrypto) { // native WebCrypto api
|
const keySize = cipher.substr(3,3);
|
||||||
const keyOptions = {
|
if (webCrypto && config.useNative && keySize !== '192') { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support
|
||||||
name: 'AES-GCM'
|
return webCrypto.importKey('raw', key, { name: ALGO }, false, ['encrypt'])
|
||||||
},
|
.then(keyObj => webCrypto.encrypt({ name: ALGO, iv }, keyObj, plaintext))
|
||||||
encryptOptions = {
|
.then(ciphertext => new Uint8Array(ciphertext));
|
||||||
name: 'AES-GCM',
|
|
||||||
iv: iv
|
|
||||||
};
|
|
||||||
return webCrypto.importKey('raw', key, keyOptions, false, ['encrypt']).then(keyObj => {
|
|
||||||
return webCrypto.encrypt(encryptOptions, keyObj, plaintext);
|
|
||||||
}).then(ciphertext => {
|
|
||||||
return new Uint8Array(ciphertext);
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if(nodeCrypto) { // native node crypto library
|
} else if (nodeCrypto && config.useNative) { // Node crypto library
|
||||||
let cipherObj = new nodeCrypto.createCipheriv('aes-' + cipher.substr(3,3) + '-gcm', new Buffer(key), new Buffer(iv));
|
const en = new nodeCrypto.createCipheriv('aes-' + keySize + '-gcm', new Buffer(key), new Buffer(iv));
|
||||||
let encrypted = Buffer.concat([cipherObj.update(new Buffer(plaintext)), cipherObj.final()]);
|
const encrypted = Buffer.concat([en.update(new Buffer(plaintext)), en.final()]);
|
||||||
return Promise.resolve(new Uint8Array(encrypted));
|
return Promise.resolve(new Uint8Array(encrypted));
|
||||||
|
|
||||||
} else { // asm.js fallback
|
} else { // asm.js fallback
|
||||||
|
@ -77,26 +71,18 @@ export function encrypt(cipher, plaintext, key, iv) {
|
||||||
*/
|
*/
|
||||||
export function decrypt(cipher, ciphertext, key, iv) {
|
export function decrypt(cipher, ciphertext, key, iv) {
|
||||||
if (cipher.substr(0,3) !== 'aes') {
|
if (cipher.substr(0,3) !== 'aes') {
|
||||||
return Promise.reject(new Error('Invalid cipher for GCM mode'));
|
return Promise.reject(new Error('GCM mode supports only AES cipher'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (webCrypto) { // native WebCrypto api
|
const keySize = cipher.substr(3,3);
|
||||||
const keyOptions = {
|
if (webCrypto && config.useNative && keySize !== '192') { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support
|
||||||
name: 'AES-GCM'
|
return webCrypto.importKey('raw', key, { name: ALGO }, false, ['decrypt'])
|
||||||
},
|
.then(keyObj => webCrypto.decrypt({ name: ALGO, iv }, keyObj, ciphertext))
|
||||||
decryptOptions = {
|
.then(plaintext => new Uint8Array(plaintext));
|
||||||
name: 'AES-GCM',
|
|
||||||
iv: iv
|
|
||||||
};
|
|
||||||
return webCrypto.importKey('raw', key, keyOptions, false, ['decrypt']).then(keyObj => {
|
|
||||||
return webCrypto.decrypt(decryptOptions, keyObj, ciphertext);
|
|
||||||
}).then(plaintext => {
|
|
||||||
return new Uint8Array(plaintext);
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if(nodeCrypto) { // native node crypto library
|
} else if (nodeCrypto && config.useNative) { // Node crypto library
|
||||||
let decipherObj = new nodeCrypto.createDecipheriv('aes-' + cipher.substr(3,3) + '-gcm', new Buffer(key), new Buffer(iv));
|
let de = new nodeCrypto.createDecipheriv('aes-' + keySize + '-gcm', new Buffer(key), new Buffer(iv));
|
||||||
let decrypted = Buffer.concat([decipherObj.update(new Buffer(ciphertext)), decipherObj.final()]);
|
let decrypted = Buffer.concat([de.update(new Buffer(ciphertext)), de.final()]);
|
||||||
return Promise.resolve(new Uint8Array(decrypted));
|
return Promise.resolve(new Uint8Array(decrypted));
|
||||||
|
|
||||||
} else { // asm.js fallback
|
} else { // asm.js fallback
|
||||||
|
|
|
@ -287,6 +287,25 @@ describe('API functional testing', function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testAESGCM(plaintext) {
|
||||||
|
symmAlgos.forEach(function(algo) {
|
||||||
|
if(algo.substr(0,3) === 'aes') {
|
||||||
|
it(algo, function(done) {
|
||||||
|
var key = openpgp.crypto.generateSessionKey(algo);
|
||||||
|
var iv = openpgp.crypto.random.getRandomValues(new Uint8Array(openpgp.crypto.gcm.ivLength));
|
||||||
|
|
||||||
|
openpgp.crypto.gcm.encrypt(algo, util.str2Uint8Array(plaintext), key, iv).then(function(ciphertext) {
|
||||||
|
return openpgp.crypto.gcm.decrypt(algo, ciphertext, key, iv);
|
||||||
|
}).then(function(decrypted) {
|
||||||
|
var decryptedStr = util.Uint8Array2str(decrypted);
|
||||||
|
expect(decryptedStr).to.equal(plaintext);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
it("Symmetric with OpenPGP CFB resync", function () {
|
it("Symmetric with OpenPGP CFB resync", function () {
|
||||||
testCFB("hello", true);
|
testCFB("hello", true);
|
||||||
testCFB("1234567", true);
|
testCFB("1234567", true);
|
||||||
|
@ -301,11 +320,37 @@ describe('API functional testing', function() {
|
||||||
testCFB("12345678901234567890123456789012345678901234567890", false);
|
testCFB("12345678901234567890123456789012345678901234567890", false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("asmCrypto AES without OpenPGP CFB resync", function () {
|
it.skip("asmCrypto AES without OpenPGP CFB resync", function () {
|
||||||
testCFB("hello");
|
testAESCFB("hello");
|
||||||
testCFB("1234567");
|
testAESCFB("1234567");
|
||||||
testCFB("foobarfoobar1234567890");
|
testAESCFB("foobarfoobar1234567890");
|
||||||
testCFB("12345678901234567890123456789012345678901234567890");
|
testAESCFB("12345678901234567890123456789012345678901234567890");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Symmetric AES-GCM (native)', function() {
|
||||||
|
var useNativeVal;
|
||||||
|
beforeEach(function() {
|
||||||
|
useNativeVal = openpgp.config.useNative;
|
||||||
|
openpgp.config.useNative = true;
|
||||||
|
});
|
||||||
|
afterEach(function() {
|
||||||
|
openpgp.config.useNative = useNativeVal;
|
||||||
|
});
|
||||||
|
|
||||||
|
testAESGCM("12345678901234567890123456789012345678901234567890");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Symmetric AES-GCM (asm.js fallback)', function() {
|
||||||
|
var useNativeVal;
|
||||||
|
beforeEach(function() {
|
||||||
|
useNativeVal = openpgp.config.useNative;
|
||||||
|
openpgp.config.useNative = false;
|
||||||
|
});
|
||||||
|
afterEach(function() {
|
||||||
|
openpgp.config.useNative = useNativeVal;
|
||||||
|
});
|
||||||
|
|
||||||
|
testAESGCM("12345678901234567890123456789012345678901234567890");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Asymmetric using RSA with eme_pkcs1 padding', function (done) {
|
it('Asymmetric using RSA with eme_pkcs1 padding', function (done) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user