signrs256.lpr 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. {$mode objfpc}
  2. {$h+}
  3. uses jsonparser, dateutils, sysutils, fppem, fpjwt, fprsa, fphashutils, fpjwarsa;
  4. Type
  5. // The claims we want to sign in our JWT.
  6. // You can skip this class and just use TClaims if the standard claims are sufficient
  7. TMyClaims = Class(TClaims)
  8. private
  9. FAdmin: Boolean;
  10. FName: string;
  11. Published
  12. Property Name : string Read FName Write FName;
  13. Property admin : Boolean Read FAdmin Write FAdmin;
  14. end;
  15. // A JWT that uses our claims
  16. TMyJWT = Class(TJWT)
  17. Function CreateClaims : TClaims; override;
  18. end;
  19. function TMyJWT.CreateClaims: TClaims;
  20. begin
  21. Result:=TMyClaims.Create;
  22. end;
  23. // Read the private/public key data
  24. // In reality you will read this from a file.
  25. procedure GetTestPEM(out aPrivateKeyPEM, aPublicKeyPEM: string);
  26. const
  27. // generated with
  28. // openssl genrsa -out private.pem 2048
  29. PrivateKeyPem =
  30. '-----BEGIN RSA PRIVATE KEY-----'#10+
  31. 'MIIEpQIBAAKCAQEAvkRfGW8psCZ3G4+hBA6W/CR/FHhBLB3k3QLypamPbRFlFBxL'#10+
  32. 'tOK2NblBybY22vUiMLZbb5x8OoOj/IhOrJAlTqhtbTWLy/0K3qbG09vLm8V40kEK'#10+
  33. '8/p0STrp3UmsxHNkccj9MRSKk7pOyEvxSCY6K5JGK1VTsMuDCS7DCYk6Vqr3zjX7'#10+
  34. 'qedF1PVM+Z5t0B+f//kt3oBETNlic4IooEpG/PN2GUQ0oZpa16DDtfgGu7wT3X3Q'#10+
  35. 'EZFWLJYQTvGc82NpachBIUvqNdIt1npbK38MXU4IPHVrSN/HdK2nQPSMLdKnTV+E'#10+
  36. 'h/HcxpfjBjarg+VjgDqlmqJ9bkosOVn35vsg8wIDAQABAoIBAQCZxVwujB7fFFdS'#10+
  37. '2QPC6Z+w7DYgbwgNBaP/0vAUXzNhbJuKY0v0Rv4H8U9wHGm9EDyvrdG8JHZqPBX+'#10+
  38. 'dJNQ97aPGaRGjO4M0NdGFve+JXcqz6/UDWkywYnV3V1A0NhmdPQK2et3DSjqN7qQ'#10+
  39. 'OoAoVWzR5gf74Zwf2Hpwo3BRdqzFeUYVDOH7e7q1SOf2QeU54kVUG21saJR0wsyH'#10+
  40. 'oSX8BMU2kmg1Un8ET4FM5xEwhdTZzgFTJVZhc6EfOKVbQt6cKmW3aER3c9vR7M3l'#10+
  41. 'N6Oq73vqrfmy+jFMwz1SoPObQQ7UAnr7YUowaX0AzxHpYm/afyVm+Toym0qWGrrY'#10+
  42. 'MY/l+vNRAoGBAOsi72pJj30ApfVbSpx8/8QIpweLbEgAD+Ssd41Kgc4O/N7azB61'#10+
  43. 'RjzSOs1BGhpAZNU6muAAbucm9EssfG5WTAjIM2W2LVuZXXEVXqEGkIymPz9NGugf'#10+
  44. 'JaCWLaoibmwHkKa+ZV9kDwasmx/VkbAfAbRWaz49ejdrMmkpCW77lYjHAoGBAM8m'#10+
  45. 'PVJWvFhQrB21xQGSWKd5iSUn2V92gICeDoORqfVtt/UPOaDT915KzXPh4bJeOwg6'#10+
  46. 'Kkx5wX6UwaNSRH39loDSY1rsBYioV8bxW0BpBvEJG7KXRbBvxzr0+TJkCHgmGMns'#10+
  47. 'dhePYUcriCaqpQi1yzf201oLTZ6PlJxkmHQobXJ1AoGBAIgWPg576InmWCa64WHU'#10+
  48. 'joq8nz8kmFTLhGdK0h56IspJrlyksUKMk8wbuGCW7y6GWlV2h7BhT86Eoxrm8lVB'#10+
  49. 'qNvkUqrpVzMOfiA2x//WNs7QYQaX75ysejCI+oDfUJ1Be5yl0TH2TSQFvfoctycB'#10+
  50. 'qxDee08YcaWlaxWl5InRHeh9AoGABm3XZWDPw6XtUZa8oIncOoZpHUAZXP8eid9d'#10+
  51. '7/NrZPScyvxH+5fYi5Kiwb/280Q9bMnxWiJFQRp40ArTmV1veFwPPVkp6s3eu4vu'#10+
  52. 'GxenYX+43lgXj5xIgKntugSkxqXYCxxNpfmLOVw+g4S0Torl3bzJXngPVqZ6JEhy'#10+
  53. '+tfuXakCgYEA19/JCD/5pVPJtwyDDAYnUUESK+JfBPq1cTbsxcOq01mp5ntsqR4y'#10+
  54. 'dtOAmxMASvsqud3XIM5fO5m3Jpl1phiGhCw4nvVLcYzVWxYY+oWoeCSyECgu5tmT'#10+
  55. 'Fo8vn4EEXCkEAA2YPiEuVcrcYsWkLivCTC19lJDfUNMmpwSdiGz/tDU='#10+
  56. '-----END RSA PRIVATE KEY-----'#10;
  57. PublicKeyPem =
  58. '-----BEGIN PUBLIC KEY-----'#10+
  59. 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvkRfGW8psCZ3G4+hBA6W'#10+
  60. '/CR/FHhBLB3k3QLypamPbRFlFBxLtOK2NblBybY22vUiMLZbb5x8OoOj/IhOrJAl'#10+
  61. 'TqhtbTWLy/0K3qbG09vLm8V40kEK8/p0STrp3UmsxHNkccj9MRSKk7pOyEvxSCY6'#10+
  62. 'K5JGK1VTsMuDCS7DCYk6Vqr3zjX7qedF1PVM+Z5t0B+f//kt3oBETNlic4IooEpG'#10+
  63. '/PN2GUQ0oZpa16DDtfgGu7wT3X3QEZFWLJYQTvGc82NpachBIUvqNdIt1npbK38M'#10+
  64. 'XU4IPHVrSN/HdK2nQPSMLdKnTV+Eh/HcxpfjBjarg+VjgDqlmqJ9bkosOVn35vsg'#10+
  65. '8wIDAQAB'#10+
  66. '-----END PUBLIC KEY-----';
  67. begin
  68. aPrivateKeyPEM:=PrivateKeyPem;
  69. aPublicKeyPEM:=PublicKeyPem;
  70. end;
  71. Procedure CreateKeyAndJWT(out Key : TJWTKey; Out JWT : TJWT);
  72. begin
  73. Key:=TJWTKey.Create('mysecretkey');
  74. JWT:=TMyJWT.Create;
  75. JWT.JOSE.alg:='none';
  76. JWT.JOSE.typ:='JWT';
  77. JWT.Claims.sub:='1234567890';
  78. JWT.Claims.iat:=1516239022;
  79. (JWT.Claims as TMyClaims).Name:='John Doe';
  80. end;
  81. var
  82. aInput, aPrivateKeyPEM, aPublicKeyPEM: String;
  83. Key: TJWTKey;
  84. VerifyResult,JWT : TJWT;
  85. Signer: TJWTSigner;
  86. NewDER: TBytes;
  87. RSAPublic: TX509RSAPublicKey;
  88. RSAPrivate: TX509RSAPrivateKey;
  89. begin
  90. CreateKeyAndJWT(Key,JWT);
  91. GetTestPEM(aPrivateKeyPEM, aPublicKeyPEM);
  92. // header
  93. jwt.JOSE.alg:=TJWTSignerRS256.AlgorithmName;
  94. // claims
  95. jwt.Claims.exp:=DateTimeToUnix(Now+10);
  96. jwt.Claims.iss:='FPC JWT';
  97. // load private key from pem
  98. Key.AsBytes:=PemToDER(APrivateKeyPem,_BEGIN_RSA_PRIVATE_KEY,_END_RSA_PRIVATE_KEY);
  99. X509RsaPrivateKeyInitFromDER(RSAPrivate,Key.AsBytes);
  100. NewDER:=RSAPrivate.AsDER;
  101. if (length(Key.AsBytes)<>length(NewDER)) or
  102. not CompareMem(@Key.AsBytes[0],@NewDER[0],length(NewDER)) then
  103. Raise exception.Create('TX509RSAPrivateKey.AsDER does not match!');
  104. // sign
  105. Signer:=TJWTSignerRS256.Create;
  106. try
  107. aInput:=Signer.AppendSignature(JWT,Key);
  108. finally
  109. Signer.Free;
  110. end;
  111. Writeln('Our JWT Token: ',aInput);
  112. // load public key from pem
  113. Key.AsBytes:=PemToDER(APublicKeyPem,_BEGIN_PUBLIC_KEY,_END_PUBLIC_KEY);
  114. X509RsaPublicKeyInitFromDER(RSAPublic,Key.AsBytes);
  115. NewDER:=RSAPublic.AsDER;
  116. if (length(Key.AsBytes)<>length(NewDER)) or
  117. not CompareMem(@Key.AsBytes[0],@NewDER[0],length(NewDER)) then
  118. Raise exception.Create('TX509RSAPublicKey.AsDER does not match');
  119. // verify our generated token. This generates a new JWT
  120. VerifyResult:=TMyJWT.ValidateJWT(aInput,Key);
  121. if VerifyResult=Nil then
  122. Raise Exception.Create('No verify resultn, verification failed!');
  123. end.