最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

windows - Creating self‐signed certificates using LibCrypto-3.dll from OpenSSL, code in FreePascal - Stack Overflow

programmeradmin5浏览0评论

I’m having trouble with the x509_sign function in the following code. The error I get from LibCrypto via ERR_print_errors_fp is:

OPENSSL_Uplink(721B6200,08): no OPENSSL_Applink"

program createselfsignedcert;

{$MODE OBJFPC}
{$LONGSTRINGS ON}

uses
  SysUtils, Windows;

const
  OPENSSL_LIB = 'libcrypto-3.dll';
//  OPENSSL_LIB = 'libeay32.dll';
  MBSTRING_FLAG = $1000;
  MBSTRING_ASC = MBSTRING_FLAG or 1;
  MBSTRING_BMP = MBSTRING_FLAG or 2;
  MBSTRING_UNIV = MBSTRING_FLAG or 3;
  MBSTRING_UTF8 = MBSTRING_FLAG or 4;
  EVP_PKEY_RSA = 6; // RSA key type

type
  TCallback=procedure(str: PChar; len: size_t; u: Pointer); //cdecl;

  PX509=Pointer;
  PEVP_PKEY=Pointer;
  PEVP_MD=Pointer;
  PASN1_TIME=Pointer;
  PBIO=PAnsiChar;

  ASN1_STRING = packed record
    length: Integer;
    _type: Integer;
    data: PChar;
    flags: LongWord;
  end;

  PASN1_UTCTIME=^ASN1_UTCTIME;
  ASN1_UTCTIME=ASN1_STRING;
  ASN1_INTEGER=ASN1_STRING;
  PASN1_INTEGER=^ASN1_STRING;

// Create Objects
function X509_new: PX509; cdecl; external OPENSSL_LIB name 'X509_new';
function X509_NAME_new: Pointer; cdecl; external OPENSSL_LIB name 'X509_NAME_new';
function EVP_PKEY_new: PEVP_PKEY; cdecl; external OPENSSL_LIB name 'EVP_PKEY_new';
function RSA_generate_key(bits: Integer; e: Integer; callback: Pointer; arg: Pointer): Pointer; cdecl; external OPENSSL_LIB name 'RSA_generate_key';
function ASN1_UTCTIME_new: PASN1_TIME; cdecl; external OPENSSL_LIB name 'ASN1_UTCTIME_new';
function BN_new: Pointer; cdecl; external OPENSSL_LIB name 'BN_new';
function BIO_new_file(filename: PChar; mode: PChar): Pointer; cdecl; external OPENSSL_LIB name 'BIO_new_file';
// Free Objects
procedure X509_free(x: PX509); cdecl; external OPENSSL_LIB name 'X509_free';
procedure X509_NAME_free(n: Pointer); cdecl; external OPENSSL_LIB name 'X509_NAME_free';
procedure EVP_PKEY_free(pkey: PEVP_PKEY); cdecl; external OPENSSL_LIB name 'EVP_PKEY_free';
procedure RSA_free(r: Pointer); cdecl; external OPENSSL_LIB name 'RSA_free';
procedure ASN1_UTCTIME_free(a: PASN1_TIME); cdecl; external OPENSSL_LIB name 'ASN1_UTCTIME_free';
procedure BN_free(a: Pointer); cdecl; external OPENSSL_LIB name 'BN_free';
function BIO_free(a: pointer): integer;  cdecl; external OPENSSL_LIB name 'BIO_free';
// Handle Objects
function X509_set_version(x: PX509; version: Integer): Integer; cdecl; external OPENSSL_LIB name 'X509_set_version';
function X509_get_serialNumber(x: PX509): Integer; cdecl; external OPENSSL_LIB name 'X509_get_serialNumber';
procedure X509_set_serialNumber(x: PX509; serial: PASN1_INTEGER); cdecl; external OPENSSL_LIB name 'X509_set_serialNumber';
procedure X509_gmtime_adj(s: PASN1_TIME; adj: Integer); cdecl; external OPENSSL_LIB name 'X509_gmtime_adj';
function X509_get0_notBefore(x: PX509): PASN1_TIME; cdecl; external OPENSSL_LIB name 'X509_get0_notBefore';
function X509_get0_notAfter(x: PX509): PASN1_TIME; cdecl; external OPENSSL_LIB name 'X509_get0_notAfter';
function X509_NAME_add_entry_by_txt(name: Pointer; field: PAnsiChar; _type: Integer; bytes: PAnsiChar; len: Integer; location, _default: Integer): integer; cdecl; external OPENSSL_LIB name 'X509_NAME_add_entry_by_txt';
function X509_set_issuer_name(x: PX509; name: Pointer): Integer; cdecl; external OPENSSL_LIB name 'X509_set_issuer_name';
function X509_set_subject_name(x: PX509; name: Pointer): Integer; cdecl; external OPENSSL_LIB name 'X509_set_subject_name';
function X509_set_pubkey(x: PX509; pkey: PEVP_PKEY): integer; cdecl; external OPENSSL_LIB name 'X509_set_pubkey';
function X509_sign(x: PX509; pkey: PEVP_PKEY; md: PEVP_MD): Integer; cdecl; external OPENSSL_LIB name 'X509_sign';
function EVP_PKEY_set1_RSA(key: pEVP_PKEY; rsa: pointer): integer; cdecl; external OPENSSL_LIB name 'EVP_PKEY_set1_RSA';
function EVP_PKEY_assign(pkey: PEVP_PKEY; typ: integer; key: pointer): integer; cdecl; external OPENSSL_LIB name 'EVP_PKEY_assign';
function PEM_write_bio_X509(bp: pBIO; x: pX509): integer; cdecl; external OPENSSL_LIB name 'PEM_write_bio_X509';
procedure PEM_write_X509(filename: pchar; x: PX509); cdecl; external OPENSSL_LIB name 'PEM_write_X509';
function PEM_write_bio_PrivateKey(bp: pointer; pkey: PEVP_PKEY; enc: pointer; kstr: pointer; klen: integer; pem_password_cb: pointer; u: pointer): integer; cdecl; external OPENSSL_LIB name 'PEM_write_bio_PrivateKey';
function PEM_write_PrivateKey(filename: pchar; pkey: PEVP_PKEY; enc: pointer; kstr: pointer; klen: integer; pem_password_cb: pointer; u: pointer): integer; cdecl; external OPENSSL_LIB name 'PEM_write_PrivateKey';
function ASN1_INTEGER_new: PASN1_INTEGER; cdecl; external OPENSSL_LIB name 'ASN1_INTEGER_new';
function ASN1_INTEGER_set_int64(a: PASN1_INTEGER; r: Int64): Integer; cdecl; external OPENSSL_LIB name 'ASN1_INTEGER_set_int64';
procedure ERR_print_errors_fp(filename: pchar); cdecl; external OPENSSL_LIB name 'ERR_print_errors_fp';
procedure ERR_print_errors_cb(callback: TCallBack; u: Pointer); cdecl; external OPENSSL_LIB name 'ERR_print_errors_cb';
procedure ERR_print_errors(bp: PBIO); cdecl; external OPENSSL_LIB name 'ERR_print_errors';
function  ERR_get_error: Cardinal; cdecl; external OPENSSL_LIB name 'ERR_get_error';

