secret.js 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. var SEA = require('./root');
  2. var shim = require('./shim');
  3. var S = require('./settings');
  4. // Derive shared secret from other's pub and my epub/epriv
  5. SEA.secret = SEA.secret || (async (key, pair, cb, opt) => { try {
  6. opt = opt || {};
  7. if(!pair || !pair.epriv || !pair.epub){
  8. pair = await SEA.I(null, {what: key, how: 'secret', why: opt.why});
  9. }
  10. var pub = key.epub || key;
  11. var epub = pair.epub;
  12. var epriv = pair.epriv;
  13. var ecdhSubtle = shim.ossl || shim.subtle;
  14. var pubKeyData = keysToEcdhJwk(pub);
  15. var props = Object.assign({ public: await ecdhSubtle.importKey(...pubKeyData, true, []) },S.ecdh); // Thanks to @sirpy !
  16. var privKeyData = keysToEcdhJwk(epub, epriv);
  17. var derived = await ecdhSubtle.importKey(...privKeyData, false, ['deriveKey']).then(async (privKey) => {
  18. // privateKey scope doesn't leak out from here!
  19. var derivedKey = await ecdhSubtle.deriveKey(props, privKey, { name: 'AES-GCM', length: 256 }, true, [ 'encrypt', 'decrypt' ]);
  20. return ecdhSubtle.exportKey('jwk', derivedKey).then(({ k }) => k);
  21. })
  22. var r = derived;
  23. if(cb){ try{ cb(r) }catch(e){console.log(e)} }
  24. return r;
  25. } catch(e) {
  26. console.log(e);
  27. SEA.err = e;
  28. if(SEA.throw){ throw e }
  29. if(cb){ cb() }
  30. return;
  31. }});
  32. // can this be replaced with settings.jwk?
  33. var keysToEcdhJwk = (pub, d) => { // d === priv
  34. //var [ x, y ] = Buffer.from(pub, 'base64').toString('utf8').split(':') // old
  35. var [ x, y ] = pub.split('.') // new
  36. var jwk = d ? { d: d } : {}
  37. return [ // Use with spread returned value...
  38. 'jwk',
  39. Object.assign(
  40. jwk,
  41. { x: x, y: y, kty: 'EC', crv: 'P-256', ext: true }
  42. ), // ??? refactor
  43. S.ecdh
  44. ]
  45. }
  46. module.exports = SEA.secret;