11

J'essaie de signer des données en utilisant l'API WebCrypto, mais au lieu de créer une clé privée/publique et de l'exporter vers pkcs # 1 ou 8, je voudrais vraiment aime utiliser le PKCS # 12 d'un utilisateur pour signer des données. J'ai lu la spécification du W3C, mais je ne peux pas en faire grand-chose et je ne trouve aucun bon document sur la façon de le faire. En ce moment, je veux laisser les applets Java et ActiveX de côté. Y at-il un moyen de modifier les éléments suivants:Comment charger un certificat numérique PKCS # 12 avec Javascript WebCrypto API

var buffer = encode(prompt("Please enter your password")); 
    //TODO: 
    //implement a prompt for a pfx or cert 

    return crypto.subtle.importKey("raw", buffer, "PBKDF2", false, usages); 
    //TODO: 
    //instead of importing it, ask for the certificate's pass to sign data 
    //with crypto.subtle.sign 

Des pointeurs?

MISE À JOUR Voici le code que je travaille

<script src="forge.min.js"></script> 

<script> 
    var errorsReportedByVerifier; 
    errorsReportedByVerifier = checkStorage() && checkBrowserAPIs(); 
    if (!errorsReportedByVerifier){ 
     console.log("adding click event"); 
     document.getElementById('btnPfx').addEventListener('click', handlePFXFile, false); 
     storeVariables(); 
     getVariables(); 
    } 


    function handlePFXFile(evnt) { 
     console.log("handling pfx") 
     //alert(document.getElementById('pfx').value); 

     //error happens in 1st line 
     //error object does not accept property replace 
     //forge.min.js Line 1, Column: 17823 
     var p12Der = forge.util.decode64(document.getElementById('pfx').valueOf()); 
     //var pkcs12Asn1 = forge.asn1.fromDer(p12Der); 
     //var pkcs12 = forge.pkcs12.pkcs12FromAsn1(pkcs12Asn1, false, 'pss'); 
     console.log("pkcs12"); 
    } 
</script> 
+0

Au moment WebCrypto est pas encore prêt pour de telles choses. –

+0

@Eugene Mayevski 'EldoS Corp, ok, pkcs8 c'est, thx – lumee

Répondre

8

cryptographie Web api ne prend pas en charge PKCS # 12. Vous pouvez utiliser une bibliothèque tierce partie pour décoder le p12 comme forger https://github.com/digitalbazaar/forge#pkcs12 et charge privateKey dans webcrypto

lecture du certificat PKCS # 12

PKCS # 12 est stocké dans DER, si sapins t le lire à partir d'un fichier ou d'utiliser un base64

//Reading certificate from a 'file' form field 
var reader = new FileReader(); 
reader.onload = function(e) {    
    var contents = e.target.result; 
    var pkcs12Der = arrayBufferToString(contents) 
    var pkcs12B64 = forge.util.encode64(pkcs12Der);  
    //do something else... 

} 
reader.readAsArrayBuffer(file); 

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; 
} 

//p12 certificate stored in Base64 format 
var pkcs12Der= forge.util.decode64(pkcs12B64); 

Decode PKCS # 12 avec forge et l'extrait clé privée

préenregistrée décoder ensuite le format DER à ASN1, et nous forge lit le contenu

var pkcs12Asn1 = forge.asn1.fromDer(pkcs12Der); 
var pkcs12 = forge.pkcs12.pkcs12FromAsn1(pkcs12Asn1, false, password); 

ensuite obtenir la clé privée de pkcs12 du certificat souhaité (voir doc forger) et convertir PKCS # 8 à importer avec webcrypto

// load keypair and cert chain from safe content(s) 
for(var sci = 0; sci < pkcs12.safeContents.length; ++sci) { 
    var safeContents = pkcs12.safeContents[sci]; 

    for(var sbi = 0; sbi < safeContents.safeBags.length; ++sbi) { 
     var safeBag = safeContents.safeBags[sbi]; 

     // this bag has a private key 
     if(safeBag.type === forge.pki.oids.keyBag) { 
      //Found plain private key 
      privateKey = safeBag.key; 
     } else if(safeBag.type === forge.pki.oids.pkcs8ShroudedKeyBag) { 
      // found encrypted private key 
      privateKey = safeBag.key; 
     } else if(safeBag.type === forge.pki.oids.certBag) { 
      // this bag has a certificate...   
     } 
    } 
} 

Convertir en PKCS # 8

function _privateKeyToPkcs8(privateKey) { 
    var rsaPrivateKey = forge.pki.privateKeyToAsn1(privateKey); 
    var privateKeyInfo = forge.pki.wrapRsaPrivateKey(rsaPrivateKey); 
    var privateKeyInfoDer = forge.asn1.toDer(privateKeyInfo).getBytes(); 
    var privateKeyInfoDerBuff = stringToArrayBuffer(privateKeyInfoDer); 
    return privateKeyInfoDerBuff; 
} 
function stringToArrayBuffer(data){ 
    var arrBuff = new ArrayBuffer(data.length); 
    var writer = new Uint8Array(arrBuff); 
    for (var i = 0, len = data.length; i < len; i++) { 
     writer[i] = data.charCodeAt(i); 
    } 
    return arrBuff; 
    } 

clé importation dans Webcrypto

Et enfin importer la clé dans webcrypto

function _importCryptoKeyPkcs8(privateKey,extractable) { 
    var privateKeyInfoDerBuff = _privateKeyToPkcs8(privateKey); 

    //Import the webcrypto key 
    return crypto.subtle.importKey(
      'pkcs8', 
      privateKeyInfoDerBuff, 
      { name: "RSASSA-PKCS1-v1_5", hash:{name:"SHA-256"}}, 
      extractable, 
      ["sign"]);   

} 
_importCryptoKeyPkcs8(entry.privateKey,extractable).  
     then(function(cryptoKey) { 
      //your cryptokey is here!!! 
     }); 

signature numérique

Avec la clé crypto importée renvoyée à l'aide de la méthode ci-dessus, vous pouvez signer avec Webcrypto.

var digestToSign = forge.util.decode64(digestToSignB64); 
var digestToSignBuf = stringToArrayBuffer(digestToSign); 

crypto.subtle.sign(
      {name: "RSASSA-PKCS1-v1_5"}, 
      cryptoKey, 
      digestToSignBuf) 
.then(function(signature){ 
    signatureB64 = forge.util.encode64(arrayBufferToString(signature)) 
}); 

I comprennent le codage de base64, car les conversions de données ne sont pas négligeables

En pkc12 vous avez également la chaîne de certification si vous avez besoin de construire des formats avancés comme AdES

+0

Y at-il un modèle prédéfini html + css que je dois suivre avec la bibliothèque de la forge. Je reçois une erreur comme: "Uncaught TypeError: Impossible de lire la propriété 'Class' de pkcs12.js non défini: 109" – lumee

+0

aussi: util.js: 1569 Uncaught TypeError: entrée.remplacer n'est pas une fonction util.js.1569 et plusieurs autres erreurs. J'ai téléchargé une version récente de github – lumee

+0

Forge est pure javascript. Vous n'avez pas besoin de HTML ou CSS. Avez-vous construit le .js minifié? N'importez pas les fichiers source un par un parce que ce sont des dépendances. S'il vous plaît, fournissez également les détails du code que vous exécutez – pedrofb