// Message Digest
function EVP_sha256: PEVP_MD; cdecl; external OPENSSL_LIB name 'EVP_sha256';
function EVP_sha1: PEVP_MD; cdecl; external OPENSSL_LIB name 'EVP_sha1';
function EVP_md5: PEVP_MD; cdecl; external OPENSSL_LIB name 'EVP_md5';

procedure HaltOnBadObj(Obj: pointer; Mess: string);
begin
  if not Assigned(Obj) then
    begin
      writeln(Mess);
      halt(1);
    end;
end;

procedure MyErrorCallback(str: PChar; len: size_t; u: Pointer); //cdecl;
begin
  WriteLn('OpenSSL Error: ', StrPas(str));
end;

procedure ShowFuncStat(RetVal: integer; Mess: string; ShowErr: boolean=False);
var
  err: Cardinal;
begin
  if RetVal=1 then
    writeln(Mess+' ok.')
  else
    begin
      writeln('Error:- '+Mess+'.');
      if ShowErr then
        ERR_print_errors_fp(@stderr);
    end;
end;

procedure GenerateRandomSerialNumber(var SerialNumber: PASN1_INTEGER);
var
  RandomValue: Int64;
  i: Integer;
begin
  // We generate a 64-bit random number
  RandomValue:=0;
  for i:=1 to 8 do
    RandomValue:=(RandomValue shl 8) or Random(256);
  // We make sure the number is positive
  RandomValue:=RandomValue and $7FFFFFFFFFFFFFFF;
  // We set the serial number
  ShowFuncStat(ASN1_INTEGER_set_int64(SerialNumber, RandomValue), 'Setting serial number');
end;

procedure CreateCertificate;
var
  x509: PX509;
  pkey: PEVP_PKEY;
  SerialNumber: PASN1_INTEGER;
  name: Pointer;
  time: PASN1_TIME;
  rsa: Pointer;
  bio: Pointer;
