2013-09-16 19 views
10

Sono bloccato con la cripto-api perché conosco poco della crittografia. Ho questoXML a PEM in Node.js

XML: 
<RSAKeyValue> 
    <Modulus>1znidPBIcMcO7K/53tkTSyKqxlG5Mcws8kVtijS4tyEU4W/FEVWYpOtv+Stnb4Vt</Modulus> 
    <Exponent>AQAB</Exponent> 
</RSAKeyValue> 

Signature: 
rNbdUP-p4pEGfwQSwR6VPvAVZ-sZu-ptgw8SofYYmNTlfUB9iUbb593eCAuT5jsqDTC 

Original data: 
<xml>...some big xml...</xml> 

Voglio verificare la firma, come faccio?

(sto usando nodo v0.10.18)

+1

La funzione crypto 'verify' di Node.js prevede che la chiave sia in formato PEM. La parte difficile qui è la conversione della chiave RSA XML in PEM. Non riesco a trovare nulla di scritto in javascript per farlo. Potrebbe essere necessario eseguire il porting su qualcosa come https://github.com/phpseclib/phpseclib/blob/master/phpseclib/Crypt/RSA.php#L866-922 su javascript. –

+1

Il "Dati originali:" è un documento XML con una firma xml? Se è così, avrai bisogno di più di qualcosa per verificare le firme digitali. Ho trovato un riferimento a [xml-crypto] (http://architects.dzone.com/articles/check-out-digital-signature) che può aiutare. – pd40

+1

I dati originali non sono un documento XML con la firma all'interno della sua struttura (come il collegamento che hai fornito). – dododedodonl

risposta

7

io non sono davvero un dev node.js, quindi questo è eccellente hacky .. Ecco una funzione che dovrebbe emettere un RSA a chiave pubblica PEM da Base64 modulo ed esponente. Vado basato sul commento di Trevor su node.js verify in attesa di un PEM.

Questa funzione compone una struttura DER AS.1 in esadecimale, quindi la decodifica esadecimale, quindi la codifica base64, quindi la inserisce a sandwich tra -----BEGIN PRIVATE KEY----- e -----END PRIVATE KEY-----. Dopotutto, è tutto un PEM.

function rsaPublicKeyPem(modulus_b64, exponent_b64) { 

    function prepadSigned(hexStr) { 
     msb = hexStr[0] 
     if (
      (msb>='8' && msb<='9') || 
      (msb>='a' && msb<='f') || 
      (msb>='A'&&msb<='F')) { 
      return '00'+hexStr; 
     } else { 
      return hexStr; 
     } 
    } 

    function toHex(number) { 
     var nstr = number.toString(16) 
     if (nstr.length%2==0) return nstr 
     return '0'+nstr 
    } 

    // encode ASN.1 DER length field 
    // if <=127, short form 
    // if >=128, long form 
    function encodeLengthHex(n) { 
     if (n<=127) return toHex(n) 
     else { 
      n_hex = toHex(n) 
      length_of_length_byte = 128 + n_hex.length/2 // 0x80+numbytes 
      return toHex(length_of_length_byte)+n_hex 
     } 
    } 

    var modulus = new Buffer(modulus_b64,'base64'); 
    var exponent = new Buffer(exponent_b64, 'base64'); 

    var modulus_hex = modulus.toString('hex') 
    var exponent_hex = exponent.toString('hex') 

    modulus_hex = prepadSigned(modulus_hex) 
    exponent_hex = prepadSigned(exponent_hex) 

    var modlen = modulus_hex.length/2 
    var explen = exponent_hex.length/2 

    var encoded_modlen = encodeLengthHex(modlen) 
    var encoded_explen = encodeLengthHex(explen) 
    var encoded_pubkey = '30' + 
     encodeLengthHex(
      modlen + 
      explen + 
      encoded_modlen.length/2 + 
      encoded_explen.length/2 + 2 
     ) + 
     '02' + encoded_modlen + modulus_hex + 
     '02' + encoded_explen + exponent_hex; 

    var seq2 = 
     '30 0d ' + 
      '06 09 2a 86 48 86 f7 0d 01 01 01' + 
      '05 00 ' + 
     '03' + encodeLengthHex(encoded_pubkey.length/2 + 1) + 
     '00' + encoded_pubkey; 

    seq2 = seq2.replace(/ /g,''); 

    var der_hex = '30' + encodeLengthHex(seq2.length/2) + seq2; 

    der_hex = der_hex.replace(/ /g, ''); 

    var der = new Buffer(der_hex, 'hex'); 
    var der_b64 = der.toString('base64'); 

    var pem = '-----BEGIN PUBLIC KEY-----\n' 
     + der_b64.match(/.{1,64}/g).join('\n') 
     + '\n-----END PUBLIC KEY-----\n'; 

    return pem 
} 

Manipolazione binaria con stringhe esadecimali? Yuck .. ma hey è un hack.

+0

Non funziona per me. Ovviamente non è chiaro cosa è sbagliato, solo che la verifica fallisce ancora. – Aaron

+0

Leggera modifica per far funzionare correttamente quel codice. '' 'pem = '----- BEGIN PUBLIC KEY ----- \ n'; \t \t for (var i = 0; i 64) { \t \t \t len = 64; \t \t} \t \t pem + = der_b64.substr (i, len) + "\ n"; \t} \t PEM + = '----- END chiave pubblica ----- \ n' '' ' – Aaron

+0

@Aaron Ho modificato la risposta .. usato un'espressione regolare al posto del ciclo. – Tracker1