11

Sto provando a firmare i dati utilizzando l'API WebCrypto, ma invece di creare una chiave privata/pubblica ed esportarla in pkcs # 1 o 8, vorrei davvero piace utilizzare PKCS # 12 di un utente per firmare i dati. Ho letto le specifiche del W3C, ma non ne posso fare molto e non riesco a trovare alcun materiale valido su come farlo. In questo momento voglio lasciare da parte ActiveX e Java Applet. C'è un modo per modificare:Come caricare un certificato digitale PKCS # 12 con 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 

Eventuali puntatori?

UPDATE Ecco il codice che ho lavorato

<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

Al momento WebCrypto non è ancora pronto per cose del genere –

+0

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

risposta

8

Web API di crittografia non supporta PKCS # 12. È possibile utilizzare una libreria di terze parti per decodificare il p12 come forgiare https://github.com/digitalbazaar/forge#pkcs12 e del carico PrivateKey in webcrypto

Leggendo il certificato PKCS # 12

PKCS # 12 è memorizzato in DER, così abeti t leggerlo da un file o utilizzare un pre-memorizzati 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); 

Decodifica PKCS # 12 con la forgia e estrarre chiave

Poi decodificare formato privato DER a ASN1, e lasciare che forgia legge il contenuto

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

quindi ottenere la chiave privata dal pkcs12 del certificato desiderato (vedi forgiare doc) e convertire in PKCS # 8 per essere importato con 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...   
     } 
    } 
} 

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

chiave Importa in Webcrypto

E infine importare la chiave nella 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!!! 
     }); 

Firma digitale

Con il cryptoKey importato restituito dal metodo precedente è possibile firmare con 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)) 
}); 

includo codifica da Base64 perché conversioni di dati non sono banali

In pkc12 si ha anche la catena di certificazione, se avete bisogno di costruire formati avanzati come AdES

+0

Esiste un template html + css predefinito che devo seguire con la libreria forge. Ottengo errore come: "Uncaught TypeError: Impossibile leggere la proprietà 'Class' di undefined pkcs12.js: 109" – lumee

+0

anche: util.js: 1569 Uncaught TypeError: input.replace non è una funzione util.js.1569 e molti altri errori. Ho scaricato una versione recente da github – lumee

+0

Forge è javascript puro. Non hai bisogno di html o css. Hai costruito i js minificati? Non importare i file di origine uno per uno perché sono delle dipendenze. Per favore, fornisci anche i dettagli del codice che stai eseguendo – pedrofb