Is it possible to encrypt a CryptoKey (private key) with a string as a encryption key and just using the WebCryptoAPI? I implemented a function but I got the following error:
Uncaught (in promise) DOMException: AES key data must be 128 or 256 bits
Also, my function.
function encryptPrivateKey() {
var promise = new Promise(function (resolve, reject) {
try {
var key = new TextEncoder().encode(pwd);
var iv = crypto.getRandomValues(new Uint8Array(12));
var alg = {name: 'AES-CTR', iv: iv};
window.crypto.subtle.importKey('raw', key, alg, false, ['encrypt']).then(function (key) {
window.crypto.subtle.encrypt(alg, key, privateKeyPEM).then(function (key) {
privateKey = key;
})
});
resolve(privateKey);
} catch (err) {
reject(Error(err));
}
});
return promise.then(function (result) {
return result;
}, function (err) {
console.log(err);
});
}
It is, first of all please use an authenticated mode of encryption such as AES-GCM.
Secondly, you should consider using an existing format such as PKCS#8 for this task. You can see PKI.js for a library that can help you do this.
Another approach would be to encrypt the key into a CMS message, here is a sample that does just that: https://pkijs.org/examples/CMSEnvelopedPreDefineDataExample.html
You can look at it to see how to do the associated webcrypto even if you wanted to do a custom format.
Third, it is much better to not encrypt with a password, anything encrypted with a password will be grindable, it is always better to generate a solid symmetric key and use that instead of a derived password.
If you do use a password be sure to use PBDKF2 to stretch the password, https://github.com/diafygi/webcrypto-examples#pbkdf2. If you do this your above sample is going to end up working.
If you use one of the existing formats for keys they will send you down this path naturally.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With