utestpem.pp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. unit utestpem;
  2. {$mode ObjFPC}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, fpcunit, testregistry, basenenc,
  6. fpTLSBigInt, fppem, fprsa, fphashutils, fpecc;
  7. Type
  8. { TTestPEM }
  9. TTestPEM = Class(TTestCase)
  10. protected
  11. procedure GetPEM_PrivateKeyRSA2048bit(out PrivatePEM, PublicPEM: Ansistring);
  12. Published
  13. Procedure TestECC_Load;
  14. Procedure TestRSA_RS256Verify;
  15. Procedure TestRSA_PrivatePublicPEM_NoPassphrase;
  16. end;
  17. implementation
  18. function LinesToText(Lines: array of string): string;
  19. var
  20. i: Integer;
  21. begin
  22. Result:='';
  23. for i:=low(Lines) to High(Lines) do
  24. Result:=Result+Lines[i]+sLineBreak;
  25. end;
  26. { TTestPEM }
  27. Const
  28. PrivateKeyFile = 'private-key.pem';
  29. procedure TTestPEM.GetPEM_PrivateKeyRSA2048bit(out PrivatePEM, PublicPEM: Ansistring
  30. );
  31. begin
  32. // generated with
  33. // openssl genrsa -out private.pem 2048
  34. PrivatePEM:=LinesToText([
  35. '-----BEGIN RSA PRIVATE KEY-----',
  36. 'MIIEpQIBAAKCAQEAvkRfGW8psCZ3G4+hBA6W/CR/FHhBLB3k3QLypamPbRFlFBxL',
  37. 'tOK2NblBybY22vUiMLZbb5x8OoOj/IhOrJAlTqhtbTWLy/0K3qbG09vLm8V40kEK',
  38. '8/p0STrp3UmsxHNkccj9MRSKk7pOyEvxSCY6K5JGK1VTsMuDCS7DCYk6Vqr3zjX7',
  39. 'qedF1PVM+Z5t0B+f//kt3oBETNlic4IooEpG/PN2GUQ0oZpa16DDtfgGu7wT3X3Q',
  40. 'EZFWLJYQTvGc82NpachBIUvqNdIt1npbK38MXU4IPHVrSN/HdK2nQPSMLdKnTV+E',
  41. 'h/HcxpfjBjarg+VjgDqlmqJ9bkosOVn35vsg8wIDAQABAoIBAQCZxVwujB7fFFdS',
  42. '2QPC6Z+w7DYgbwgNBaP/0vAUXzNhbJuKY0v0Rv4H8U9wHGm9EDyvrdG8JHZqPBX+',
  43. 'dJNQ97aPGaRGjO4M0NdGFve+JXcqz6/UDWkywYnV3V1A0NhmdPQK2et3DSjqN7qQ',
  44. 'OoAoVWzR5gf74Zwf2Hpwo3BRdqzFeUYVDOH7e7q1SOf2QeU54kVUG21saJR0wsyH',
  45. 'oSX8BMU2kmg1Un8ET4FM5xEwhdTZzgFTJVZhc6EfOKVbQt6cKmW3aER3c9vR7M3l',
  46. 'N6Oq73vqrfmy+jFMwz1SoPObQQ7UAnr7YUowaX0AzxHpYm/afyVm+Toym0qWGrrY',
  47. 'MY/l+vNRAoGBAOsi72pJj30ApfVbSpx8/8QIpweLbEgAD+Ssd41Kgc4O/N7azB61',
  48. 'RjzSOs1BGhpAZNU6muAAbucm9EssfG5WTAjIM2W2LVuZXXEVXqEGkIymPz9NGugf',
  49. 'JaCWLaoibmwHkKa+ZV9kDwasmx/VkbAfAbRWaz49ejdrMmkpCW77lYjHAoGBAM8m',
  50. 'PVJWvFhQrB21xQGSWKd5iSUn2V92gICeDoORqfVtt/UPOaDT915KzXPh4bJeOwg6',
  51. 'Kkx5wX6UwaNSRH39loDSY1rsBYioV8bxW0BpBvEJG7KXRbBvxzr0+TJkCHgmGMns',
  52. 'dhePYUcriCaqpQi1yzf201oLTZ6PlJxkmHQobXJ1AoGBAIgWPg576InmWCa64WHU',
  53. 'joq8nz8kmFTLhGdK0h56IspJrlyksUKMk8wbuGCW7y6GWlV2h7BhT86Eoxrm8lVB',
  54. 'qNvkUqrpVzMOfiA2x//WNs7QYQaX75ysejCI+oDfUJ1Be5yl0TH2TSQFvfoctycB',
  55. 'qxDee08YcaWlaxWl5InRHeh9AoGABm3XZWDPw6XtUZa8oIncOoZpHUAZXP8eid9d',
  56. '7/NrZPScyvxH+5fYi5Kiwb/280Q9bMnxWiJFQRp40ArTmV1veFwPPVkp6s3eu4vu',
  57. 'GxenYX+43lgXj5xIgKntugSkxqXYCxxNpfmLOVw+g4S0Torl3bzJXngPVqZ6JEhy',
  58. '+tfuXakCgYEA19/JCD/5pVPJtwyDDAYnUUESK+JfBPq1cTbsxcOq01mp5ntsqR4y',
  59. 'dtOAmxMASvsqud3XIM5fO5m3Jpl1phiGhCw4nvVLcYzVWxYY+oWoeCSyECgu5tmT',
  60. 'Fo8vn4EEXCkEAA2YPiEuVcrcYsWkLivCTC19lJDfUNMmpwSdiGz/tDU=',
  61. '-----END RSA PRIVATE KEY-----' ]);
  62. // public key extracted with
  63. // openssl rsa -in private.pem -outform PEM -pubout -out public.pem
  64. PublicPEM:=LinesToText([
  65. '-----BEGIN PUBLIC KEY-----',
  66. 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvkRfGW8psCZ3G4+hBA6W',
  67. '/CR/FHhBLB3k3QLypamPbRFlFBxLtOK2NblBybY22vUiMLZbb5x8OoOj/IhOrJAl',
  68. 'TqhtbTWLy/0K3qbG09vLm8V40kEK8/p0STrp3UmsxHNkccj9MRSKk7pOyEvxSCY6',
  69. 'K5JGK1VTsMuDCS7DCYk6Vqr3zjX7qedF1PVM+Z5t0B+f//kt3oBETNlic4IooEpG',
  70. '/PN2GUQ0oZpa16DDtfgGu7wT3X3QEZFWLJYQTvGc82NpachBIUvqNdIt1npbK38M',
  71. 'XU4IPHVrSN/HdK2nQPSMLdKnTV+Eh/HcxpfjBjarg+VjgDqlmqJ9bkosOVn35vsg',
  72. '8wIDAQAB',
  73. '-----END PUBLIC KEY-----' ]);
  74. end;
  75. procedure TTestPEM.TestECC_Load;
  76. Const
  77. // Hex encoded keys, Obtained using XMLRAD
  78. // Private key matched openssl
  79. // openssl ec -text -in private-key.pem -noout
  80. resprivatekey = '8D8DC61A006BF4E8C508ACFDEB331E385E763B6C4CD52B918C438D5B1804A5A9';
  81. respublickey = '03675CA1BD5D466F5EE30CEC92FDECCB0834A6467E7013CAF05C7B68648F7DB93C';
  82. ResX = 'Z1yhvV1Gb17jDOyS_ezLCDSmRn5wE8rwXHtoZI99uTw';
  83. ResY = 'kBzplHWhOlp71lYjOaoK6Bfo9crVT3mbCEAWqK-1FVs';
  84. // Obtained through OpenSSL: public key as X&Y (DER 04 prefix removed)
  85. ResXY = {04}
  86. '675ca1bd5d466f5ee30cec92fdec'+
  87. 'cb0834a6467e7013caf05c7b68648f'+
  88. '7db93c901ce99475a13a5a7bd65623'+
  89. '39aa0ae817e8f5cad54f799b084016'+
  90. 'a8afb5155b';
  91. var
  92. List: TStrings;
  93. PrivateKey : TEccPrivateKey;
  94. PublicKey : TEccPublicKey;
  95. XHex,YHex,PublicKeyX64, PublicKeyY64 : Ansistring;
  96. Res : Boolean;
  97. begin
  98. List := TStringList.Create;
  99. try
  100. PrivateKey:=Default(TEccPrivateKey);
  101. PublicKey:=Default(TEccPublicKey);
  102. Res:=FileExists(PrivateKeyFile) and PemIsECDSA(PrivateKeyFile, List);
  103. AssertTrue('Have file with Key',Res);
  104. if Res then
  105. PemLoadPublicKey64FromList(List, PrivateKey, PublicKey, PublicKeyX64, PublicKeyY64);
  106. AssertEquals('Private key',resprivatekey,BytesToHexStr(BytesFromVar(@PrivateKey,Sizeof(PrivateKey))));
  107. AssertEquals('Public key',respublickey,BytesToHexStr(BytesFromVar(@PublicKey,Sizeof(PublicKey))));
  108. AssertEquals('X',resX,PublicKeyX64);
  109. AssertEquals('Y',resY,PublicKeyY64);
  110. XHex:=base16.Encode(base64url.Decode(PublicKeyX64),False);
  111. YHex:=base16.Encode(base64url.Decode(PublicKeyY64),False);
  112. AssertEquals('Public as X,Y',ResXY,LowerCase(XHex+YHex));
  113. // Writeln('X ', PublicKeyX64,' -> ',XHex);
  114. // Writeln('Y ', PublicKeyY64,' -> ',YHex);
  115. finally
  116. List.Free;
  117. end;
  118. end;
  119. procedure TTestPEM.TestRSA_RS256Verify;
  120. begin
  121. if not fprsa.TestRS256Verify then
  122. Fail('TestRS256Verify');
  123. end;
  124. procedure TTestPEM.TestRSA_PrivatePublicPEM_NoPassphrase;
  125. const
  126. SecretMsg = 'FreePascal RSA Test';
  127. var
  128. PrivatePEM, PublicPEM, Original, Encrypted, Decrypted: Ansistring;
  129. DER: TBytes;
  130. PrivateRSA, PublicRSA: TRSA;
  131. EncryptedLen, DecryptedLen: Integer;
  132. begin
  133. GetPEM_PrivateKeyRSA2048bit(PrivatePEM, PublicPEM);
  134. RSACreate(PublicRSA);
  135. RSACreate(PrivateRSA);
  136. try
  137. // load public key
  138. DER:=PemToDER(PublicPEM,_BEGIN_PUBLIC_KEY,_END_PUBLIC_KEY);
  139. if length(DER)=0 then
  140. Fail('PemToDER public key');
  141. RSAInitFromPublicKeyDER(PublicRSA,DER);
  142. // load private key
  143. DER:=PemToDER(PrivatePEM,_BEGIN_RSA_PRIVATE_KEY,_END_RSA_PRIVATE_KEY);
  144. if length(DER)=0 then
  145. Fail('PemToDER private rsa key');
  146. RSAInitFromPrivateKeyDER(PrivateRSA,DER);
  147. AssertEquals('PublicRSA.ModulusLen=PrivateRSA.ModulusLen',PublicRSA.ModulusLen,PrivateRSA.ModulusLen);
  148. if BICompare(PublicRSA.M,PrivateRSA.M)<>0 then
  149. Fail('PublicRSA.M = PrivateRSA.M');
  150. if BICompare(PublicRSA.E,PrivateRSA.E)<>0 then
  151. Fail('PublicRSA.E = PrivateRSA.E');
  152. Original:=SecretMsg;
  153. // encrypt with public key
  154. SetLength(Encrypted{%H-},PublicRSA.ModulusLen);
  155. EncryptedLen:=RSAEncryptSign(PublicRSA,@Original[1],length(Original),@Encrypted[1],false);
  156. if EncryptedLen<PublicRSA.ModulusLen then
  157. AssertEquals('EncryptedLen = ModulusLen',EncryptedLen,PublicRSA.ModulusLen);
  158. // decrypt with private key
  159. SetLength(Decrypted{%H-},EncryptedLen);
  160. DecryptedLen:=RSADecryptVerify(PrivateRSA,@Encrypted[1],@Decrypted[1],EncryptedLen,false);
  161. if DecryptedLen<>length(Original) then
  162. AssertEquals('DecryptedLen = length(Original)',DecryptedLen,length(Original));
  163. SetLength(Decrypted,DecryptedLen);
  164. if Decrypted<>Original then
  165. Fail('Decrypted = Original');
  166. finally
  167. RSAFree(PublicRSA);
  168. RSAFree(PrivateRSA);
  169. end;
  170. end;
  171. initialization
  172. RegisterTest(TTestPEM);
  173. end.