Indy 中调用 X509_new 时访问冲突

问题描述 投票:0回答:1

我使用以下程序:

procedure TForm2.Label1DblClick(Sender: TObject);
  procedure GenerateSelfSignedCertificate(const AFileName: string);
    procedure GenerateRandomSerialNumber(SerialNumber: PASN1_INTEGER);
    var
      RandomValue: Int64;
      I: Integer;
    begin
      // We generate a 64-bit random number
      RandomValue := 0;
      for I := 1 to 8 do
      begin
        RandomValue := (RandomValue shl 8) or Random(256);
      end;

      // We make sure the number is positive
      RandomValue := RandomValue and $7FFFFFFFFFFFFFFF;

      // We set the serial number
      if ASN1_INTEGER_set(SerialNumber, RandomValue) = 0 then
        raise Exception.Create('Error setting serial number');
    end;

    function DateToASN1_TIME(const ADate: TDateTime): PASN1_TIME;
    var
      AStruct: TSystemTime;
      ASN1_Time: PASN1_TIME;
    begin
      DateTimeToSystemTime(ADate, AStruct);
      ASN1_Time := ASN1_TIME_set(nil, SystemTimeToDateTime(AStruct));
      Result := ASN1_Time;
    end;

  var
    Cert: PX509;
    PrivateKey: PEVP_PKEY;
    SerialNumber: PASN1_INTEGER;
    Name: PX509_NAME;
    Bio: PBIO;
    NotBefore, NotAfter: TDateTime;
  begin
    // Inițializați OpenSSL
    IdSSLOpenSSL.LoadOpenSSLLibrary;

    // A new certificate is created
    Cert := X509_new; // ERROR!!!! Access Vioaltion at address 00000...
    try // A new RSA private key is created
      PrivateKey := EVP_PKEY_new;
      try
        if EVP_PKEY_assign(PrivateKey, EVP_PKEY_RSA,
          PByte(RSA_generate_key(2048, RSA_F4, nil, nil))) = 0 then
          raise Exception.Create('Error generating private key');

        // Certificate version is set (X509 v3)
        X509_set_version(Cert, 2);

        // A random serial number is generated
        SerialNumber := ASN1_INTEGER_new;
        if SerialNumber = nil then
          raise Exception.Create('Error creating ASN1_INTEGER');

        try
          GenerateRandomSerialNumber(SerialNumber);
          if X509_set_serialNumber(Cert, SerialNumber) = 0 then
            raise Exception.Create
              ('Error setting serial number for certificate');
        finally
          ASN1_INTEGER_free(SerialNumber);
        end;

        // The start and end date of the certificate is set
        NotBefore := Now - 1;
        // The certificate is valid from yesterday
        NotAfter := NotBefore + 365;
        // The certificate is valid for approximately one year
        X509_set_notBefore(Cert, DateToASN1_TIME(NotBefore));
        X509_set_notAfter(Cert, DateToASN1_TIME(NotAfter));

        // The public key is set
        X509_set_pubkey(Cert, PrivateKey);

        // Issuer and subject name is set (localhost is used)
        Name := X509_get_subject_name(Cert);
        X509_NAME_add_entry_by_txt(Name, 'CN', MBSTRING_ASC,
          PAnsiChar('localhost'), -1, -1, 0);
        X509_set_issuer_name(Cert, Name);

        // The certificate is signed
        if X509_sign(Cert, PrivateKey, EVP_sha256) = 0 then
          raise Exception.Create('Error signing the certificate');

        // The certificate and private key are saved in a PEM file
        Bio := BIO_new_file(PAnsiChar(AnsiString(AFileName)), 'w+');
        try
          PEM_write_bio_X509(Bio, Cert);
          PEM_write_bio_PrivateKey(Bio, PrivateKey, nil, nil, 0, nil, nil);
        finally
          BIO_free(Bio);
        end;
      finally
        EVP_PKEY_free(PrivateKey);
      end;
    finally
      X509_free(Cert);
    end;
  end;

begin
  GenerateSelfSignedCertificate('.\CertificatTest.pem');
  ShowMessage('Certificate successfully generated!');
end;

Cert := X509_new;
线上我收到一条错误消息

地址访问冲突...

X509_new函数在使用OpenSSL的Indy框架的IdSSLOpenSSLHeaders单元中定义如下:

{$EXTERNALSYM X509_new}
X509_new : function: PX509 cdecl = nil;

我正在尝试生成自签名的 X509 证书。代码是在与 ChatGPT 多次讨论后生成的。但是我无法克服这个错误。

delphi openssl indy x509certficiate2
1个回答
0
投票

Indy 在运行时动态加载 OpenSSL 函数。在尝试使用它加载的任何函数之前,您不会检查

LoadOpenSSLLibrary()
是否成功。检查
LoadOpenSSLLibrary()
的返回值,例如:

if not IdSSLOpenSSL.LoadOpenSSLLibrary then
begin
  // error handling...
end;

此外,在 OpenSSL 加载失败后,请使用

IdSSLOpenSSLHeaders.WhichFailedToLoad()
检查,以了解实际加载失败的内容。 正如您在评论中提到的:

OpenSSl 库有版本 3

Indy 尚不支持 OpenSSL 3.x(正在进行中)。支持的最后一个版本是 1.0.2u,您可以从 https://github.com/IndySockets/OpenSSL-Binaries 获取该版本。如果您尝试加载较新的版本,

LoadOpenSSLLibrary()
将失败并且
WhichFailedToLoad()
将报告
Unsupported SSL Library version

话虽如此,

X509_new
不被视为关键函数,因为 Indy 不直接使用它,因此如果
X509_new
未从
libcrypto
库导出,则加载 OpenSSL 不会失败(如果成功的话)。
IdSSLOpenSSLHeaders.X509_new
指针将只是
nil
,因此如果您打算直接使用
X509_new()
,您还应该检查该条件。

© www.soinside.com 2019 - 2024. All rights reserved.