secret.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  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 = async (key, pair, cb) => { try {
  6. const pub = key.epub || key
  7. const epub = pair.epub
  8. const epriv = pair.epriv
  9. const ecdhSubtle = shim.ossl || shim.subtle
  10. const pubKeyData = keysToEcdhJwk(pub)
  11. const props = Object.assign(
  12. S.ecdh,
  13. { public: await ecdhSubtle.importKey(...pubKeyData, true, []) }
  14. )
  15. const privKeyData = keysToEcdhJwk(epub, epriv)
  16. const derived = await ecdhSubtle.importKey(...privKeyData, false, ['deriveKey'])
  17. .then(async (privKey) => {
  18. // privateKey scope doesn't leak out from here!
  19. const 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. const r = derived;
  23. if(cb){ try{ cb(r) }catch(e){console.log(e)} }
  24. return r;
  25. } catch(e) {
  26. SEA.err = e;
  27. if(cb){ cb() }
  28. return;
  29. }}
  30. const keysToEcdhJwk = (pub, d) => { // d === priv
  31. //const [ x, y ] = Buffer.from(pub, 'base64').toString('utf8').split(':') // old
  32. const [ x, y ] = pub.split('.') // new
  33. const jwk = d ? { d: d } : {}
  34. return [ // Use with spread returned value...
  35. 'jwk',
  36. Object.assign(
  37. jwk,
  38. { x: x, y: y, kty: 'EC', crv: 'P-256', ext: true }
  39. ), // ??? refactor
  40. S.ecdh
  41. ]
  42. }
  43. module.exports = SEA.secret;