将 webcrypto 密钥导出为 PEM 格式
Export webcrypto key to PEM format
我正在使用带有 RSASSA-PKCS1-v1_5 (https://github.com/diafygi/webcrypto-examples#rsassa-pkcs1-v1_5---sign) 的 WebCrypto,我需要使用 javascript 代码将 public 密钥导出为 PEM 格式。
文档说可以用这种方式导出密钥:
https://github.com/diafygi/webcrypto-examples#rsassa-pkcs1-v1_5---exportkey
但我需要不同的格式。
有什么想法吗?
提前致谢。
此致
将 public 密钥导出到 spki
window.crypto.subtle.exportKey("spki",keys.publicKey);
并将生成的数组缓冲区转换为 base64 添加 PEM headers -----BEGIN PUBLIC KEY-----
和 -----END PUBLIC KEY-----
。下面我为函数 spkiToPEM
提供了一个完整的示例
crypto.subtle.generateKey(
{
name: "RSASSA-PKCS1-v1_5",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {name: "SHA-256"},
},
false,
["sign", "verify"]
).then(function(keys){
return window.crypto.subtle.exportKey("spki",keys.publicKey);
}).then (function(keydata){
var pem = spkiToPEM(keydata);
console.log(pem);
}).catch(function(err){
console.error(err);
});
function spkiToPEM(keydata){
var keydataS = arrayBufferToString(keydata);
var keydataB64 = window.btoa(keydataS);
var keydataB64Pem = formatAsPem(keydataB64);
return keydataB64Pem;
}
function arrayBufferToString( buffer ) {
var binary = '';
var bytes = new Uint8Array( buffer );
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return binary;
}
function formatAsPem(str) {
var finalString = '-----BEGIN PUBLIC KEY-----\n';
while(str.length > 0) {
finalString += str.substring(0, 64) + '\n';
str = str.substring(64);
}
finalString = finalString + "-----END PUBLIC KEY-----";
return finalString;
}
浏览器不支持spki
格式,您基本上必须使用jwt
才能跨浏览器互操作。
您可以在此处查看 spki
的示例 - https://github.com/PeculiarVentures/PKI.js/blob/5b9c35c154c48b232b45cc2a908c88e2f56a8447/src/CryptoEngine.js#L55
如果有人正在寻找更现代的解决方案,这里是@pedrofb 在 es-next
中的解决方案:
const getPublicKey = async () => {
const options = {
name: 'RSASSA-PKCS1-v1_5',
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: { name: 'SHA-256' },
};
const keys = await window.crypto.subtle.generateKey(
options,
false, // non-exportable (public key still exportable)
['sign', 'verify'],
);
const publicKey = await window.crypto.subtle.exportKey('spki', keys.publicKey);
let body = window.btoa(String.fromCharCode(...new Uint8Array(publicKey)));
body = body.match(/.{1,64}/g).join('\n');
return `-----BEGIN PUBLIC KEY-----\n${body}\n-----END PUBLIC KEY-----`;
};
使用:
getPublicKey().then(value => console.log(value));
输出:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2NYY4J3mY6DjmhwxRRK9
UMdTx7RnoteFAAlaqkV3jff3o+O8h/NtAi1jnsrMp6SOewdO9Ae8htV5CK7WZ3yX
cJ5hR5yGCcgKcDYSP1PKb9aqp4vGOjrbAhTcJyIs/qjBqtxcYY/oICKMV3Lmmf/E
WJKtXaKJBk5v97XuBuX1ccaNaU7WxW5QayR0kR0oyJh21WJjHaVQEoLABIao+8fy
d/p2nu/BLvPrtIy76M+VrfK0V45ODC0dolx0XtWRhI9odrBBayOvuIwa4nrLYI0W
Y2QW5aQM5R7JddA6KxiVsQr3JsWncEdw/wOkMtKXMEQcmqLldDQgGCOVNxy4saRl
VwIDAQAB
-----END PUBLIC KEY-----
我正在使用带有 RSASSA-PKCS1-v1_5 (https://github.com/diafygi/webcrypto-examples#rsassa-pkcs1-v1_5---sign) 的 WebCrypto,我需要使用 javascript 代码将 public 密钥导出为 PEM 格式。
文档说可以用这种方式导出密钥: https://github.com/diafygi/webcrypto-examples#rsassa-pkcs1-v1_5---exportkey 但我需要不同的格式。
有什么想法吗?
提前致谢。
此致
将 public 密钥导出到 spki
window.crypto.subtle.exportKey("spki",keys.publicKey);
并将生成的数组缓冲区转换为 base64 添加 PEM headers -----BEGIN PUBLIC KEY-----
和 -----END PUBLIC KEY-----
。下面我为函数 spkiToPEM
提供了一个完整的示例
crypto.subtle.generateKey(
{
name: "RSASSA-PKCS1-v1_5",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {name: "SHA-256"},
},
false,
["sign", "verify"]
).then(function(keys){
return window.crypto.subtle.exportKey("spki",keys.publicKey);
}).then (function(keydata){
var pem = spkiToPEM(keydata);
console.log(pem);
}).catch(function(err){
console.error(err);
});
function spkiToPEM(keydata){
var keydataS = arrayBufferToString(keydata);
var keydataB64 = window.btoa(keydataS);
var keydataB64Pem = formatAsPem(keydataB64);
return keydataB64Pem;
}
function arrayBufferToString( buffer ) {
var binary = '';
var bytes = new Uint8Array( buffer );
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return binary;
}
function formatAsPem(str) {
var finalString = '-----BEGIN PUBLIC KEY-----\n';
while(str.length > 0) {
finalString += str.substring(0, 64) + '\n';
str = str.substring(64);
}
finalString = finalString + "-----END PUBLIC KEY-----";
return finalString;
}
浏览器不支持spki
格式,您基本上必须使用jwt
才能跨浏览器互操作。
您可以在此处查看 spki
的示例 - https://github.com/PeculiarVentures/PKI.js/blob/5b9c35c154c48b232b45cc2a908c88e2f56a8447/src/CryptoEngine.js#L55
如果有人正在寻找更现代的解决方案,这里是@pedrofb 在 es-next
中的解决方案:
const getPublicKey = async () => {
const options = {
name: 'RSASSA-PKCS1-v1_5',
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: { name: 'SHA-256' },
};
const keys = await window.crypto.subtle.generateKey(
options,
false, // non-exportable (public key still exportable)
['sign', 'verify'],
);
const publicKey = await window.crypto.subtle.exportKey('spki', keys.publicKey);
let body = window.btoa(String.fromCharCode(...new Uint8Array(publicKey)));
body = body.match(/.{1,64}/g).join('\n');
return `-----BEGIN PUBLIC KEY-----\n${body}\n-----END PUBLIC KEY-----`;
};
使用:
getPublicKey().then(value => console.log(value));
输出:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2NYY4J3mY6DjmhwxRRK9
UMdTx7RnoteFAAlaqkV3jff3o+O8h/NtAi1jnsrMp6SOewdO9Ae8htV5CK7WZ3yX
cJ5hR5yGCcgKcDYSP1PKb9aqp4vGOjrbAhTcJyIs/qjBqtxcYY/oICKMV3Lmmf/E
WJKtXaKJBk5v97XuBuX1ccaNaU7WxW5QayR0kR0oyJh21WJjHaVQEoLABIao+8fy
d/p2nu/BLvPrtIy76M+VrfK0V45ODC0dolx0XtWRhI9odrBBayOvuIwa4nrLYI0W
Y2QW5aQM5R7JddA6KxiVsQr3JsWncEdw/wOkMtKXMEQcmqLldDQgGCOVNxy4saRl
VwIDAQAB
-----END PUBLIC KEY-----