2015-11-16 4 views
0

J'essaie de générer une clé RSA avec Web Crypto et l'utiliser pour signer une chaîne avec jsrsasign (Firefox does not support RSA-PSS). Par conséquent, exporter la clé Crypto Web et de le convertir à PKCS8-PEM, mais quand je l'appelle KEYUTIL.getKeyFromPlainPrivatePKCS8PEM importer la clé de jsrsasign une erreur est renvoyée: plaine malformé clé privée PKCS8 (code: 001)Comment exporter la clé Web Crypto vers jsrsasign

Qu'est-ce que J'ai tort? 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----- 
`; 
} 

Edit:

Je viens de réaliser que jsrsasign peut gérer 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) 

Je préfère cette solution, mais j'aime toujours savoir pourquoi ma solution pkcs8 ne ne fonctionne pas.

Répondre

1

Votre clé codée PEM est en réalité PKCS # 1 et non PKCS # 8 en raison de la partie 'RSA'. C'est juste l'objet clé RSA dans DER sans l'identificateur de clé encapsulé dans une séquence. Jsrsasign recherche un en-tête PKCS # 8 "BEGIN PRIVATE KEY" et non "BEGIN RSA PRIVATE KEY". Changer l'en-tête le fait fonctionner.

2

Cela ne fonctionne pas en changeant l'en-tête PEM de "----BEGIN RSA PRIVATE KEY-----" à "-----BEGIN PRIVATE KEY-----" puisque le contenu est différent. Je pense qu'utiliser JWK pour l'exportation de fichier est la meilleure façon de le faire, car il aura beaucoup d'interopérabilité entre n'importe quel navigateur. J'ai essayé la même chose avant cependant PKCS # 8 ne fonctionne pas sur certains navigateurs.

Comme Felix décrit, votre RSA clé est un PKCS # 1 clé qui a "-----BEGIN RSA PRIVATE KEY-----"tête PEM.

Si vous devez convertir PKCS # 1 à PKCS # 8 clé KEYUTIL classe peut être utile comme dans cet exemple:

keyobj = KEYUTIL.getKey("-----BEGIN RSA PRIVATE KEY-----..."); // your key 
pkcs8pem = KEYUTIL.getPEM(keyobj, "PKCS8PRV");