I have 2 different web software. At one of them I want to encrypt user's data in browser using public key from the server and store encrypted user's data at database. After that I want to have possibility to decrypt those data on server side or browser.
I tried to create proof of concept - It works with keys that were generated by Web Cypto API itself but fail with keys from another source.
How to reproduce:
I've create RSA keys using OpenSSL Ruby standard library
require 'openssl'
rsa = OpenSSL::PKey::RSA.new(2048)
puts rsa.to_s
puts rsa.public_key.to_s
I'm trying to use them to encrypt/decrypt messages via Web Crypto API.
However I've encountered and error while importing private key.
In DevTools I see it as Error
without a backtrace.
Could someone advice How can I achieve by goal?
function arrayBufferToString(buf) {
let bytes = new Uint8Array(buf);
return bytes.reduce((str, byte) => str + String.fromCharCode(byte), "");
}
function stringToArrayBuffer(str) {
let buf = new ArrayBuffer(str.length);
let bufView = new Uint8Array(buf);
for (var i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
function base64ToBinary(str) {
return atob(str);
}
function binaryToBase64(str) {
return btoa(str);
}
(async function main() {
console.clear();
var content = "hello world!"; //+ Math.random();
console.log("content: ", content);
let algorithmOptions = {
name: "RSA-OAEP",
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256"
};
let rsaPrivate =
"-----BEGIN RSA PRIVATE KEY-----\n" +
"MIIEogIBAAKCAQEAqnXo4TWhiUaDpiQBArFq5B22JB2ebKlAvQMbDrOakK8Tactj\n" +
"zg64ZTXwZhadVcfPwFvoS45O6LkIZL+o7F9N7WnlRiT5SXgwkPzQ75l2EcGqZKgK\n" +
"lyCl5THuD2RRMOTJI1bzmx8DO/f7LMHr3xUGtdHXzqICxIUwa5B0RTvHG/j6Wirk\n" +
"Z51ArwQa5ZrtyGXJoupgws0LZRuadJBkbIRUaaujv1pA25Dmzu7pODr3S2XWqIYy\n" +
"cfJqxgIGvNJ7LHTEPLBWh1xCc0MNf3C9cZNEsVmDgGCYS4oeKuBbUoqF6eirQHC6\n" +
"rkW+4KwE/Rvo6LZVrtl1vh6vI+rVt6wvoWydYQIDAQABAoIBAB+xZogg6ZTVaHrG\n" +
"bO2sQPyCza+vVhpL6b56ylgUaqOF+a0M5NSWBhDDU5wXjk85pFXWgL0zi1ZXuMjK\n" +
"ncS8/4cpzjgZfcP8NcNvTgWOWdZ5VI38dGOe7VlMzD9OXo4hq4gHjamEvZwzwh6T\n" +
"O6CxjxrVFjPUCYGyZctKA2Qv9hgsB9Nq7EV5z/VErN33OI1edHeMIdZ0tvahQNrY\n" +
"2It26hKsxSKAowm7H+NG0fJsVUmN0m1Ou0od9tqzX6XwOgycUvvdr5iHrECHFMDe\n" +
"be5iZ19evzai8gdxr4ZkWdF5P7+VltI7vlKpHKUvx/I/mO/XWq4yo4efEoLYWjfe\n" +
"Vz8OG7ECgYEA2yAesiDs3buYAQ8nEVje6sn/jr2PgtXXo6TXHbd3NNCnvbt71LWw\n" +
"5P8dUqqiIwKskjargEU0HphQKmUubnSdYdl+rLpwcCsRn/0kBX1+89vv7XWnn20i\n" +
"j07IUtsHev40xK3joJcJ1eHsHjkljJaMsRvGilo8V7eh5p8WkfDA4jUCgYEAxyVR\n" +
"DQSc0U/O9++euv9LVUxqISaSG866/k9HP++IKhcN3Gh3gcJJcMETgtH0sEa5ut9K\n" +
"AzC61OTZqpB+t1bVOpdzj2h4K0YVy2FVAB/wpZcoslrD4hC6Zh7tcUlfrdo3Pj+i\n" +
"1cJzqaqZDVv0Rtxwz9ekWkBi9V+pPWohntZas/0CgYBRTS2WcdjwvDW9zt1z9kFf\n" +
"Y+tKDtM8fBMySGr4P6YfFnvmTbW4SmGD1ZQPo/fcfZWB+n7PbN3VrDWyRTBhEyuB\n" +
"rqztcY9eTtyPO+EtmE6ONEBlHo4+/MMh4N06wMGZxM/XWZ1nbCLeFKEC5bkk3Ib+\n" +
"/4s+shRJh3yukMBTDbzDMQKBgH7Rtc7LfC4TW+MqdnPxNgEo+4EG9g69VPm0dNQz\n" +
"bwwWyF3vLQO2PVyPqCQsHl3PfGGT5qcndiMzZaYoBHou0vVQE2hlB/nO1PxCjIXa\n" +
"0T4yh9kk0g95xapY0a7OIh8tkvaSQdlMzqlimbsXLvWdVj4VvnU3AY3vEHCq0KQ9\n" +
"L1/lAoGAbRAVMic9JDVqjpxfjAeL1E9w30m59vDCIEjJdMGX5BHOea7iVbQshilb\n" +
"yo+1s+QfWVNT0jOTzo4VPRomRNbdEIMb5W/M3zv+cUAmnCJymHUBiBP0N+ZO8+g8\n" +
"lEB3MJBdfsiKxMiX69jcoU1fB8tAwwE3hWSmkNKuvvzjOgxhtgQ=\n" +
"-----END RSA PRIVATE KEY-----";
let rsaPrivateBase64String = rsaPrivate.split("\n").slice(1, -1).join("");
// console.log("rsaPrivateString", rsaPrivateBase64String);
let rsaPublic =
"-----BEGIN PUBLIC KEY-----\n" +
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqnXo4TWhiUaDpiQBArFq\n" +
"5B22JB2ebKlAvQMbDrOakK8Tactjzg64ZTXwZhadVcfPwFvoS45O6LkIZL+o7F9N\n" +
"7WnlRiT5SXgwkPzQ75l2EcGqZKgKlyCl5THuD2RRMOTJI1bzmx8DO/f7LMHr3xUG\n" +
"tdHXzqICxIUwa5B0RTvHG/j6WirkZ51ArwQa5ZrtyGXJoupgws0LZRuadJBkbIRU\n" +
"aaujv1pA25Dmzu7pODr3S2XWqIYycfJqxgIGvNJ7LHTEPLBWh1xCc0MNf3C9cZNE\n" +
"sVmDgGCYS4oeKuBbUoqF6eirQHC6rkW+4KwE/Rvo6LZVrtl1vh6vI+rVt6wvoWyd\n" +
"YQIDAQAB\n" +
"-----END PUBLIC KEY-----";
let rsaPublicBase64String = rsaPublic.split("\n").slice(1, -1).join("");
// console.log("rsaPublicBase64String", rsaPublicBase64String);
let pubKey = await crypto.subtle.importKey(
"spki",
stringToArrayBuffer(base64ToBinary(rsaPublicBase64String)),
algorithmOptions,
false, ["encrypt"]
);
console.log("pubKey", pubKey);
// >> ERROR IS ON STATEMENT BELOW
let privKey = await crypto.subtle.importKey(
"pkcs8",
stringToArrayBuffer(base64ToBinary(rsaPrivateBase64String)),
algorithmOptions,
false, ["decrypt"]
);
console.log("privKey", privKey);
let encryptedBuf = await crypto.subtle.encrypt({
name: "RSA-OAEP"
},
pubKey,
stringToArrayBuffer(content)
);
let encrypted = arrayBufferToString(encryptedBuf);
console.log("encrypted", binaryToBase64(encrypted));
let decryptedBuf = await crypto.subtle.decrypt({
name: "RSA-OAEP"
},
privKey,
stringToArrayBuffer(encrypted)
);
let decrypted = arrayBufferToString(decryptedBuf);
console.log("decrypted", decrypted);
})().catch(error => console.error(error));
Here's code sandbox link