UNPKG

node-jose

Version:

A JavaScript implementation of the JSON Object Signing and Encryption (JOSE) for current web browsers and node.js-based servers

224 lines (201 loc) 5.04 kB
/*! * jwk/octkey.js - Symmetric Octet Key Representation * * Copyright (c) 2015 Cisco Systems, Inc. See LICENSE file. */ "use strict"; var util = require("../util"); var JWK = { BaseKey: require("./basekey.js"), helpers: require("./helpers.js") }; var SIG_ALGS = [ "HS256", "HS384", "HS512" ]; var ENC_ALGS = [ "A128GCM", "A192GCM", "A256GCM", "A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512", "A128CBC+HS256", "A192CBC+HS384", "A256CBC+HS512" ]; var WRAP_ALGS = [ "A128KW", "A192KW", "A256KW", "A128GCMKW", "A192GCMKW", "A256GCMKW", "PBES2-HS256+A128KW", "PBES2-HS384+A192KW", "PBES2-HS512+A256KW", "dir" ]; function adjustDecryptProps(alg, props) { if ("iv" in props) { props.iv = Buffer.isBuffer(props.iv) ? props.iv : util.base64url.decode(props.iv || ""); } if ("adata" in props) { props.adata = Buffer.isBuffer(props.adata) ? props.adata : Buffer.from(props.adata || "", "utf8"); } if ("mac" in props) { props.mac = Buffer.isBuffer(props.mac) ? props.mac : util.base64url.decode(props.mac || ""); } if ("tag" in props) { props.tag = Buffer.isBuffer(props.tag) ? props.tag : util.base64url.decode(props.tag || ""); } return props; } function adjustEncryptProps(alg, props) { if ("iv" in props) { props.iv = Buffer.isBuffer(props.iv) ? props.iv : util.base64url.decode(props.iv || ""); } if ("adata" in props) { props.adata = Buffer.isBuffer(props.adata) ? props.adata : Buffer.from(props.adata || "", "utf8"); } return props; } var JWKOctetCfg = { publicKey: function(props) { var fields = JWK.helpers.COMMON_PROPS.concat([ ]); var pk; pk = JWK.helpers.unpackProps(props, fields); return pk; }, privateKey: function(props) { var fields = JWK.helpers.COMMON_PROPS.concat([ {name: "k", type: "binary"} ]); var pk; pk = JWK.helpers.unpackProps(props, fields); if (pk && pk.k) { pk.length = pk.k.length * 8; } else { pk = undefined; } return pk; }, thumbprint: function(json) { if (json.private) { json = json.private; } var fields; fields = { k: json.k || "", kty: "oct" }; return fields; }, algorithms: function(keys, mode) { var len = keys.private && (keys.private.k.length * 8); var mins = [256, 384, 512]; if (!len) { return []; } switch (mode) { case "encrypt": case "decrypt": return ENC_ALGS.filter(function(a) { return (a === ("A" + (len / 2) + "CBC-HS" + len)) || (a === ("A" + (len / 2) + "CBC+HS" + len)) || (a === ("A" + len + "GCM")); }); case "sign": case "verify": // TODO: allow for HS{less-than-keysize} return SIG_ALGS.filter(function(a) { var result = false; mins.forEach(function(m) { if (m > len) { return; } result = result | (a === ("HS" + m)); }); return result; }); case "wrap": case "unwrap": return WRAP_ALGS.filter(function(a) { return (a === ("A" + len + "KW")) || (a === ("A" + len + "GCMKW")) || (a.indexOf("PBES2-") === 0) || (a === "dir"); }); } return []; }, encryptKey: function(alg, keys) { return keys.private && keys.private.k; }, encryptProps: adjustEncryptProps, decryptKey: function(alg, keys) { return keys.private && keys.private.k; }, decryptProps: adjustDecryptProps, wrapKey: function(alg, keys) { return keys.private && keys.private.k; }, wrapProps: adjustEncryptProps, unwrapKey: function(alg, keys) { return keys.private && keys.private.k; }, unwrapProps: adjustDecryptProps, signKey: function(alg, keys) { return keys.private && keys.private.k; }, verifyKey: function(alg, keys) { return keys.private && keys.private.k; } }; // Factory var JWKOctetFactory = { kty: "oct", prepare: function(props) { // TODO: validate key properties var cfg = JWKOctetCfg; var p = Promise.resolve(props); p = p.then(function(json) { return JWK.helpers.thumbprint(cfg, json); }); p = p.then(function(hash) { var prints = {}; prints[JWK.helpers.INTERNALS.THUMBPRINT_HASH] = hash; props[JWK.helpers.INTERNALS.THUMBPRINT_KEY] = prints; return cfg; }); return p; }, generate: function(size) { // TODO: validate key sizes var key = util.randomBytes(size / 8); return Promise.resolve({ k: key }); } }; // public API module.exports = Object.freeze({ config: JWKOctetCfg, factory: JWKOctetFactory }); // registration (function(REGISTRY) { REGISTRY.register(JWKOctetFactory); })(require("./keystore").registry);