在调用DLL的应用程序中,该应用程序在墨西哥实现电子帐单,错误OPENSSL_UPLINK OPENSSL_APPLINK终止进程(崩溃)。
调试DLL时,我在加载CER文件时看到错误。和.KEY
以下是我的主密码。
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;
以下是我编写函数的单元代码
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;
的。 KEY及其私钥是正确的,这是我在调试中检查的第一件事。
最奇怪的是,我有两个文件夹,一个是应用程序正在生产中,另一个是测试。并且仅在测试文件夹中无法正常工作。
应用程序应在Citrix下运行。
在开发计算机上,一切都运行正常,错误在于实现和测试文件夹,Citrix服务器是Win Server 2003
如果有人可以帮我找到这个错误,请提前致谢
答案 0 :(得分:0)
我也来自墨西哥,我也为Delphi开发了数字发票(Facturacion Electronica)的开源库,并且还与OpenSSL和Delphi的实现进行了斗争。
实际上我们的代码看起来很相似,你可以查看我打开私钥的“ClaseOpenSSL.pas”代码:
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
问候!