fcl-hash: rsa encrypt: fixed using non zero padding bytes

This commit is contained in:
mattias 2022-04-29 00:18:24 +02:00
parent 864b2ad3f3
commit 8639593574
3 changed files with 73 additions and 20 deletions

View File

@ -852,7 +852,7 @@ begin
raise Exception.Create(IntToStr(Id));
if ASNSize<8 then
begin
SetLength(Result,ASNSize);
SetLength(Result{%H-},ASNSize);
Value:=StrToInt64Def(List[ListIndex],0);
for i:=ASNSize-1 downto 0 do
begin

View File

@ -45,7 +45,7 @@ Procedure BytesToHexStrAppend(aBytes : TBytes;var aHexStr : AnsiString);
procedure BytesEncodeBase64(Source: Tbytes; out Dest: AnsiString; const IsURL, MultiLines, Padding: Boolean);
Function BytesEncodeBase64(Source: Tbytes; const IsURL, MultiLines, Padding: Boolean) : AnsiString;
function CryptoGetRandomBytes(Buffer: PByte; const Count: Integer): Boolean;
function CryptoGetRandomBytes(Buffer: PByte; const Count: Integer; ZeroBytesAllowed: boolean = true): Boolean;
Function ExtractBetween(const ASource,aStart,aEnd : String) : String;
Type
@ -345,6 +345,7 @@ type
TLecuyer = record
rs1, rs2, rs3: UInt32;
SeedCount: UInt32;
ZeroBytesAllowed: boolean;
procedure Seed;
function Next: UInt32;
end;
@ -372,26 +373,36 @@ end;
function TLecuyer.Next: UInt32;
begin
if SeedCount and $FFFF = 0 then // reseed after 256KB of output
Seed
else
Inc(SeedCount);
Result := rs1;
rs1 := ((Result and -2) shl 12) xor (((Result shl 13) xor Result) shr 19);
Result := rs2;
rs2 := ((Result and -8) shl 4) xor (((Result shl 2) xor Result) shr 25);
Result := rs3;
rs3 := ((Result and -16) shl 17) xor (((Result shl 3) xor Result) shr 11);
Result := rs1 xor rs2 xor result;
repeat
if SeedCount and $FFFF = 0 then // reseed after 256KB of output
Seed
else
Inc(SeedCount);
Result := rs1;
rs1 := ((Result and -2) shl 12) xor (((Result shl 13) xor Result) shr 19);
Result := rs2;
rs2 := ((Result and -8) shl 4) xor (((Result shl 2) xor Result) shr 25);
Result := rs3;
rs3 := ((Result and -16) shl 17) xor (((Result shl 3) xor Result) shr 11);
Result := rs1 xor rs2 xor Result;
if ZeroBytesAllowed then exit;
if ((Result and $ff)<>0)
and ((Result and $ff00)<>0)
and ((Result and $ff0000)<>0)
and ((Result and $ff000000)<>0) then
exit;
until false;
end;
function CryptoGetRandomBytes(Buffer: PByte; const Count: Integer): Boolean;
function CryptoGetRandomBytes(Buffer: PByte; const Count: Integer;
ZeroBytesAllowed: boolean): Boolean;
var
I, Remainder, Rounds: Integer;
Lecuyer: TLecuyer;
R: UInt32;
begin
Result := True;
Lecuyer.ZeroBytesAllowed:=ZeroBytesAllowed;
Lecuyer.Seed;
Rounds := Count div SizeOf(UInt32);
for I := 0 to Rounds-1 do
@ -418,7 +429,6 @@ begin
P2:=Pos(aEnd,ASource,P1);
if P2<=0 then exit;
Result:=Copy(aSource,P1,P2-P1);
end;
function IntGetRandomNumber(aBytes : PByte; aCount: Integer): Boolean;

View File

