admin管理员组文章数量:1430533
I am trying to create the following flow:
- Create a keypair on the client
- Send the public key to the server (nodejs)
- Encrypt a string on the server using a WebCryptoAPI polyfill
- 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]"
});
I am trying to create the following flow:
- Create a keypair on the client
- Send the public key to the server (nodejs)
- Encrypt a string on the server using a WebCryptoAPI polyfill https://github./PeculiarVentures/node-webcrypto-ossl
- 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]"
});
Share
Improve this question
edited Mar 23, 2018 at 18:04
dendog
asked Mar 23, 2018 at 17:11
dendogdendog
3,3685 gold badges33 silver badges70 bronze badges
4
- to encrypt and decrypt you need to have a shared key between both partie – Abslen Char Commented Mar 23, 2018 at 17:14
- assymetric keys work just fine @AbdeslemCharif – dendog Commented Mar 23, 2018 at 17:43
- Why not just use HTTPS, it provided plete e2e encryption. – zaph Commented Mar 23, 2018 at 17:49
- @zaph this is part of a bigger project for authentication – dendog Commented Mar 23, 2018 at 17:50
2 Answers
Reset to default 4SOLVED!
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.
Consider taking a look at a higher level library that deals with the exchange problems for you; for example js-jose https://github./square/js-jose/tree/master/examples or PKIjs https://pkijs/examples/CMSEnvelopedExample.html.
本文标签: javascriptEncrypt in Nodejs and decrypt on the client using WebCrypto APIStack Overflow
版权声明:本文标题:javascript - Encrypt in Nodejs and decrypt on the client using WebCrypto API - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745521614a2661650.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论