CryptoKey ArrayBuffer到base64和Back [英] CryptoKey ArrayBuffer to base64 and Back
问题描述
我想知道如何解决这个问题。我使用WebCrypto API生成RSA-OAEP密钥对,然后我从密钥对导出pkcs8中的私钥,该密钥对作为ArrayBuffer导出,我想将此ArrayBuffer编码为base64,因此我可以将其存储为PEM。
I was wondering how do I solve this problem. I generate RSA-OAEP keypair using WebCrypto API, then I export private key in pkcs8 from the keypair which exports as ArrayBuffer and I want to encode this ArrayBuffer into base64 so I can store it as a PEM.
在这个测试示例中,我将密钥导出为pkcs8并将此pkcs8导回到CryptoKey。问题在于它有时会起作用,有时却不起作用。
In this testing example I am exporting key as pkcs8 and importing this pkcs8 back to CryptoKey. The problem is that sometimes it works and sometimes it does not.
这些是代码的结果:
注意:只有这些状态中的一个不是全部发生在一旦。
注2:此示例不包含----- BEGIN PRIVATE KEY -----前缀和后缀我只对密钥进行编码。
These are results of the code: NOTE: Only happens one of these states not all at once. NOTE2: This example does not contain -----BEGIN PRIVATE KEY----- prefix and suffix I am only encoding the key.
Case1 :Uncaught(承诺)URIError:URI格式不正确(...)b64DecodeUnicode @ try.php:20b64toab @ try.php:70wayBack @ try.php:66(匿名函数)@ try.php:56
Case1: Uncaught (in promise) URIError: URI malformed(…)b64DecodeUnicode @ try.php:20b64toab @ try.php:70wayBack @ try.php:66(anonymous function) @ try.php:56
案例2:未定义:1未捕获(在承诺中)DOMException
Case2: undefined:1 Uncaught (in promise) DOMException
案例3:确定 - 一直有效。
Case3: OK - works all the way back.
我不知道导致错误的原因,但我认为它与base64编码有关。正如我所说,有时私钥生成正常,有时不生成。
I don't know what causes the errors but I think it has something to do with base64 encoding. As I said sometimes private key generates OK and sometimes not.
非常感谢你提前得到的每一个帮助。
Thank you very much for every help in advance.
function b64EncodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
function b64DecodeUnicode(str) {
return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
}
function addNewLines(str) {
var finalString = '';
for(var i=0; i < str.length; i++) {
finalString += str.substring(0, 64) + '\n';
str = str.substring(64);
}
return finalString;
}
window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {name: "SHA-256"}
},
true,
["encrypt", "decrypt"]
).then(function(keyPair) {
window.crypto.subtle.exportKey(
"pkcs8",
keyPair.privateKey
).then(function(exportedPrivateKey) {
var byteArray = new Uint8Array(exportedPrivateKey);
console.log(byteArray);
var byteString = '';
for(var i=0; i < byteArray.byteLength; i++) {
byteString += String.fromCodePoint(byteArray[i]);
}
wayBack(addNewLines(b64EncodeUnicode(byteString)));
});
});
function wayBack(pem) {
var lines = pem.split('\n');
var encodedString = '';
for(var i=0; i < lines.length; i++) {
encodedString += lines[i].trim();
}
b64toab(encodedString);
}
function b64toab(b64) {
var byteString = b64DecodeUnicode(b64);
console.log(byteString);
var byteArray = new Uint8Array(byteString.length);
for(var i=0; i < byteString.length; i++) {
byteArray[i] = byteString.codePointAt(i);
}
console.log(byteArray);
window.crypto.subtle.importKey(
"pkcs8",
byteArray,
{
name: "RSA-OAEP",
hash: {name: "SHA-256"}
},
true,
["decrypt"]
).then(function(importedPrivateKey) {
console.log(importedPrivateKey);
});
}
推荐答案
你忘了包含最后一个将字符串拆分为64个字符的块时PEM的一部分。只需将 finalString + = str;
添加到 addNewLines
You forgot to include the last part of PEM when you split the string in blocks of 64 characters. Just add finalString += str;
to addNewLines
function addNewLines(str) {
var finalString = '';
for(var i=0; i < str.length; i++) {
finalString += str.substring(0, 64) + '\n';
str = str.substring(64);
}
finalString += str;
return finalString;
}
我已经重构了你的例子,看看发生了什么。如果您认为有用,请使用以下代码
I have refactorized your example to see what is happening. Use the below code if you consider it useful
function b64EncodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
function b64DecodeUnicode(str) {
return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
}
function addNewLines(str) {
var finalString = '';
for(var i=0; i < str.length; i++) {
finalString += str.substring(0, 64) + '\n';
str = str.substring(64);
}
finalString += str;
return finalString;
}
function removeLines(pem) {
var lines = pem.split('\n');
var encodedString = '';
for(var i=0; i < lines.length; i++) {
encodedString += lines[i].trim();
}
return encodedString;
}
function stringToArrayBuffer(byteString){
var byteArray = new Uint8Array(byteString.length);
for(var i=0; i < byteString.length; i++) {
byteArray[i] = byteString.codePointAt(i);
}
return byteArray;
}
function arrayBufferToString(exportedPrivateKey){
var byteArray = new Uint8Array(exportedPrivateKey);
var byteString = '';
for(var i=0; i < byteArray.byteLength; i++) {
byteString += String.fromCodePoint(byteArray[i]);
}
return byteString;
}
window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {name: "SHA-256"}
},
true,
["encrypt", "decrypt"]
).then(function(keyPair) {
window.crypto.subtle.exportKey(
"pkcs8",
keyPair.privateKey
).then(function(exportedPrivateKey) {
var privateKeyDer = arrayBufferToString(exportedPrivateKey); //pkcs#8 to DER
var privateKeyB64 = b64EncodeUnicode(privateKeyDer); //btoa(privateKeyDer);
var privateKeyPEMwithLines = addNewLines(privateKeyB64); //split PEM into 64 character strings
var privateKeyPEMwithoutLines = removeLines(privateKeyPEMwithLines); //join PEM
var privateKeyDerDecoded = b64DecodeUnicode(privateKeyPEMwithoutLines); // atob(privateKeyB64);
var privateKeyArrayBuffer = stringToArrayBuffer(privateKeyDerDecoded); //DER to arrayBuffer
window.crypto.subtle.importKey( //importKEy
"pkcs8",
privateKeyArrayBuffer,
{
name: "RSA-OAEP",
hash: {name: "SHA-256"}
},
true,
["decrypt"]
).then(function(importedPrivateKey) {
console.log(importedPrivateKey);
});
});
});
这篇关于CryptoKey ArrayBuffer到base64和Back的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!