mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 22:09:32 +02:00
fcl-web: TJWTSignerRSA: prefix hash with ASN1 digest info
This commit is contained in:
parent
22c86e857e
commit
e339f8b660
@ -14,6 +14,17 @@ uses
|
|||||||
const
|
const
|
||||||
RSAPublicKeyOID = '1.2.840.113549.1.1.1';
|
RSAPublicKeyOID = '1.2.840.113549.1.1.1';
|
||||||
|
|
||||||
|
RSADigestInfoSHA256 = 1;
|
||||||
|
RSADigestInfoSHA384 = 2;
|
||||||
|
RSADigestInfoSHA512 = 3;
|
||||||
|
RSADigestInfoSHA224 = 4;
|
||||||
|
RSADigestInfoSHA512_224 = 5;
|
||||||
|
RSADigestInfoSHA512_256 = 6;
|
||||||
|
RSADigestInfoSHA3_224 = 7;
|
||||||
|
RSADigestInfoSHA3_256 = 8;
|
||||||
|
RSADigestInfoSHA3_384 = 9;
|
||||||
|
RSADigestInfoSHA3_512 = 10;
|
||||||
|
|
||||||
type
|
type
|
||||||
TRSA = record
|
TRSA = record
|
||||||
M: PBigInt; // Modulus
|
M: PBigInt; // Modulus
|
||||||
@ -81,6 +92,8 @@ function RSADecryptVerify(var RSA: TRSA; const Input: PByte; Output: PByte; Len:
|
|||||||
function RS256VerifyFromPublicKeyHexa(const PublicKeyHexa, SignatureBaseHash, Signature: String): Boolean;
|
function RS256VerifyFromPublicKeyHexa(const PublicKeyHexa, SignatureBaseHash, Signature: String): Boolean;
|
||||||
function TestRS256Verify: Boolean;
|
function TestRS256Verify: Boolean;
|
||||||
|
|
||||||
|
function EncodeDigestInfoSHA(SHAType, len: byte): TBytes;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
const
|
const
|
||||||
@ -330,7 +343,7 @@ begin
|
|||||||
Exit;
|
Exit;
|
||||||
Size := RSA.ModulusLen;
|
Size := RSA.ModulusLen;
|
||||||
Padding := Size-Len-3;
|
Padding := Size-Len-3;
|
||||||
if Len > Size-11 then
|
if Len > Size-8-3 then
|
||||||
Exit;
|
Exit;
|
||||||
{$IFDEF CRYPTO_DEBUG}
|
{$IFDEF CRYPTO_DEBUG}
|
||||||
writeln('RSAEncryptSign - Len = ' + IntToStr(Len) + ' Size = ' + IntToStr(Size) + ' Padding = ' + IntToStr(Padding)); //To Do
|
writeln('RSAEncryptSign - Len = ' + IntToStr(Len) + ' Size = ' + IntToStr(Size) + ' Padding = ' + IntToStr(Padding)); //To Do
|
||||||
@ -642,5 +655,16 @@ begin
|
|||||||
Result := RsaVerify(Modulus, Exponent, Hash, Signature);
|
Result := RsaVerify(Modulus, Exponent, Hash, Signature);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function EncodeDigestInfoSHA(SHAType, len: byte): TBytes;
|
||||||
|
begin
|
||||||
|
Result:= [
|
||||||
|
ASN1_SEQ, 17 + len,
|
||||||
|
ASN1_SEQ, 13,
|
||||||
|
ASN1_OBJID, 9, 2*40 + 16, $86, $48, 1, 101, 3, 4, 2, SHAType,
|
||||||
|
ASN1_NULL, 0,
|
||||||
|
ASN1_OCTSTR, len
|
||||||
|
];
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -14,9 +14,9 @@ Type
|
|||||||
TJWTSignerRSA = Class(TJWTSigner)
|
TJWTSignerRSA = Class(TJWTSigner)
|
||||||
Public
|
Public
|
||||||
Class function AlgorithmName : String; override;
|
Class function AlgorithmName : String; override;
|
||||||
function ComputeHash(const Value: TBytes): TBytes; virtual; abstract;
|
function ComputeASNHash(const Value: TBytes): TBytes; virtual; abstract;
|
||||||
Function CreateSignature(aJWT : TJWT; aKey : TJWTKey) : String; override;
|
Function CreateSignature(aJWT : TJWT; aPrivateKey : TJWTKey) : String; override;
|
||||||
Function Verify(const aJWT : String; aKey : TJWTKey) : Boolean; override; overload;
|
Function Verify(const aJWT : String; aPublicKey : TJWTKey) : Boolean; override; overload;
|
||||||
end;
|
end;
|
||||||
TJWTSignerRSAClass = class of TJWTSignerRSA;
|
TJWTSignerRSAClass = class of TJWTSignerRSA;
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ Type
|
|||||||
TJWTSignerRS256 = class(TJWTSignerRSA)
|
TJWTSignerRS256 = class(TJWTSignerRSA)
|
||||||
public
|
public
|
||||||
class function AlgorithmName : String; override;
|
class function AlgorithmName : String; override;
|
||||||
function ComputeHash(const Value: TBytes): TBytes; override;
|
function ComputeASNHash(const Value: TBytes): TBytes; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TJWTSignerRS384 }
|
{ TJWTSignerRS384 }
|
||||||
@ -33,7 +33,7 @@ Type
|
|||||||
TJWTSignerRS384 = class(TJWTSignerRSA)
|
TJWTSignerRS384 = class(TJWTSignerRSA)
|
||||||
public
|
public
|
||||||
class function AlgorithmName : String; override;
|
class function AlgorithmName : String; override;
|
||||||
function ComputeHash(const Value: TBytes): TBytes; override;
|
function ComputeASNHash(const Value: TBytes): TBytes; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TJWTSignerRS512 }
|
{ TJWTSignerRS512 }
|
||||||
@ -41,7 +41,7 @@ Type
|
|||||||
TJWTSignerRS512 = class(TJWTSignerRSA)
|
TJWTSignerRS512 = class(TJWTSignerRSA)
|
||||||
public
|
public
|
||||||
class function AlgorithmName : String; override;
|
class function AlgorithmName : String; override;
|
||||||
function ComputeHash(const Value: TBytes): TBytes; override;
|
function ComputeASNHash(const Value: TBytes): TBytes; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -53,10 +53,11 @@ begin
|
|||||||
Result:='RS512';
|
Result:='RS512';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TJWTSignerRS512.ComputeHash(const Value: TBytes): TBytes;
|
function TJWTSignerRS512.ComputeASNHash(const Value: TBytes): TBytes;
|
||||||
begin
|
begin
|
||||||
Result:=nil;
|
Result:=nil;
|
||||||
TSHA512.DigestBytes(Value,Result);
|
TSHA512.DigestBytes(Value,Result);
|
||||||
|
Result:=Concat(EncodeDigestInfoSHA(RSADigestInfoSHA512,length(Result)),Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TJWTSignerRS384 }
|
{ TJWTSignerRS384 }
|
||||||
@ -66,10 +67,11 @@ begin
|
|||||||
Result:='RS384';
|
Result:='RS384';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TJWTSignerRS384.ComputeHash(const Value: TBytes): TBytes;
|
function TJWTSignerRS384.ComputeASNHash(const Value: TBytes): TBytes;
|
||||||
begin
|
begin
|
||||||
Result:=nil;
|
Result:=nil;
|
||||||
TSHA384.DigestBytes(Value,Result);
|
TSHA384.DigestBytes(Value,Result);
|
||||||
|
Result:=Concat(EncodeDigestInfoSHA(RSADigestInfoSHA384,length(Result)),Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TJWTSignerRS256 }
|
{ TJWTSignerRS256 }
|
||||||
@ -79,10 +81,11 @@ begin
|
|||||||
Result:='RS256';
|
Result:='RS256';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TJWTSignerRS256.ComputeHash(const Value: TBytes): TBytes;
|
function TJWTSignerRS256.ComputeASNHash(const Value: TBytes): TBytes;
|
||||||
begin
|
begin
|
||||||
Result:=nil;
|
Result:=nil;
|
||||||
TSHA256.DigestBytes(Value,Result);
|
TSHA256.DigestBytes(Value,Result);
|
||||||
|
Result:=Concat(EncodeDigestInfoSHA(RSADigestInfoSHA256,length(Result)),Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TJWTSignerRSA }
|
{ TJWTSignerRSA }
|
||||||
@ -93,9 +96,9 @@ begin
|
|||||||
Result:='RSA';
|
Result:='RSA';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TJWTSignerRSA.CreateSignature(aJWT: TJWT; aKey: TJWTKey): String;
|
function TJWTSignerRSA.CreateSignature(aJWT: TJWT; aPrivateKey: TJWTKey): String;
|
||||||
var
|
var
|
||||||
aSignInput, Hash, aSignature: TBytes;
|
aSignInput, ASNHash, aSignature: TBytes;
|
||||||
RSA: TRSA;
|
RSA: TRSA;
|
||||||
begin
|
begin
|
||||||
Result:='';
|
Result:='';
|
||||||
@ -103,13 +106,13 @@ begin
|
|||||||
aSignInput:=GetSignInput(aJWT);
|
aSignInput:=GetSignInput(aJWT);
|
||||||
if length(aSignInput)=0 then
|
if length(aSignInput)=0 then
|
||||||
raise Exception.Create('20220430010854: missing SignInput');
|
raise Exception.Create('20220430010854: missing SignInput');
|
||||||
Hash:=ComputeHash(aSignInput);
|
ASNHash:=ComputeASNHash(aSignInput);
|
||||||
|
|
||||||
RSACreate(RSA);
|
RSACreate(RSA);
|
||||||
try
|
try
|
||||||
RSAInitFromPrivateKeyDER(RSA,aKey.AsBytes);
|
RSAInitFromPrivateKeyDER(RSA,aPrivateKey.AsBytes);
|
||||||
SetLength(aSignature{%H-},RSA.ModulusLen);
|
SetLength(aSignature{%H-},RSA.ModulusLen);
|
||||||
if RSAEncryptSign(RSA,@Hash[0],length(Hash),@aSignature[0],true)<RSA.ModulusLen then
|
if RSAEncryptSign(RSA,@ASNHash[0],length(ASNHash),@aSignature[0],true)<RSA.ModulusLen then
|
||||||
raise Exception.Create('20220429223334');
|
raise Exception.Create('20220429223334');
|
||||||
Result:=Base64URL.Encode(@aSignature[0],Length(aSignature),False);
|
Result:=Base64URL.Encode(@aSignature[0],Length(aSignature),False);
|
||||||
finally
|
finally
|
||||||
@ -117,7 +120,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TJWTSignerRSA.Verify(const aJWT: String; aKey: TJWTKey): Boolean;
|
function TJWTSignerRSA.Verify(const aJWT: String; aPublicKey: TJWTKey): Boolean;
|
||||||
var
|
var
|
||||||
aHeader, theClaims, aSignature, aInput: String;
|
aHeader, theClaims, aSignature, aInput: String;
|
||||||
InputBytes, EncryptedHash, DecryptedHash, ActualHash: TBytes;
|
InputBytes, EncryptedHash, DecryptedHash, ActualHash: TBytes;
|
||||||
@ -135,7 +138,7 @@ begin
|
|||||||
// decrypt hash
|
// decrypt hash
|
||||||
RSACreate(RSA);
|
RSACreate(RSA);
|
||||||
try
|
try
|
||||||
RSAInitFromPublicKeyDER(RSA,aKey.AsBytes);
|
RSAInitFromPublicKeyDER(RSA,aPublicKey.AsBytes);
|
||||||
SetLength(DecryptedHash{%H-},length(EncryptedHash));
|
SetLength(DecryptedHash{%H-},length(EncryptedHash));
|
||||||
HashLen:=RSADecryptVerify(RSA,@EncryptedHash[0],@DecryptedHash[0],length(DecryptedHash),true);
|
HashLen:=RSADecryptVerify(RSA,@EncryptedHash[0],@DecryptedHash[0],length(DecryptedHash),true);
|
||||||
if HashLen<=0 then exit;
|
if HashLen<=0 then exit;
|
||||||
@ -148,7 +151,7 @@ begin
|
|||||||
aInput:=aHeader+'.'+theClaims;
|
aInput:=aHeader+'.'+theClaims;
|
||||||
SetLength(InputBytes{%H-},length(aInput));
|
SetLength(InputBytes{%H-},length(aInput));
|
||||||
Move(aInput[1],InputBytes[0],length(aInput));
|
Move(aInput[1],InputBytes[0],length(aInput));
|
||||||
ActualHash:=ComputeHash(InputBytes);
|
ActualHash:=ComputeASNHash(InputBytes);
|
||||||
|
|
||||||
// check decrypted hash and actual hash fit
|
// check decrypted hash and actual hash fit
|
||||||
Result:=(length(DecryptedHash)=length(ActualHash))
|
Result:=(length(DecryptedHash)=length(ActualHash))
|
||||||
|
Loading…
Reference in New Issue
Block a user