Creating Self Signed Certificates using LibCrypto-3.dll from openssl lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- Trax · 2025-03-17 03:48 I'm having trouble with following bits in this code.   X509_set_serialNumber(x, serial);   X509_sign(x, pkey, nil); and   PEM_write_bio_X509(PAnsiChar('cert.pem'), x); I think the last two could be related to the first. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program createselfsignedcert; {$MODE OBJFPC}{$LONGSTRINGS ON} uses  SysUtils, Windows; const  OPENSSL_LIB = 'libcrypto-3.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; type  PX509 = Pointer;  PEVP_PKEY = Pointer;  PASN1_TIME = Pointer;  pBIO=PAnsiChar; function X509_new: PX509; cdecl; external OPENSSL_LIB name 'X509_new';procedure X509_free(x: PX509); cdecl; external OPENSSL_LIB name 'X509_free';function EVP_PKEY_new: PEVP_PKEY; cdecl; external OPENSSL_LIB name 'EVP_PKEY_new';procedure EVP_PKEY_free(pkey: PEVP_PKEY); cdecl; external OPENSSL_LIB name 'EVP_PKEY_free';function EVP_PKEY_set1_RSA(key: pEVP_PKEY; rsa: pointer): integer; cdecl; external OPENSSL_LIB name 'EVP_PKEY_set1_RSA';function X509_set_version(x: PX509; version: Integer): Integer; cdecl; external OPENSSL_LIB name 'X509_set_version';procedure X509_gmtime_adj(s: PASN1_TIME; adj: Integer); cdecl; external OPENSSL_LIB name 'X509_gmtime_adj';function ASN1_UTCTIME_new: PASN1_TIME; cdecl; external OPENSSL_LIB name 'ASN1_UTCTIME_new';procedure ASN1_UTCTIME_free(a: PASN1_TIME); cdecl; external OPENSSL_LIB name 'ASN1_UTCTIME_free';function X509_get_serialNumber(x: PX509): Integer; cdecl; external OPENSSL_LIB name 'X509_get_serialNumber';procedure X509_set_serialNumber(x: PX509; serial: Integer); cdecl; external OPENSSL_LIB name 'X509_set_serialNumber';function X509_NAME_new: Pointer; cdecl; external OPENSSL_LIB name 'X509_NAME_new';procedure X509_NAME_free(n: Pointer); cdecl; external OPENSSL_LIB name 'X509_NAME_free';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';procedure BN_free(a: Pointer); cdecl; external OPENSSL_LIB name 'BN_free';function BN_new: Pointer; cdecl; external OPENSSL_LIB name 'BN_new';function RSA_generate_key(bits: Integer; e: Integer; callback: Pointer; arg: Pointer): Pointer; cdecl; external OPENSSL_LIB name 'RSA_generate_key';procedure RSA_free(r: Pointer); cdecl; external OPENSSL_LIB name 'RSA_free';function BIO_new_file(filename: PChar; mode: PChar): Pointer; cdecl; external OPENSSL_LIB name 'BIO_new_file';function X509_sign(x: PX509; pkey: PEVP_PKEY; md: Pointer): Integer; cdecl; external OPENSSL_LIB name 'X509_sign';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';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'; procedure CreateCertificate;var  x: PX509;  pkey: PEVP_PKEY;  serial: Integer;  name: Pointer;  time: PASN1_TIME;  rsa: Pointer;  bio: Pointer;begin  // Create a new X509 structure  x := X509_new;  if not Assigned(x) then    raise Exception.Create('Error creating X509 structure');   // Set the version of the certificate (X509v3)  if X509_set_version(x, 2) <> 1 then    raise Exception.Create('Error setting X509 version');   // Generate key pair  pkey := EVP_PKEY_new;  if not Assigned(pkey) then    raise Exception.Create('Error creating private key');   rsa := RSA_generate_key(2048, $10001, nil, nil);  if not Assigned(rsa) then  raise Exception.Create('Error generating RSA key');{  else      // Test to see if the private keys are written, it breaks EVP_PKEY_set1_RSA(pkey, rsa)    begin      if EVP_PKEY_assign(pkey, 6, rsa)<=0 then        raise Exception.Create('Error assigning RSA key to EVP_PKEY')      else        begin            bio:= BIO_new_file('privatea_key.pem', 'w');            if bio = nil then            raise Exception.Create('Error creating BIO for file')          else              if PEM_write_bio_PrivateKey(bio, pkey, nil, nil, 0, nil, nil) <= 0 then                raise Exception.Create('Error writing private key to file');        end;    end;    }   // Assign the generated key to the pkey structure  if EVP_PKEY_set1_RSA(pkey, rsa) <> 1 then    raise Exception.Create('Error assigning RSA to pkey');   // Set the private key for the certificate  if X509_set_pubkey(x, pkey) <> 1 then    raise Exception.Create('Error setting public key');   // Create a serial number  serial := Random($FFFFFFFF);  X509_set_serialNumber(x, serial);   // Set validity period (e.g., one year from now)  time := ASN1_UTCTIME_new;  if not Assigned(time) then    raise Exception.Create('Error creating time structure');   X509_gmtime_adj(time, 60 * 60 * 24 * 365); // One year from now   // Set the issuer and subject names (you can customize these)  name := X509_NAME_new;  if not Assigned(name) then    raise Exception.Create('Error creating name structure');   X509_NAME_add_entry_by_txt(name, 'C', MBSTRING_ASC, PAnsiChar('US'), Length('US'), -1, -1);  X509_NAME_add_entry_by_txt(name, 'ST', MBSTRING_ASC, PAnsiChar('California'), Length('California'), -1, -1);  X509_NAME_add_entry_by_txt(name, 'L', MBSTRING_ASC, PAnsiChar('San Francisco'), Length('San Francisco'), -1, -1);  X509_NAME_add_entry_by_txt(name, 'O', MBSTRING_ASC, PAnsiChar('My Organization'), Length('My Organization'), -1, -1);  X509_NAME_add_entry_by_txt(name, 'OU', MBSTRING_ASC, PAnsiChar('My Organizational Unit'), Length('My Organizational Unit'), -1, -1);  X509_NAME_add_entry_by_txt(name, 'CN', MBSTRING_ASC, PAnsiChar('localhost'), Length('localhost'), -1, -1);   // Set the issuer and subject names in the certificate  if X509_set_issuer_name(x, name) <> 1 then    raise Exception.Create('Error setting issuer name');   if X509_set_subject_name(x, name) <> 1 then    raise Exception.Create('Error setting subject name');   // Sign the certificate with the private key  if X509_sign(x, pkey, nil) <> 1 then    raise Exception.Create('Error signing certificate');   // Save the certificate to a file (e.g., cert.pem)  if PEM_write_bio_X509(PAnsiChar('cert.pem'), x) <> 1 then//  if SSL_write_file('cert.pem', x) <> 1 then    raise Exception.Create('Error writing certificate to file');   // Free allocated resources  X509_free(x);  EVP_PKEY_free(pkey);  ASN1_UTCTIME_free(time);  X509_NAME_free(name);  BN_free(rsa);end; begin  try    CreateCertificate;    Writeln('Self- signed certificate created successfully.');  except    on E: Exception do      Writeln(E.ClassName, ': ', E.Message);  end;end.  Thanks for any help. ---------------------------------------------------------------------- Trax · 2025-03-17 04:19 OPENSSL_LIB = 'libcrypto-3.dll' in the code can be changed to libcrypto.dll or libcrypto.so for linux systems. ---------------------------------------------------------------------- MarkMLl · 2025-03-17 07:32 Quote from: Trax on March 17, 2025, 05:19:11 amOPENSSL_LIB = 'libcrypto-3.dll' in the code can be changed to libcrypto.dll or libcrypto.so for linux systems. Thanks for that, useful to know. MarkMLl ---------------------------------------------------------------------- Trax · 2025-03-18 08:18 Fixed Quote from: Trax on March 17, 2025, 04:48:53 am  X509_set_serialNumber(x, serial); Fixed this by declaring the following in the type section. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   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;   Declared serial as a PASN1_INTEGER in the 'procedure CreateCertificate' var section; Changed X509_set_serialNumber to the following and added two extra function calls. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure X509_set_serialNumber(x: PX509; serial: PASN1_INTEGER); cdecl; external OPENSSL_LIB name 'X509_set_serialNumber';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'; Found the following code to generate a random serial number. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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    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_int64(SerialNumber, RandomValue) = 0 then    raise Exception.Create('Error setting serial number');end;  and changed the X509_set_serialNumber section in 'procedure CreateCertificate' to this. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   Serial:=ASN1_INTEGER_new;  GenerateRandomSerialNumber(Serial);  X509_set_serialNumber(x509, Serial); ---------------------------------------------------------------------- Trax · 2025-03-18 08:23 Oh yeah changed x in 'procedure CreateCertificate;' var section to x509. Still having trouble with X509_sign which I think maybe related having md encryption to nil. ---------------------------------------------------------------------- Trax · 2025-03-21 10:22 Okay only got one error so far the following code and that is with the x509_sign function. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program createselfsignedcert; {$MODE OBJFPC}{$LONGSTRINGS ON} uses  SysUtils, Windows; const  OPENSSL_LIB = 'libcrypto-3.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  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 Objectsfunction 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 Objectsprocedure 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 Objectsfunction X509_set_version(x: PX509; version: Integer): Integer; cdecl; external OPENSSL_LIB name 'X509_set_version';procedure X509_gmtime_adj(s: PASN1_TIME; adj: Integer); cdecl; external OPENSSL_LIB name 'X509_gmtime_adj';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';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 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';// Message Digestfunction 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 ShowFuncStat(RetVal: integer; Mess: string);begin  if RetVal=1 then    writeln(Mess+' ok.')  else    writeln('Error:- '+Mess+'.');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');  // 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  // 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'), Length('US'), -1, -1), 'Set Country');  ShowFuncStat(X509_NAME_add_entry_by_txt(name, 'ST', MBSTRING_ASC, PAnsiChar('California'), Length('California'), -1, -1), 'Set State');  ShowFuncStat(X509_NAME_add_entry_by_txt(name, 'L', MBSTRING_ASC, PAnsiChar('San Francisco'), Length('San Francisco'), -1, -1), 'Set Location');  ShowFuncStat(X509_NAME_add_entry_by_txt(name, 'O', MBSTRING_ASC, PAnsiChar('My Organization'), Length('My Organization'), -1, -1), 'Set Organization');  ShowFuncStat(X509_NAME_add_entry_by_txt(name, 'OU', MBSTRING_ASC, PAnsiChar('My Organizational Unit'), Length('My Organizational Unit'), -1, -1), 'Set Department');  ShowFuncStat(X509_NAME_add_entry_by_txt(name, 'CN', MBSTRING_ASC, PAnsiChar('localhost'), Length('localhost'), -1, -1), '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  ShowFuncStat(X509_sign(x509, pkey, EVP_sha256()), 'Signing Certificate');  // 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.