首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Openssl_Uplink no Openssl_Applink

Openssl_Uplink no Openssl_Applink
EN

Stack Overflow用户
提问于 2013-12-21 08:58:14
回答 1查看 1.5K关注 0票数 0

在调用在墨西哥实现电子账单的DLL的应用程序中,错误OPENSSL_UPLINK OPENSSL_APPLINK会终止进程(崩溃)。

当您调试DLL时,我发现错误是在加载CER文件时出现的。和.KEY

以下是我的主代码。

代码语言:javascript
复制
function TFacturacion.Validar_Certificado : boolean;
var
  Certificado : TCertificado;
begin
  Certificado := TCertificado.Create;
try
 begin
  Certificado.LoadFromFile(DmDatos.IBDs_SistemaCERTFNAME.AsString);
  case TipoCertificado(Certificado.Base64) of
tcDESCONOCIDO : begin
     FRespuestaCFD := 'Certificado Desconocido o de Pruebas';
     Result := False;
    end;
    tcFIEL : begin
     FRespuestaCFD := 'Certificado FIEL';
     Result := False;
    end;
    tcCSD : begin
     Result := True;
    end;
 end;         // Fin Case
end;          // Fin Begin protegido(TRY)
Except
 Result := False;
 FRespuestaCFD := 'Error en Certificado....No se pudo localizar el Archivo .CER';
end;

if Result = False then
 begin
  Certificado.Free;
  Certificado := NIl;
   Exit;
 end;

CertificadoB64 := Certificado.Base64;
Certificado.Free;
Certificado := Nil;

end;

function TFacturacion.Validar_Llave : Boolean;
var Llave : TLlavePrivada;
begin
 Result := False;
 Llave := TLlavePrivada.Create;

 if Llave.DER_LoadFromFile(DmDatos.IBDs_SistemaKEYFNAME.AsString,         DmDatos.IBDs_SistemaCLAVEPRIVADA.AsString ) then
 begin
  FLlaveB64 := Llave.Base64;
  Result := True;
 end
 else
  begin
    FRespuestaCFD := 'Error al abrir la Llave, es posible que la clave no sea la correcta';
 end;

Llave.Free;
Llave := Nil;

end;

以下是对函数进行编码的单元的代码

代码语言:javascript
复制
procedure TX509Certificate.LoadFromFile(FileName: string);
 begin
  LoadFromFile(Filename, auto);
 end;

procedure TX509Certificate.LoadFromFile(FileName: string; Encoding: TEncoding);
var
 certfile: pBIO;
 p12: pPKCS12;
 a: pEVP_PKEY;
 c: pX509;
 ca: pSTACK_OFX509;
begin
 c := nil;

 if not(Encoding in [auto, DER, PEM, NETSCAPE, PKCS12]) then
raise EOpenSSL.Create('Bad certificate encoding.');

 if not FileExists(FileName) then
raise EOpenSSL.Create('Certificate file not found ('+FileName+')');

 certfile := BIO_new(BIO_s_file());

 if certfile = nil then
raise EOpenSSL.Create('Error creating BIO.');

 BIO_read_filename(certfile, ToChar(FileName));

 if (Encoding = auto) or (encoding = DER) then
  begin
fCertificate := d2i_X509_bio(certfile, nil);
if (Encoding = auto) and (fCertificate = nil) then
  BIO_reset(certfile);
  end;

 if ((Encoding = auto) and (fCertificate = nil)) or (encoding = NETSCAPE) then
  begin
// See apps.c
  end;

 if ((Encoding = auto) and (fCertificate = nil)) or (encoding = PEM) then
  begin
fCertificate := PEM_read_bio_X509_AUX(certfile, c, nil, nil);
if (Encoding = auto) and (fCertificate = nil) then
 BIO_reset(certfile);
  end;

 if ((Encoding = auto) and (fCertificate = nil)) or (encoding = PKCS12) then  
  begin
p12 := d2i_PKCS12_bio(certfile, nil);
PKCS12_parse(p12, nil, a, c, ca);
fCertificate := c;
PKCS12_free(p12);
p12 := nil;
  end;

  BIO_free(certfile);
  if fCertificate = nil then
raise EOpenSSL.Create('Unable to read certificate from file ' + FileName + '.');
end;

function TPKCS8.DER_LoadFromFile(DERFname, PrivateKey: string) : boolean;
var
 bioDER : pBIO;
 p8 : pX509_SIG;
 p8inf : pPKCS8_Priv_Key_Info;
begin
 //OpenSSL pkcs8 -inform DER -in DERFName -passin pass:PrivateKey

 Result := false;

 bioDER := nil; p8 := nil;

 if FileExists(DERFname) then
  try
bioDER := BIO_new(BIO_s_file());
BIO_read_filename(bioDER,ToChar(DERFName));
p8 := d2i_PKCS8_bio(bioDER,nil);
if p8 = nil then exit; //El archivo no es un .key bien formado
//------HERE CRASH-----------------------------------------------
p8inf := PKCS8_decrypt(p8,ToChar(PrivateKey),length(PrivateKey));
//-------------------------------------------------------------
if p8inf = nil then exit; //No es la clave de llave privada correcta
  fLlave := EVP_PKCS82PKEY(p8inf);
    Result := true;
  finally
X509_SIG_free(p8);
BIO_free(bioDER);
EVP_cleanup;
  end;
end;

