如何将 Web 加密密钥导出到 jsrsasign
How to export Web Crypto key to jsrsasign
我尝试使用 Web Crypto and use it to sign a string with jsrsasign () 生成 RSA 密钥。因此,我导出 Web 加密密钥并将其转换为 PKCS8-PEM,但是当我调用 KEYUTIL.getKeyFromPlainPrivatePKCS8PEM
将密钥导入 jsrsasign 时,抛出错误:格式错误的普通 PKCS8 私钥(代码:001 )
我做错了什么? JSBin
window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {name: "SHA-256"},
},
true,
["encrypt", "decrypt"]
)
.then(keyPair => window.crypto.subtle.exportKey("pkcs8", keyPair.privateKey))
.then(arrayBufferToBase64String)
.then(toPem)
.then(pem => {
var rsa = KEYUTIL.getKeyFromPlainPrivatePKCS8PEM(pem); // throws: malformed plain PKCS8 private key(code:001)
var sig = rsa.signStringPSS('text', 'sha256', 32);
console.log('signature', sig);
})
.catch(::console.error)
function arrayBufferToString(arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer)
var byteString = '';
for (var i=0; i<byteArray.byteLength; i++) {
byteString += String.fromCharCode(byteArray[i]);
}
return byteString;
}
function arrayBufferToBase64String(arrayBuffer) {
return btoa(arrayBufferToString(arrayBuffer));
}
function toPem(key) {
return `
-----BEGIN RSA PRIVATE KEY-----
${key}
-----END RSA PRIVATE KEY-----
`;
}
编辑:
我刚刚意识到 jsrsasign 可以处理 jwk:
window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {name: "SHA-256"},
},
true,
["encrypt", "decrypt"]
)
.then(keyPair => window.crypto.subtle.exportKey("jwk", keyPair.privateKey))
.then(jwk => {
var rsa = KEYUTIL.getKey(jwk);
var sig = rsa.signStringPSS('text', 'sha256', 32);
console.log('signature', sig);
})
.catch(::console.error)
我更喜欢这个解决方案,但我仍然想知道为什么我的 pkcs8 解决方案不起作用。
由于 'RSA' 部分,您的 PEM 编码密钥实际上是 PKCS#1 而不是 PKCS#8。这只是 DER 中的 RSA 密钥 object,没有包含在序列中的密钥标识符。
jsrsasign 正在寻找 PKCS#8 header "BEGIN PRIVATE KEY" 而不是 "BEGIN RSA PRIVATE KEY"。更改 header 使其工作。
将 PEM header 从 "----BEGIN RSA PRIVATE KEY-----"
更改为 "-----BEGIN PRIVATE KEY-----"
是行不通的,因为内容不同。我认为使用 JWK 进行文件导出是执行此操作的最佳方式,因为它在任何浏览器之间具有很大的互操作性。我以前尝试过同样的事情,但是 PKCS#8 在某些浏览器上不起作用。
如 Felix 所述,您的 RSA 密钥是一个 PKCS#1 密钥,其中包含 "-----BEGIN RSA PRIVATE KEY-----"
PEM header.
如果需要将PKCS#1转换为PKCS#8密钥KEYUTILclass 可能很有用,就像这个例子:
keyobj = KEYUTIL.getKey("-----BEGIN RSA PRIVATE KEY-----..."); // your key
pkcs8pem = KEYUTIL.getPEM(keyobj, "PKCS8PRV");
我尝试使用 Web Crypto and use it to sign a string with jsrsasign (KEYUTIL.getKeyFromPlainPrivatePKCS8PEM
将密钥导入 jsrsasign 时,抛出错误:格式错误的普通 PKCS8 私钥(代码:001 )
我做错了什么? JSBin
window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {name: "SHA-256"},
},
true,
["encrypt", "decrypt"]
)
.then(keyPair => window.crypto.subtle.exportKey("pkcs8", keyPair.privateKey))
.then(arrayBufferToBase64String)
.then(toPem)
.then(pem => {
var rsa = KEYUTIL.getKeyFromPlainPrivatePKCS8PEM(pem); // throws: malformed plain PKCS8 private key(code:001)
var sig = rsa.signStringPSS('text', 'sha256', 32);
console.log('signature', sig);
})
.catch(::console.error)
function arrayBufferToString(arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer)
var byteString = '';
for (var i=0; i<byteArray.byteLength; i++) {
byteString += String.fromCharCode(byteArray[i]);
}
return byteString;
}
function arrayBufferToBase64String(arrayBuffer) {
return btoa(arrayBufferToString(arrayBuffer));
}
function toPem(key) {
return `
-----BEGIN RSA PRIVATE KEY-----
${key}
-----END RSA PRIVATE KEY-----
`;
}
编辑:
我刚刚意识到 jsrsasign 可以处理 jwk:
window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {name: "SHA-256"},
},
true,
["encrypt", "decrypt"]
)
.then(keyPair => window.crypto.subtle.exportKey("jwk", keyPair.privateKey))
.then(jwk => {
var rsa = KEYUTIL.getKey(jwk);
var sig = rsa.signStringPSS('text', 'sha256', 32);
console.log('signature', sig);
})
.catch(::console.error)
我更喜欢这个解决方案,但我仍然想知道为什么我的 pkcs8 解决方案不起作用。
由于 'RSA' 部分,您的 PEM 编码密钥实际上是 PKCS#1 而不是 PKCS#8。这只是 DER 中的 RSA 密钥 object,没有包含在序列中的密钥标识符。
jsrsasign 正在寻找 PKCS#8 header "BEGIN PRIVATE KEY" 而不是 "BEGIN RSA PRIVATE KEY"。更改 header 使其工作。
将 PEM header 从 "----BEGIN RSA PRIVATE KEY-----"
更改为 "-----BEGIN PRIVATE KEY-----"
是行不通的,因为内容不同。我认为使用 JWK 进行文件导出是执行此操作的最佳方式,因为它在任何浏览器之间具有很大的互操作性。我以前尝试过同样的事情,但是 PKCS#8 在某些浏览器上不起作用。
如 Felix 所述,您的 RSA 密钥是一个 PKCS#1 密钥,其中包含 "-----BEGIN RSA PRIVATE KEY-----"
PEM header.
如果需要将PKCS#1转换为PKCS#8密钥KEYUTILclass 可能很有用,就像这个例子:
keyobj = KEYUTIL.getKey("-----BEGIN RSA PRIVATE KEY-----..."); // your key
pkcs8pem = KEYUTIL.getPEM(keyobj, "PKCS8PRV");