Skip to content

Commit

Permalink
Update: generate and apply header values when key wrapping (#189)
Browse files Browse the repository at this point in the history
  • Loading branch information
linuxwolf committed May 18, 2018
1 parent da9a9f2 commit 370baa4
Show file tree
Hide file tree
Showing 9 changed files with 366 additions and 269 deletions.
61 changes: 47 additions & 14 deletions lib/algorithms/aes-gcm.js
Expand Up @@ -6,22 +6,43 @@
"use strict";

var helpers = require("./helpers.js"),
util = require("../util"),
CONSTANTS = require("./constants.js"),
GCM = require("../deps/ciphermodes/gcm");

function gcmEncryptFN(size) {
function gcmEncryptFN(size, wrap) {
function commonChecks(key, iv) {
if (size !== (key.length << 3)) {
throw new Error("invalid key size");
}
if (12 !== iv.length) {
if (!iv && !wrap) {
throw new Error("invalid iv");
}
if (iv && 12 !== iv.length) {
throw new Error("invalid iv");
}
}

function prepareResults(results) {
if (wrap) {
var iv = util.base64url.encode(results.iv);
var tag = util.base64url.encode(results.tag);

results = {
data: results.data,
header: {
iv: iv,
tag: tag
}
};
}

return results;
}

// ### 'fallback' implementation -- uses forge
var fallback = function(key, pdata, props) {
var iv = props.iv || Buffer.alloc(0),
var iv = props.iv,
adata = props.aad || props.adata || Buffer.alloc(0),
cipher,
cdata;
Expand All @@ -33,6 +54,8 @@ function gcmEncryptFN(size) {
return Promise.reject(err);
}

iv = iv || util.randomBytes(12);

// setup cipher
cipher = GCM.createCipher({
key: key,
Expand Down Expand Up @@ -69,10 +92,11 @@ function gcmEncryptFN(size) {

// resolve with output
var tag = cipher.tag;
resolve({
resolve(prepareResults({
data: cdata,
iv: iv,
tag: tag
});
}));
})();
});

Expand All @@ -82,7 +106,7 @@ function gcmEncryptFN(size) {
// ### WebCryptoAPI implementation
// TODO: cache CryptoKey sooner
var webcrypto = function(key, pdata, props) {
var iv = props.iv || Buffer.alloc(0),
var iv = props.iv,
adata = props.aad || props.adata || Buffer.alloc(0);

try {
Expand All @@ -91,6 +115,8 @@ function gcmEncryptFN(size) {
return Promise.reject(err);
}

iv = iv || util.randomBytes(12);

var alg = {
name: "AES-GCM"
};
Expand All @@ -114,18 +140,19 @@ function gcmEncryptFN(size) {
var cdata = result.slice(0, tagStart);
cdata = Buffer.from(cdata);

return {
return prepareResults({
data: cdata,
iv: iv,
tag: tag
};
});
});

return promise;
};

// ### NodeJS implementation
var nodejs = function(key, pdata, props) {
var iv = props.iv || Buffer.alloc(0),
var iv = props.iv,
adata = props.aad || props.adata || Buffer.alloc(0);

try {
Expand All @@ -134,6 +161,8 @@ function gcmEncryptFN(size) {
return Promise.reject(err);
}

iv = iv || util.randomBytes(12);

var alg = "aes-" + (key.length * 8) + "-gcm";
var cipher;
try {
Expand All @@ -154,14 +183,16 @@ function gcmEncryptFN(size) {
]);
var tag = cipher.getAuthTag();

return {
return prepareResults({
data: cdata,
iv: iv,
tag: tag
};
});
};

return helpers.setupFallback(nodejs, webcrypto, fallback);
}

function gcmDecryptFN(size) {
function commonChecks(key, iv, tag) {
if (size !== (key.length << 3)) {
Expand Down Expand Up @@ -331,10 +362,12 @@ var aesGcm = {};
"A192GCMKW",
"A256GCMKW"
].forEach(function(alg) {
var size = parseInt(/A(\d+)GCM(?:KW)?/g.exec(alg)[1]);
var parts = /A(\d+)GCM(KW)?/g.exec(alg);
var size = parseInt(parts[1]);
var wrap = (parts[2] === "KW");
aesGcm[alg] = {
encrypt: gcmEncryptFN(size),
decrypt: gcmDecryptFN(size)
encrypt: gcmEncryptFN(size, wrap),
decrypt: gcmDecryptFN(size, wrap)
};
});

Expand Down

0 comments on commit 370baa4

Please sign in to comment.