How to generate certificates example the easy way lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- Thaddy · 2024-03-01 17:53 How about this, can be improved (factor out the write loop, save to file, etc) but it generates a key pair that is accepted, apart from the CA part in browsers of course, but you know that.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 testcert;{$mode objfpc}{$I-}{$H+}uses   sysutils, base64, classes, sslbase, openssl, fpopenssl; var   X509:TOpenSSLX509Certificate;   certkey:TCertAndKey;   pk,cr:TBytes;   e:ansistring;   i:integer;begin   X509:=TOpenSSLX509Certificate.Create;   try     certkey:=X509.CreateCertificateAndKey;     cr:=certkey.certificate;   pk:=certkey.privatekey;     setstring(e,Pchar(certkey.Certificate),length(certkey.Certificate));     e:=EncodeStringBase64(e);     writeln('-----BEGIN CERTIFICATE-----');     for i :=1 to length(e) do     begin       write(e[i]);       if (i mod 64 = 0) or (i >=length(e)) then writeln;     end;     writeln('-----END CERTIFICATE-----');     writeln;     setstring(e,PAnsiChar(certkey.PrivateKey),length(certkey .PrivateKey));     e:=EncodeStringBase64(e);     writeln('-----BEGIN RSA PRIVATE KEY-----');     for i :=1 to length(e) do     begin       write(e[i]);       if (i mod 64 = 0) or (i >=length(e)) then writeln;     end;     writeln('-----END RSA PRIVATE KEY-----');   finally     X509.Free;   end;end.It is a 40 liner, but be careful. The certificates are accepted, though. I got fed up with complex code, as usual, and this is a 40 liner. Users must in reality split up the code to cer and pem. But this is how it works, provided openssl is installed correctly. (cross platform tested) ---------------------------------------------------------------------- MarkMLl · 2024-03-02 08:34 I like it, and I can assure you that I'd be the last person to criticise you for putting straightforward code into an example. Can I ask for a bit more: if you wanted to get a fingerprint of a file, sign this with the private key you've just generated, and later validate it with the corresponding public key, how would you go about it? MarkMLl ---------------------------------------------------------------------- Thaddy · 2024-03-02 08:46 Mark, there is other code in that default tree that I am exploring now. I might be able to come up with a clear solution for your request. Point is, there is a lot of code available to us that is largely unexplored. ---------------------------------------------------------------------- MarkMLl · 2024-03-02 12:43 It's certainly interesting, and you've got a better grounding in this than I have. MarkMLl ---------------------------------------------------------------------- TRon · 2024-03-02 13:20 Quote from: MarkMLl on March 02, 2024, 01:43:24 pmIt's certainly interesting, and you've got a better grounding in this than I have. +1 Thank you for that example Thaddy. My problem is more that the interwebs is scattered with examples using deprecated functionality (not to mention that openssl documentation is ... of another category    ) . It might be able to work fantastic but there is a lot of functionality missing our header files in that case (I do not even have the capacity/knowledge to be able to tell whether that is a good or bad thing). ---------------------------------------------------------------------- Thaddy · 2024-03-02 13:35 The headers in trunk are up to date enough. I chose simply Michael's defaults in fpopenssl. but the class can set the properties, so that is OK. There will be updates, though. I have a lot to play with, including some small patches for fcl-net. (TLS1.3 and higher support) ---------------------------------------------------------------------- Fibonacci · 2024-03-02 14:28 Why fpopenssl.pp by default has {$DEFINE DUMPCERT} which dumps the cert to /tmp/x509.txt or C:\temp\x509.txt? I dont think this is what is expected. ---------------------------------------------------------------------- Thaddy · 2024-03-02 14:34 The unit is quite new. That should not be enabled by default, I agree. Anyway I added a dot.. And submitted a bug report. edit Already fixed in trunk. Thank you Michael! ---------------------------------------------------------------------- Fibonacci · 2024-03-02 19:20 Quote from: Thaddy on March 02, 2024, 03:34:56 pmAnd submitted a bug report. edit Already fixed in trunk. Thank you Michael! Where is thank you for me? I found this "bug" BTW. Is this unit really that new? That define was there since 5 years. ---------------------------------------------------------------------- Thaddy · 2024-03-02 19:49 Well, I found it too, but  thanks... ---------------------------------------------------------------------- BSaidus · 2024-03-15 22:17 Hello. Thanks @Thaddy for this code. I indeed generate a pair of certificate, just want to informe while decoding the public cert, I do not take account of dates ( ValidFrom, ValidTo) 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 testcert; {$mode objfpc}{$I-}{$H+}  uses   sysutils,   DateUtils,   base64,   classes,   sslbase,   openssl,   fpopenssl;   var   XL509  : TOpenSSLX509Certificate;   LCertkey : TCertAndKey;   LPk ,LCr : TBytes;   LE       : AnsiString;   I        : Integer;   LNow, L10Now: TDateTime;begin    LNow := TDateTime( Now() );   L10Now := TDateTime( IncYear(Now(), 10) );    XL509 := TOpenSSLX509Certificate.Create;   XL509.CommonName   := 'uccenos.net';   XL509.Country      := 'DZ';   XL509.HostName     := 'uc1.uccenos.net';   XL509.Organization := 'uccen';   XL509.ValidFrom    := LNow;   XL509.ValidTo      := L10Now;    //XL509.Version      := 1;   XL509.KeySize      := 2048;    try      LCertkey := XL509.CreateCertificateAndKey;        LCr      := LCertkey.certificate;     LPk      := LCertkey.privatekey;     SetString( LE, PChar(LCertkey.Certificate), Length(LCertkey.Certificate) );     LE       := EncodeStringBase64(LE);      writeln('-----BEGIN CERTIFICATE-----');      for I :=1 to length(LE) do     begin       write(LE[I]);       if (I mod 64 = 0) or (I >=length(LE)) then writeln;     end;      writeln('-----END CERTIFICATE-----');     writeln;      SetString( LE, PAnsiChar(LCertkey.PrivateKey), Length(LCertkey.PrivateKey) );     LE       := EncodeStringBase64(LE);      writeln('-----BEGIN RSA PRIVATE KEY-----');      for I :=1 to length(LE) do     begin       write(LE[I]);       if (I mod 64 = 0) or (I >=length(LE)) then writeln;     end;      writeln('-----END RSA PRIVATE KEY-----');    finally      XL509.Free;    end; end. ---------------------------------------------------------------------- toby · 2024-03-17 20:31 BSaidus adding writeln for the following variables gives lnow :  4.5368843078414349E+004  l10now :  4.9020843078414349E+004 xl509.validfrom :  4.5368843078414349E+004  xl509.validto :  4.9020843078414349E+004 but using openssl x509 -in x509.txt -text -noout gives Validity             Not Before: Bad time value             Not After : Bad time value using openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout x509.txt -out x509.txt gives good dates with openssl x509 -in x509.txt -text -noout openssl version   gives OpenSSL 3.0.5 5 Jul 2022 (Library: OpenSSL 3.0.5 5 Jul 2022) ---------------------------------------------------------------------- Fibonacci · 2024-03-17 20:39 Works for me 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 openssl x509 -in x509.txt -text -noout 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         Version: 1 (0x0)        Serial Number: 10 (0xa)        Signature Algorithm: sha1WithRSAEncryption        Issuer: C = DZ, CN = uc1.uccenos.net, O = uccen        Validity            Not Before: Mar 17 21:39:13 2024 GMT            Not After : Mar 17 21:39:13 2034 GMT      Subject: C = DZ, CN = uc1.uccenos.net, O = uccen DLL version OpenSSL 3.0.1 14 Dec 2021 (writeln(OpenSSLGetVersion(0))) CLI version OpenSSL 1.1.1l 24 Aug 2021 ---------------------------------------------------------------------- toby · 2024-03-17 21:16 writeln(now); LNow := TDateTime(Now()); writeln(lnow); both writelns give the same 'now' output - shouldn't tdatetime(now) convert to a readable date/time? openssl x509 -in x509.txt -text -noout         Version: 1 (0x0)         Serial Number: 10 (0xa)         Signature Algorithm: sha1WithRSAEncryption         Issuer: C = DZ, CN = uc1.uccenos.net, O = uccen         Validity             Not Before: Bad time value             Not After : Bad time value         Subject: C = DZ, CN = uc1.uccenos.net, O = uccen ---------------------------------------------------------------------- Fibonacci · 2024-03-17 21:23 Quote from: toby on March 17, 2024, 10:16:23 pmwriteln(now); LNow := TDateTime(Now()); writeln(lnow); both writelns give the same 'now' output - shouldn't tedatetime(now) convert to a readable date/time? No. Why should it if both Now() and LNow return the same type? Now() is already TDateTime, dont cast it to TDateTime, it wont do anything. You can use DateTimeToStr() from SysUtils to convert it to a readable format. ---------------------------------------------------------------------- toby · 2024-03-17 21:34 Fibonacci said : No. Why should it if both Now() and LNow return the same type? Now() is already TDateTime, dont cast it to TDateTime, it wont do anything. then why is it in his code? LNow := TDateTime(Now()); L10Now := TDateTime(IncYear(Now(), 10)); i am on linux btw ---------------------------------------------------------------------- Fibonacci · 2024-03-17 21:37 I have no idea Thats not my code. You can shorten it to: 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 LNow := Now;L10Now := IncYear(LNow, 10); ---------------------------------------------------------------------- toby · 2024-03-17 21:43 Fibonacci i assume you are using windows i get the same with thaddy's original code where there is no direct use of now and now + 10 yeears  so it should default to 30 days is there a problem in the linux fpopenssl.pp? ---------------------------------------------------------------------- Fibonacci · 2024-03-17 21:46 May be. Lets wait for someone else to confirm (on Linux), and then perhaps we can report an issue. EDIT: Actually, I checked it myself. Linux Mint. 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         Version: 1 (0x0)        Serial Number: 10 (0xa)        Signature Algorithm: sha1WithRSAEncryption        Issuer: C = DZ, CN = uc1.uccenos.net, O = uccen        Validity            Not Before: Bad time value            Not After : Bad time value        Subject: C = DZ, CN = uc1.uccenos.net, O = uccen OpenSSL 3.0.2 15 Mar 2022 ---------------------------------------------------------------------- toby · 2024-03-17 22:10 i'm gonna take a guess that the problem is in this fpopenssl.pp  procedure 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 TOpenSSLX509Certificate.SetTimes(x : PX509);var  Utc : PASN1_UTCTIME;begin  Utc:=Asn1UtctimeNew;  tryASN1UtcTimeSetString(Utc ,PAnsiChar(FormatDateTime('YYMMDDHHNNSS',ValidFrom)));    X509SetNotBefore(x, Utc);SN1UtcTimeSetString(Utc,PAnsiChar(FormatDateT ime('YYMMDDHHNNSS',ValidTo)));    X509SetNotAfter(x,Utc);  finally    Asn1UtctimeFree(Utc);  end;end; ---------------------------------------------------------------------- Fibonacci · 2024-03-17 22:13 Probably. In trunk this proc looks different. 3 months ago this was changed: https://gitlab.com/freepascal.org/fpc/source/- /commit/fb9bcac2d3c1dd1178b6a7ce090e0345014ad04f How old is your installation? Cos mine is surely older than 3 months This is it. Confirmed. Update the unit and it works fine. ---------------------------------------------------------------------- toby · 2024-03-17 22:25 for sure - 6 months fpc-3.3.1 9/15/23 ---------------------------------------------------------------------- BSaidus · 2024-03-17 22:45 I've tested the prog using trunk version of fpc. It works well. Quote from: toby on March 17, 2024, 10:34:47 pmFibonacci said : No. Why should it if both Now() and LNow return the same type? Now() is already TDateTime, dont cast it to TDateTime, it wont do anything. then why is it in his code? LNow := TDateTime(Now()); L10Now := TDateTime(IncYear(Now(), 10)); i am on linux btw Yes then Now() return TDateTime, I did that just to be sur I do well, but you can do without casting. It will be better to add property 'SUBJECT' of type string to mimic the openssl subject. trying to decode the generated certificate it lakes some params & SHA1 is depricated QuoteCertificate Information: Common Name: uc1.uccenos.net Subject Alternative Names (SANs): N/A Organization: uccen Locality: N/A State: N/A Country: DZ Valid From: 2024-03-17 23:43:24 UTC Valid To: 2034-03-17 23:43:24 UTC Issuer: uc1.uccenos.net Serial Number: 0A Algorithm: sha1WithRSAEncryption Key size: 2048 ---------------------------------------------------------------------- toby · 2024-03-17 23:22 BSaidus yes very nice now with the updated fpopenssl.pp (also needed to update the openssl.pp)- your adding the XL509 : TOpenSSLX509Certificate; class code is a very nice addition/completion to the original posters code. adding openssl Subject woruld be good you can 'decode' the cert with openssl x509 -in x509.txt -text -noout ---------------------------------------------------------------------- Thaddy · 2024-03-18 05:27 expect newer examples soon. michael authored some neat new code in trunk from saturday. (examples in fcl-hash) ---------------------------------------------------------------------- toby · 2024-03-19 18:38 BSaidus to not need incyear (just to reduce needing dateutils in uses clause) //L10Now := lnow + 3.6520000000000000E+003; // 10 year L10Now := lnow + 3.6500000000000000E+002; // 1 year however 'removing' dateutils didn't reduce size of resulting executable - so it must be used in one of the other units same with classes and openssl