2011-10-27 17 views
27

Sto tentando di creare un programma che utilizza alcuni servizi Web in Delphi XE. Per connettersi ai servizi Web, devo utilizzare un certificato autofirmato, che è memorizzato nell'archivio dei certificati di Windows. Apro Cert Store con CertOpenSystemStore, ottengo il certificato con CertFindCertificateInStore e lo imposta con SSL_CTX_use_certificate. Nessun problema con questo. Poi ho la chiave pubblica blob con CryptExportKey e portare una chiave privata come questo:Utilizzo di certificato e chiave privata da Windows Cert Store con OpenSSL

function PrivKeyBlob2RSA(const AKeyBlob: PByte; const ALength: Integer; const ASSLCtx: PSSL_CTX): IdSSLOpenSSLHeaders.PEVP_PKEY; 
var 
    modulus: PByte; 
    bh: PBLOBHEADER; 
    rp: PRSAPUBKEY; 
    rsa_modlen: DWORD; 
    rsa_modulus: PAnsiChar; 
    rkey: PRSA; 
begin 
    bh := PBLOBHEADER(AKeyBlob); 
    Assert(bh^.bType = PUBLICKEYBLOB); 
    rp := PRSAPUBKEY(AKeyBlob + 8); 
    Assert(rp.magic = $31415352); 
    rsa_modulus := PAnsiChar(Integer(Pointer(rp))+12); 
    rkey := RSA_new_method(ASSLCtx.client_cert_engine); 
    rkey^.References := 1; 
    rkey^.e := BN_new; 
    rkey^.n := BN_new; 
    BN_set_word(rkey^.e, rp^.pubexp); 
    rsa_modlen := (rp^.bitlen div 8) + 1; 
    modulus := AllocMem(rsa_modlen); 
    CopyMemory(modulus, rsa_modulus, rsa_modlen); 
    RevBuffer(modulus, rsa_modlen); 
    BN_bin2bn(modulus, rsa_modlen, rkey^.n); 
    Result := EVP_PKEY_new; 
    EVP_PKEY_assign_RSA(Result, PAnsiChar(rkey)); 
end; 

Ho quindi impostare il tutto con SSL_CTX_use_PrivateKey e SSL_CTX_check_private_key - nessun problema finora. Ma quando inizia il trasferimento dei dati, ottengo una violazione di accesso in libeay32.dll. Se carico la chiave dal file .pem, tutto va bene. Non riesco a vedere quello che sto facendo male, si prega di aiuto :)

Ecco il messaggio di errore esatto: violazione

accesso all'indirizzo 09881C5F nel modulo 'libeay32.dll'. Leggi di indirizzo 00000000.

La versione libeay32.dll è 1.0.0.5. Provato anche con la versione 0.9. Qualcosa ha avuto lo stesso errore, solo un indirizzo diverso.

Di seguito si riporta la struttura RSA ricevo in PrivKeyBlob2RSA:

pad 0 
version 0 
meth  $898030C 
engine  nil 
n  $A62D508 
e  $A62D4D8 
d  nil 
p  nil 
q  nil 
dmp1  nil 
dmq1  nil 
iqmp  nil 
ex_data (nil, -1163005939 {$BAADF00D}) 
references 1 
flags  6 
_method_mod_n nil 
_method_mod_p nil 
_method_mod_q nil 
bignum_data nil {#0} 
blinding nil 
mt_blinding nil 

Ho controllato le n ed e bignum, e hanno ragione, e tutto il resto sembra ok. E sì, l'errore si verifica quando si chiama la funzione ssl_read.

+3

Benvenuti in StackOverflow. Ho paura "Ottengo violazione di accesso in libea32.dll" non ci fornisce informazioni per andare avanti a provare e aiutarti. Se ricevi un messaggio di errore o un'eccezione o AV, è ** molto ** importante includere il messaggio di errore ** esatto ** (insieme a qualsiasi indirizzo di memoria). Non fornire questo significa che lo abbiamo chiesto, e poi aspettiamo che ce lo diamo, prima che possiamo provare e aiutare. Se fornisci le informazioni sull'errore nella tua domanda originale (insieme al codice e al testo della domanda come hai fornito tu), otterrai una risposta molto più velocemente. Si prega di modificare e aggiungerlo. Grazie. :) –

+2

Le eccezioni con 'Read of address 0x00000000' in Delphi sono quasi sempre (non il 100% delle volte, ma quasi) causate dall'accesso a un oggetto prima della sua creazione, o da un puntatore a cui non è mai assegnato nulla a cui puntare (a zero puntatore). Puoi restringere il punto nel codice che causa la violazione di accesso? (+1 per una buona domanda dopo la modifica, BTW.) –

+0

@Ken White Grazie per la risposta. In qualche modo non riesco ad allineare bene il codice nel commento, quindi ho modificato la domanda. La struttura RSA mi sembra ok .. – Andrejs

risposta

1

Mi sembra motivi più ragionevoli che si otterrebbe questi errori includono:

  1. Versione errata della DLL di OpenSSL (libeay32 ssleay.dll) o un errore nel dichiarare wrapper SSL (in questo caso potrebbe essere necessario un aggiornamento di versione 10 di Indy).

  2. Avendo già liberato il blocco di memoria che stai passando nella DLL, come da commento di Ken.

  3. Alcuni errori di dereferenziamento del puntatore nel codice che hai postato. A una chiamata a CopyMemory potrebbe mancare un livello di puntatore indiretto tramite "PointerVariableName ^" invece di "PointerVariableName". Leggi su "parametri var non tipizzati e puntatori in pascal" se non sei chiaro.