gun/sea/secret.js
sirpy 29ed57e955
react native support (#5)
* WIP: use isomorphic-webcrypto for RN

* WIP: expo friendly exports

* WIP: buffer for RN

* WIP: textencoder for RN

* WIP: aeskey from jwk instead of raw for RN

* fix: missing taglength for msrcrypto

* add: update isomorphic-webcrypto

* add: match isocrypto api

* add: failing test for 4e2 as 400

* fix: remove extra atob btoa

* add: sea unbuild

* refactor: according to mhelander review

* refactor: shorter require

* fix: make bug test pass, capitlize bug test.

* fix: npm ci + sea test

* add: restore old browser export and add react-native friendly exports

* fix: import buffer into correct global/window

* fix: bad comparison

* fix: only include buffer if no btoa/atob
2019-12-08 17:41:26 +02:00

52 lines
2.0 KiB
JavaScript

var SEA = require('./root');
var shim = require('./shim');
var S = require('./settings');
// Derive shared secret from other's pub and my epub/epriv
SEA.secret = SEA.secret || (async (key, pair, cb, opt) => { try {
opt = opt || {};
if(!pair || !pair.epriv || !pair.epub){
pair = await SEA.I(null, {what: key, how: 'secret', why: opt.why});
}
var pub = key.epub || key;
var epub = pair.epub;
var epriv = pair.epriv;
var ecdhSubtle = shim.ossl || shim.subtle;
var pubKeyData = keysToEcdhJwk(pub);
var props = Object.assign({ public: await ecdhSubtle.importKey(...pubKeyData, true, []) },S.ecdh); // Thanks to @sirpy !
var privKeyData = keysToEcdhJwk(epub, epriv);
var derived = await ecdhSubtle.importKey(...privKeyData, false, ['deriveBits']).then(async (privKey) => {
// privateKey scope doesn't leak out from here!
var derivedBits = await ecdhSubtle.deriveBits(props, privKey, 256);
var rawBits = new Uint8Array(derivedBits);
var derivedKey = await ecdhSubtle.importKey('raw', rawBits,{ name: 'AES-GCM', length: 256 }, true, [ 'encrypt', 'decrypt' ]);
return ecdhSubtle.exportKey('jwk', derivedKey).then(({ k }) => k);
})
var r = derived;
if(cb){ try{ cb(r) }catch(e){console.log(e)} }
return r;
} catch(e) {
console.log(e);
SEA.err = e;
if(SEA.throw){ throw e }
if(cb){ cb() }
return;
}});
// can this be replaced with settings.jwk?
var keysToEcdhJwk = (pub, d) => { // d === priv
//var [ x, y ] = Buffer.from(pub, 'base64').toString('utf8').split(':') // old
var [ x, y ] = pub.split('.') // new
var jwk = d ? { d: d } : {}
return [ // Use with spread returned value...
'jwk',
Object.assign(
jwk,
{ x: x, y: y, kty: 'EC', crv: 'P-256', ext: true }
), // ??? refactor
S.ecdh
]
}
module.exports = SEA.secret;