diff --git a/sea.js b/sea.js index 82936f78..2f765d5b 100644 --- a/sea.js +++ b/sea.js @@ -221,6 +221,13 @@ if(d){ jwk.d = d } return jwk; }; + + s.keyTojwk = function(keyBytes) { + var jwkKeyString = keyBytes.toString('base64') + jwkKeyString = jwkKeyString.replace(/\+/g, "-").replace(/\//g, "_").replace(/\=/g, ""); + jwkKeyString = { kty: "oct", k: jwkKeyString, ext: false, alg: "A256GCM"}; + return jwkKeyString + } s.recall = { validity: 12 * 60 * 60, // internally in seconds : 12 hours hook: function(props){ return props } // { iat, exp, alias, remember } // or return new Promise((resolve, reject) => resolve(props) @@ -496,6 +503,7 @@ ;USE(function(module){ var shim = USE('./shim'); + var S = USE('./settings'); var sha256hash = USE('./sha256'); const importGen = async (key, salt, opt) => { @@ -503,7 +511,8 @@ var opt = opt || {}; const combo = key + (salt || shim.random(8)).toString('utf8'); // new const hash = shim.Buffer.from(await sha256hash(combo), 'binary') - return await shim.subtle.importKey('raw', new Uint8Array(hash), opt.name || 'AES-GCM', false, ['encrypt', 'decrypt']) + const jwkHash = S.keyTojwk(hash) + return await shim.subtle.importKey('jwk', jwkHash, {name:'AES-GCM'}, false, ['encrypt', 'decrypt']) } module.exports = importGen; })(USE, './aeskey'); @@ -650,6 +659,7 @@ SEA.verify = USE('./verify'); SEA.encrypt = USE('./encrypt'); SEA.decrypt = USE('./decrypt'); + SEA.aeskey = USE('./aeskey'); SEA.random = SEA.random || shim.random; diff --git a/sea/aeskey.js b/sea/aeskey.js index f003a38e..e1ff9663 100644 --- a/sea/aeskey.js +++ b/sea/aeskey.js @@ -1,5 +1,6 @@ var shim = require('./shim'); + var S = require('./settings'); var sha256hash = require('./sha256'); const importGen = async (key, salt, opt) => { @@ -7,7 +8,8 @@ var opt = opt || {}; const combo = key + (salt || shim.random(8)).toString('utf8'); // new const hash = shim.Buffer.from(await sha256hash(combo), 'binary') - return await shim.subtle.importKey('raw', new Uint8Array(hash), opt.name || 'AES-GCM', false, ['encrypt', 'decrypt']) + const jwkHash = S.keyTojwk(hash) + return await shim.subtle.importKey('jwk', jwkHash, {name:'AES-GCM'}, false, ['encrypt', 'decrypt']) } module.exports = importGen; \ No newline at end of file diff --git a/sea/sea.js b/sea/sea.js index 57826cde..b7d6db7f 100644 --- a/sea/sea.js +++ b/sea/sea.js @@ -7,6 +7,7 @@ SEA.verify = require('./verify'); SEA.encrypt = require('./encrypt'); SEA.decrypt = require('./decrypt'); + SEA.aeskey = require('./aeskey'); SEA.random = SEA.random || shim.random; diff --git a/sea/settings.js b/sea/settings.js index 8e68e8c5..484bea73 100644 --- a/sea/settings.js +++ b/sea/settings.js @@ -18,6 +18,13 @@ if(d){ jwk.d = d } return jwk; }; + + s.keyTojwk = function(keyBytes) { + var jwkKeyString = keyBytes.toString('base64') + jwkKeyString = jwkKeyString.replace(/\+/g, "-").replace(/\//g, "_").replace(/\=/g, ""); + jwkKeyString = { kty: "oct", k: jwkKeyString, ext: false, alg: "A256GCM"}; + return jwkKeyString + } s.recall = { validity: 12 * 60 * 60, // internally in seconds : 12 hours hook: function(props){ return props } // { iat, exp, alias, remember } // or return new Promise((resolve, reject) => resolve(props) diff --git a/sea/shim.js b/sea/shim.js index b6026e8c..a6e8f8a1 100644 --- a/sea/shim.js +++ b/sea/shim.js @@ -6,24 +6,31 @@ if(SEA.window){ api.crypto = window.crypto || window.msCrypto; + if(!api.crypto) { + api.crypto = require('isomorphic-webcrypto'); + } api.subtle = (api.crypto||o).subtle || (api.crypto||o).webkitSubtle; api.TextEncoder = window.TextEncoder; - api.TextDecoder = window.TextDecoder; + api.TextDecoder = window.TextDecoder; api.random = (len) => Buffer.from(api.crypto.getRandomValues(new Uint8Array(Buffer.alloc(len)))) } + if(!api.TextDecoder) + { + const { TextEncoder, TextDecoder } = require('text-encoding') + api.TextDecoder = TextDecoder + api.TextEncoder = TextEncoder + } if(!api.crypto){try{ var crypto = require('crypto', 1); - const { TextEncoder, TextDecoder } = require('text-encoding', 1) Object.assign(api, { crypto, - //subtle, - TextEncoder, - TextDecoder, random: (len) => Buffer.from(crypto.randomBytes(len)) }); //try{ - const WebCrypto = require('node-webcrypto-ossl', 1); - api.ossl = api.subtle = new WebCrypto({directory: 'ossl'}).subtle // ECDH + // const WebCrypto = require('node-webcrypto-ossl', 1); + // api.ossl = api.subtle = new WebCrypto({directory: 'ossl'}).subtle // ECDH + const isocrypto = require('isomorphic-webcrypto'); + api.ossl = api.subtle = isocrypto.subtle //}catch(e){ //console.log("node-webcrypto-ossl is optionally needed for ECDH, please install if needed."); //} diff --git a/test/sea/sea.js b/test/sea/sea.js index e4e5f70e..b5bd7dd4 100644 --- a/test/sea/sea.js +++ b/test/sea/sea.js @@ -37,7 +37,12 @@ describe('SEA', function(){ var gun; var pub; describe('Utility', function(){ - + it('generates aeskey from jwk', function(done) { + SEA.aeskey('x','x').then(k => { + expect(k.data.toString('base64')).to.be('Xd6JaIf2dUybFb/jpEGuSAbfL96UABMR4IvxEGIuC74=') + done() + }) + }) it('quickstart', function(done){ SEA.pair(function(pair){ SEA.encrypt('hello self', pair, function(enc){