这个。密钥及其私钥是正确的,这是我在调试中检查的第一件事。

最奇怪的是,我有两个文件夹,一个是应用程序在生产中,另一个是测试。并且仅在测试文件夹中无法正常工作。

应用程序应该在Citrix下运行。

在开发计算机上,一切工作正常,错误出在实现和测试文件夹中,

Citrix服务器是Win server 2003

如果有人能帮我找出这个错误,请提前表示感谢。

EN

回答 1

Stack Overflow用户

发布于 2014-01-15 09:15:54

我也来自墨西哥,我也为Delphi开发了一个用于数字发票(Facturacion Electronica)的开源库,也曾与OpenSSL和Delphi的实现进行过斗争。

实际上我们的代码看起来非常相似,你可以看看我的"ClaseOpenSSL.pas“代码,我在其中打开私钥:

代码语言:javascript
复制
function TOpenSSL.AbrirLlavePrivada(Ruta, ClaveLlavePrivada : String) : pPKCS8_Priv_Key_Info;
var
    bioArchivoLlave : pBIO;
    sMsgErr: String;
    p8 : pX509_SIG;
    p8inf : pPKCS8_Priv_Key_Info;
    {$IF CompilerVersion >= 20}
        p8pass: PAnsiChar;
    {$ELSE}
        p8pass: PChar;
    {$IFEND}
begin
    // Creamos el objeto en memoria para leer la llave en formato binario .DER (.KEY)
    bioArchivoLlave := BIO_new(BIO_s_file());

    if Not FileExists(Ruta) then
      Raise ENoExisteArchivoException.Create('El archivo de llave privada no existe.');

    // Checamos que la extension de la llave privada sea la correcta
    if AnsiPos('.PEM', Uppercase(Ruta)) > 0 then
      Raise ELlaveFormatoIncorrectoException.Create('La llave privada debe de ser el archivo binario (.key, .cer) y ' +
            'no el formato base64 .pem');

    // Leemos el archivo de llave binario en el objeto creado en memoria
    // DIferentes parametros si usa Delphi 2009 o superior...
    {$IF CompilerVersion >= 20}
        if BIO_read_filename(bioArchivoLlave, PWideChar(AnsiString(Ruta))) = 0 then
    {$ELSE}
        if BIO_read_filename(bioArchivoLlave, PChar(AnsiString(Ruta))) = 0 then
    {$IFEND}
          raise ELlaveLecturaException.Create('Error al leer llave privada. Error reportado: '+
                ObtenerUltimoMensajeDeError);

    // Checamos que la clave no est� vacia
    if Trim(ClaveLlavePrivada) = '' then
      raise ELlavePrivadaClaveIncorrectaException.Create('La clave de la llave privada esta vacia');

    // Convertimos al tipo adecuado de acuerdo a la version de Delphi...
    {$IF CompilerVersion >= 20}
        // Delphi 2009 o superior
        p8pass:=PAnsiChar(AnsiString(ClaveLlavePrivada));
    {$ELSE}
        p8pass:=PChar(AnsiString(ClaveLlavePrivada));
    {$IFEND}

    p8:=nil;
    p8inf:=nil;

    try
        //  Leemos la llave en formato binario (PKCS8)
        p8 := d2i_PKCS8_bio(bioArchivoLlave, nil);
        if not Assigned(p8) then
          raise ELlaveLecturaException.Create('Error al leer llave privada. Error reportado: '+
                ObtenerUltimoMensajeDeError);

        // Des encriptamos la llave en memoria usando la clave proporcionada
        p8inf := PKCS8_decrypt(p8, p8pass, StrLen(p8pass));
        if Not Assigned(p8inf) then
        begin
           sMsgErr:=ObtenerUltimoMensajeDeError;
           // TODO: Crear excepciones para los diferentes tipos de error que puede haber al
           // tratar de desencriptar la llave privada
           // Llave incorrecta (Mensaje exacto: 23077074:PKCS12 routines:PKCS12_pbe_crype:pkcs12 cipherfinal error)
           if ((AnsiPos('cipherfinal error', sMsgErr) > 0) or // clave incorrecta
              (AnsiPos('bad decrypt', sMsgErr) > 0))   // clave incorrecta
           then
              raise ELlavePrivadaClaveIncorrectaException.Create('La clave de la llave privada fue incorrecta')
           else
              if (AnsiPos('unknown pbe algorithm', sMsgErr) > 0) then // Clave vacia o pertenece a la FIEL
                Raise ELlavePareceSerFiel.Create('Al parecer la llave privada pertenece a la FIEL')
              else
                raise ELlaveLecturaException.Create('Error desconocido al desencriptar llave privada. Error reportado: '+
                      ObtenerUltimoMensajeDeError);
        end;
    finally
        // Liberamos las variables usadas en memoria
        X509_SIG_free(p8);
          BIO_free(bioArchivoLlave);
    end;

    Result:=p8inf;
end;

作为一个C库,OpenSSL在参数和传递正确的数据类型和缓冲区等方面往往非常挑剔,释放分配的"pBIO“变量也是非常重要的。

如果您愿意,欢迎您为库做贡献,随时欢迎您的帮助:)

Github项目位于:http://github.com/bambucode/tfacturaelectronica

我们的(相当新的)支持小组在:http://groups.google.com/forum/#!forum/tfacturaelectronica

致以问候!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20714254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档