@ -6,6 +6,8 @@ unit fprsa;
interface
{off $DEFINE CRYPTO_DEBUG}
uses
sysutils, Classes, fpTLSBigInt, fphashutils, fpasn;
@ -317,6 +319,9 @@ var
Decrypted: PBigInt;
Encrypted: PBigInt;
Block: array[0..RSA_MODULUS_BYTES_MAX-1] of Byte;
{$IFDEF CRYPTO_DEBUG}
i: integer;
{$ENDIF}
begin
Result := -1;
if Input = nil then
@ -352,8 +357,13 @@ begin
Imported[1]:=2;
// Pad with random non-zero bytes
if not CryptoGetRandomBytes(@Imported[2], Padding) then
if not CryptoGetRandomBytes(@Imported[2], Padding, false) then
Exit;
{$IFDEF CRYPTO_DEBUG}
for i:=0 to Padding-1 do
if Imported[2+i]=0 then
raise Exception.Create('20220429000653');
{$ENDIF}
end;
// Trailing zero after padding bytes
@ -363,7 +373,7 @@ begin
System.Move(Input^,Imported[3 + Padding],Len);
{$IFDEF CRYPTO_DEBUG}
writeln('RSAEncryptSign - Imported Size = ' + IntToStr(Size) + ' Imported = ',Imported,Size);
writeln('RSAEncryptSign - Imported Size = ' + IntToStr(Size) + ' Len = ',Len);
{$ENDIF}
// Encrypt the Block
@ -381,7 +391,7 @@ begin
BIExport(RSA.Context,Encrypted,Output,Size); // this releases Encrypted
{$IFDEF CRYPTO_DEBUG}
writeln('RSAEncryptSign - Output Size = ' + IntToStr(Size) + ' Output = ',Output,Size);
writeln('RSAEncryptSign - Output Size = ' + IntToStr(Size) + ' Len = ',Len);
{$ENDIF}
// Return Result
@ -425,23 +435,38 @@ begin
// Decrypt with Private Key
Decrypted := BICRT(RSA.Context,Encrypted,RSA.DP,RSA.DQ,RSA.P,RSA.Q,RSA.QInv);
end;
Exported := @Block;
Exported := @Block[0];
if Size > RSA_MODULUS_BYTES_MAX then
begin
Exported := GetMem(Size);
if Exported = nil then
begin
{$IFDEF CRYPTO_DEBUG}
writeln('RSADecryptVerify GetMem failed');
{$ENDIF}
Exit;
end;
end;
try
BIExport(RSA.Context, Decrypted, Exported, Size);
if Exported[Count] <> 0 then
begin
{$IFDEF CRYPTO_DEBUG}
writeln('RSADecryptVerify leading zero missing');
{$ENDIF}
Exit; // Check Leading Zero
end;
Inc(Count);
if Verify then
begin
// Check Block Type 1
if Exported[Count] <> 1 then
begin
{$IFDEF CRYPTO_DEBUG}
writeln('RSADecryptVerify Verify Blockt Type<>1');
{$ENDIF}
Exit;
end;
Inc(Count);
while (Exported[Count] = $FF) and (Count < Size) do
begin
@ -453,7 +478,12 @@ begin
begin
// Check Block Type 2
if Exported[Count] <> 2 then
begin
{$IFDEF CRYPTO_DEBUG}
writeln('RSADecryptVerify Decrypt Blockt Type<>2');
{$ENDIF}
Exit;
end;
Inc(Count);
while (Exported[Count] <> 0) and (Count < Size) do
begin
@ -464,13 +494,26 @@ begin
end;
// Check trailing zero byte and padding size
if (Count = Size) or (Padding < 8) then
begin
{$IFDEF CRYPTO_DEBUG}
writeln('RSADecryptVerify invalid padding');
{$ENDIF}
Exit;
end;
if Exported[Count] <> 0 then
begin
{$IFDEF CRYPTO_DEBUG}
writeln('RSADecryptVerify after padding zero missing');
{$ENDIF}
Exit;
end;
Inc(Count);
Result := Size-Count;
if Len < Result then
begin
{$IFDEF CRYPTO_DEBUG}
writeln('RSADecryptVerify Output too small');
{$ENDIF}
Result := -1;
Exit;
end;
@ -526,7 +569,7 @@ begin
Exit;
if not ASNFetchOID(DataP, DataEnd, OID) then // OID: Algorithm
Exit;
if not ASNFetch(DataP, DataEnd, ASNType, ASNSize) then // ASN1_NULL OctetString: Digest
if not ASNFetch(DataP, DataEnd, ASNType, ASNSize) then // ASN1_NULL
Exit;
if ASNType = ASN1_NULL then
begin