4

我正在使用带有 RSASSA-PKCS1-v1_5 ( https://github.com/diafygi/webcrypto-examples#rsassa-pkcs1-v1_5---sign ) 的 WebCrypto,我需要使用 javascript 代码将公钥导出为 PEM 格式。

文档说可以通过这种方式导出密钥: https ://github.com/diafygi/webcrypto-examples#rsassa-pkcs1-v1_5---exportkey 但我需要不同的格式。

任何想法?

提前致谢。

问候

4

3 回答 3

14

将公钥导出到spki

window.crypto.subtle.exportKey("spki",keys.publicKey);

并将生成的数组缓冲区转换为 base64,添加 PEM 标头-----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;
}
于 2016-10-30T09:11:23.587 回答
2

如果有人正在寻找更现代的解决方案,这里是@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-----
于 2019-03-15T17:51:21.307 回答
0

spki格式不被浏览器很好地支持,您基本上必须使用jwt才能跨浏览器进行互操作。

你可以在spki这里看到一个例子 - https://github.com/PeculiarVentures/PKI.js/blob/5b9c35c154c48b232b45cc2a908c88e2f56a8447/src/CryptoEngine.js#L55

于 2017-02-03T03:47:15.590 回答