begin
  // Create a new X509 structure
  x509:=X509_new;
  HaltOnBadObj(x509, 'Error creating X509 structure');
  // Set the version of the certificate (X509v3)
  ShowFuncStat(X509_set_version(x509, 2), 'Setting X509 version');
  // Generate key pair
  pkey:=EVP_PKEY_new;
  HaltOnBadObj(pkey, 'Error creating private key');
  rsa:=RSA_generate_key(2048, $10001, nil, nil);
  HaltOnBadObj(rsa, 'Error generating RSA key');
  // Assign the generated key to the pkey structure
  ShowFuncStat(EVP_PKEY_set1_RSA(pkey, rsa), 'Assigning RSA to pkey');
  bio:=BIO_new_file('privatea_key.pem', 'w');
  HaltOnBadObj(bio, 'Error creating BIO for file');
  ShowFuncStat(PEM_write_bio_PrivateKey(bio, pkey, nil, nil, 0, nil, nil), 'Writing private key to file');
//  ShowFuncStat(PEM_write_PrivateKey(@stderr, pkey, nil, nil, 0, nil, nil), 'Writing private key to file');
  // Set the private key for the certificate
  ShowFuncStat(X509_set_pubkey(x509, pkey), 'Setting public key');
  // Set the serial number for x509
  SerialNumber:=ASN1_INTEGER_new;
  HaltOnBadObj(SerialNumber, 'Error creating Serial Number');
  GenerateRandomSerialNumber(SerialNumber);
  X509_set_serialNumber(x509, SerialNumber);
  // Set validity period (e.g., one year from now)
  time:=ASN1_UTCTIME_new;
 // HaltOnBadObj(time, 'Error creating time structure');
  X509_gmtime_adj(time, 60*60*24*365); // One year from now

 // X509_gmtime_adj(X509_get0_notBefore(x509), 0);
 // X509_gmtime_adj(X509_get0_notAfter(x509), 60*60*24*365);

  // Set the issuer and subject names (you can customize these)
  name:=X509_NAME_new;
  HaltOnBadObj(name, 'Error creating name structure');
  ShowFuncStat(X509_NAME_add_entry_by_txt(name, 'C', MBSTRING_ASC, PAnsiChar('US'), -1, -1, 0), 'Set Country');
  ShowFuncStat(X509_NAME_add_entry_by_txt(name, 'ST', MBSTRING_ASC, PAnsiChar('California'), -1, -1, 0), 'Set State');
  ShowFuncStat(X509_NAME_add_entry_by_txt(name, 'L', MBSTRING_ASC, PAnsiChar('San Francisco'), -1, -1, 0), 'Set Location');
  ShowFuncStat(X509_NAME_add_entry_by_txt(name, 'O', MBSTRING_ASC, PAnsiChar('My Organization'), -1, -1, 0), 'Set Organization');
  ShowFuncStat(X509_NAME_add_entry_by_txt(name, 'OU', MBSTRING_ASC, PAnsiChar('My Organizational Unit'), -1, -1, 0), 'Set Department');
  ShowFuncStat(X509_NAME_add_entry_by_txt(name, 'CN', MBSTRING_ASC, PAnsiChar('localhost'), -1, -1, 0), 'Set Common Name');
  // Set the issuer and subject names in the certificate
  ShowFuncStat(X509_set_issuer_name(x509, name), 'Setting issuer name');
  ShowFuncStat(X509_set_subject_name(x509, name), 'Setting subject name');
  // Sign the certificate with the private key
  //////////////////////// This fails
  ShowFuncStat(X509_sign(x509, pkey, EVP_sha256()), 'Signing Certificate', true);
  ////////////////////////
  // Save the certificate to a file (e.g., cert.pem)
  bio:=BIO_new_file('cert.pem', 'w');
  ShowFuncStat(PEM_write_bio_X509(bio, x509), 'Writing Certificate');
  // Free everything
  X509_free(x509);
  EVP_PKEY_free(pkey);
  ASN1_UTCTIME_free(time);
  X509_NAME_free(name);
  BN_free(rsa);
  BIO_free(bio);
end;

begin
  try
    CreateCertificate;
    Writeln('Self-signed certificate created successfully.');
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

This this the output.

Setting X509 version ok.
Assigning RSA to pkey ok.
Writing private key to file ok.
Setting public key ok.
Setting serial number ok.
Set Country ok.
Set State ok.
Set Location ok.
Set Organization ok.
Set Department ok.
Set Common Name ok.
Setting issuer name ok.
Setting subject name ok.
Error:- Signing Certificate.
OPENSSL_Uplink(721B6200,08): no OPENSSL_Applink

I’ve seen this same error in several other coding languages and seen no solutions for this error.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论