11

Я пытаюсь подписать данные с использованием API WebCrypto, но вместо создания частного/открытого ключа и его экспорта в pkcs # 1 или 8 я бы действительно как использовать PKCS # 12 пользователя для подписи данных. Я читал спецификацию W3C, но не могу сделать много из этого и не могу найти хороший материал о том, как это сделать. Сейчас я хочу оставить ActiveX и Java Applets в стороне. Есть ли способ настроить следующее:Как загрузить цифровой сертификат PKCS №12 с помощью API Javascript WebCrypto

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 

Любые указатели?

UPDATE Вот код, я работаю

<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

На данный момент WebCrypto еще не готовы за такие вещи. –

+0

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

ответ

8

Web криптография апи не поддерживает PKCS # 12. Вы можете использовать библиотеку третьей стороны для декодирования p12, как подделать https://github.com/digitalbazaar/forge#pkcs12 и нагрузки PrivateKey в webcrypto

Считывание PKCS # 12 сертификат

PKCS # 12 хранится в DER, так пихты т читать из файла или использовать предварительно сохраненной 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 с горном и извлечь секретный ключ

Затем декодирует формат DER к ASN1, и пусть кузнечно считывает содержимое

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

Затем получить закрытый ключ от pkcs12 требуемого сертификата (см подделать документ) и конвертировать в PKCS # 8, которые будут импортированы с 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...   
     } 
    } 
} 

Преобразовать в 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; 
    } 

ключ импорта в Webcrypto

И, наконец, импортировать ключ в 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!!! 
     }); 

Цифровая подпись

С импортированным ключом cryptoKey, возвращенным из вышеуказанного метода, вы можете подписаться с помощью 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 включает в себя кодированием с base64, поскольку преобразование данных не является тривиальным

В pkc12 у вас также есть цепь сертификации, если вам нужно создать дополнительные форматы, такие как ADES

+0

Есть ли предопределенный шаблон html + css, который я должен соблюдать с помощью библиотеки forge. Я получаю ошибку, например: «Uncaught TypeError: Невозможно прочитать свойство« Класс »неопределенного pkcs12.js: 109« – lumee

+0

также: util.js: 1569 Uncaught TypeError: input.replace не является функцией util.js.1569 и несколькими другими ошибками. Я загрузил последнюю версию из github – lumee

+0

Forge - это чистый javascript. Вам не нужны html или css. Вы построили миниатюрный .js? Не импортируйте исходные файлы один за другим, потому что это зависимости. Пожалуйста, также указывайте детали кода, который вы выполняете. – pedrofb

 Смежные вопросы

  • Нет связанных вопросов^_^