4

I am trying to create the following flow:

  1. Create a keypair on the client
  2. Send the public key to the server (nodejs)
  3. Encrypt a string on the server using a WebCryptoAPI polyfill https://github.com/PeculiarVentures/node-webcrypto-ossl
  4. Send the encrypted data back to the client for decryption

I am struggling (for a long time time) with the data types.

Below is the code, first to generate the keys (client):

// some reusable settings objects const crypto = window.crypto.subtle; let publicKeyToExport = {}; let privateKeyToStore = {}; // function called to create a keypair const generateKeypair = () => { crypto.generateKey({ name : 'RSA-OAEP', modulusLength : 2048, //can be 1024, 2048, or 4096 publicExponent : new Uint8Array([0x01, 0x00, 0x01]), hash : {name: 'SHA-256'}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512" }, true, ['encrypt', 'decrypt'] ).then((key) => { publicKeyToExport = key.publicKey; privateKeyToStore = key.privateKey; console.log(key); }).catch((err) => { console.error(err); }); }; 

Then to export:

// function to export the generate publicKey const exportPublicKey = (publicKey) => { crypto.exportKey('jwk', publicKey) .then((keydata) => { fetch('/key2', { method : 'POST', mode : 'cors', body : JSON.stringify(keydata), headers : new Headers({ 'Content-Type' : 'application/json' }) }).then(res => res.json()) .catch(err => console.error(err)) .then(res => console.log(res)); console.log(keydata); }) .catch((err) => { console.log(err); }); }; 

Save the key:

app.post('/key2', (req, res) => { webcrypto.subtle.importKey( 'jwk', req.body, { name : 'RSA-OAEP', hash : {name : 'SHA-256'}, }, false, ['encrypt'] ).then((publicKey) => { keyStorage.setItem('alicePubKey', publicKey); if(publicKey == keyStorage.getItem('alicePubKey')); res.json({ 'success' : 'key received and saved' }); console.log('saved key from client: ' + publicKey); return; }) .catch((err) => { console.error(err); }); }); 

Encrypt on server:

app.get('/challenge', (req, res) => { let challengeFromServer = null; let key = keyStorage.getItem('alicePubKey'); let buf = new Buffer.from('decryptthis!'); webcrypto.subtle.encrypt( { name : 'RSA-OAEP' }, key, buf ) .then((encrypted) => { console.log('challenge created: ' + encrypted); res.json({'challenge' : new Uint8Array(encrypted) }) }) .catch((err) => { console.error(err); }) 

Get encrypted data and decrypt - not working :)

const requestChallenge = () => { fetch('/challenge') .then((res) => { return res.json(); }) .then((data) => { console.log(data); console.log(ArrayBuffer.isView(data.challenge)) console.log(new ArrayBuffer(data.challenge)) crypto.decrypt({ name : 'RSA-OAEP' }, privateKeyToStore, new ArrayBuffer(data.challenge)) .then((decrypted)=>{ console.log(decrypted) }) .catch(err => console.error(err)); }) .catch(err => console.error(err)); }; 

The following lines are the issue I think!

console.log(ArrayBuffer.isView(data.challenge)) // false console.log(new ArrayBuffer(data.challenge)) // empty 

Small update:

 res.json( {'challenge' : encrypted , // {} empty 'uint' : new Uint8Array(encrypted), // {0: 162, 1: 252, 2: 113, 3: 38, ....... 'stringify' : JSON.stringify(encrypted), // "{}" empty 'toString' : encrypted.toString() // "[object ArrayBuffer]" }); 
4
  • to encrypt and decrypt you need to have a shared key between both partie Commented Mar 23, 2018 at 17:14
  • assymetric keys work just fine @AbdeslemCharif Commented Mar 23, 2018 at 17:43
  • Why not just use HTTPS, it provided complete e2e encryption. Commented Mar 23, 2018 at 17:49
  • @zaph this is part of a bigger project for authentication Commented Mar 23, 2018 at 17:50

2 Answers 2

4

SOLVED!

The issue was with data types.

The way to solve this if anyone has the issue is to ensure on your server you send your ciphertext as a Buffer, my express app:

res.write(new Buffer(encrypted), 'binary') res.end(null, 'binary') 

And on the client receive it and decode, as below:

const decryptedReadable = new TextDecoder().decode(decrypted) 

Happy coding.

Sign up to request clarification or add additional context in comments.

Comments

0

Consider taking a look at a higher level library that deals with the exchange problems for you; for example js-jose https://github.com/square/js-jose/tree/master/examples or PKIjs https://pkijs.org/examples/CMSEnvelopedExample.html.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.