2011-10-27 17 views
27

Estoy intentando hacer un programa que utiliza algunos servicios web en Delphi XE. Para conectarme a los servicios web, tengo que usar un certificado autofirmado, que se almacena en la tienda de certificados de Windows. Abrí la tienda de certificados con CertOpenSystemStore, obtuve el certificado con CertFindCertificateInStore y lo configuré con SSL_CTX_use_certificate. No hay problema con esto Luego llego el blob de clave pública con CryptExportKey y compone una clave privada así:Uso de certificado y clave privada de 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; 

luego lo configuro con SSL_CTX_use_PrivateKey y SSL_CTX_check_private_key - ningún problema hasta el momento. Pero cuando comienza la transferencia de datos, aparece una infracción de acceso en libeay32.dll. Si cargo la clave desde el archivo .pem, todo está bien. No puedo ver lo que estoy haciendo mal, por favor ayuda :)

Aquí es el mensaje de error exacto: violación

acceso a 09881C5F dirección en el módulo 'libeay32.dll'. Leído de dirección 00000000.

La versión de libeay32.dll es 1.0.0.5. Intenté con la versión 0.9.algo también: recibí el mismo error, solo una dirección diferente.

A continuación se muestra la estructura de RSA consigo en 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 

Revisé los n y e bignums, y que son correctos, y todo lo demás se ve bien. Y sí, el error ocurre al llamar a la función ssl_read.

+3

Bienvenido a StackOverflow. Me temo que "obtengo una infracción de acceso en libea32.dll" no nos da información para intentar ayudarte. Si recibe un mensaje de error o una excepción o AV, es ** muy ** importante incluir el mensaje de error ** exacto ** (junto con las direcciones de memoria). Si no nos proporciona ese medio, lo pedimos y luego esperamos a que nos lo entregue antes de que podamos intentar ayudarlo. Si proporcionas la información de error en tu pregunta original (junto con el código y el texto de la pregunta como has proporcionado), obtendrás una respuesta mucho más rápido. Por favor edítalo y agrégalo. Gracias. :) –

+2

Las excepciones con la 'Lectura de la dirección 0x00000000' en Delphi casi siempre (no el 100% del tiempo, pero casi) son causadas por acceder a un objeto antes de su creación, o un puntero que nunca tiene asignado ningún elemento (un puntero). ¿Puedes limitar el lugar en el código que está causando la violación de acceso? (+1 para una buena pregunta después de la edición, BTW.) –

+0

@Ken White Gracias por la respuesta. De alguna manera, no puedo alinear el código muy bien en el comentario, así que edité la pregunta. La estructura de RSA me parece bien ... – Andrejs

Respuesta

1

Me parece las razones más razonables se podrían obtener estos errores incluyen:

  1. versión incorrecta de DLL de OpenSSL (libeay32 ssleay.dll) o error en la declaración de envolturas SSL (en este caso, es posible que necesite una actualización de Indy versión 10).

  2. Al haber liberado el bloque de memoria que está pasando a la DLL, según el comentario de Ken.

  3. Algún error sutil de desreferenciación del puntero en el código que ha publicado. Una llamada a CopyMemory podría perder un nivel de indirección de puntero a través de "PointerVariableName ^" en lugar de solo "PointerVariableName". Lea sobre "parámetros var no tipados y punteros en pascal" si no está seguro.

Cuestiones relacionadas