Generate Pades impossible

Hi

Soory to bother because I am sure I made something wrong and probably very stupid, but I cannot detect what !!!

I received this error message :


GExperts Debugger Exception Notification

Project Bagueur.exe raised exception class ERangeError with message 'Erreur de vérification d'étendue at address 00000000029311D5'.

[&Filter ...] [Ignore &All this Session] [Break] [Additional &Info] [Continue]

ThreadId=27160
ProcessId=10
ThreadName=""
ExceptionMessage="Erreur de vérification d'étendue at address 00000000029311D5"
ExceptionName="ERangeError"
ExceptionDisplayName="ERangeError"
ExceptionAddress=7FFCFF38FE7C
FileName=
LineNumber=
ExceptionObject=264BE2EB8D0
Classes=[ERangeError,EIntError,EExternal,Exception,TObject]


I followed indication from your PDF file and demo. Thus my code is simply :

FUNCTION TfDivers.Signer_PDF(Source : String): Boolean;
Var
  Fichier_Cle, Fichier_Cert, Temp : String;
   PAdES: TPAdES;

BEGIN
    PAdES := TPAdES.Create;
    TRY
        TRY
              Fichier_Cle :=  'xxx.key'; // Fichier de la cle;
              Fichier_Cert := 'xxxx.crt'; // Fichier du certificat;
              Ok := FileExists(Fichier_Cle) AND FileExists(Fichier_Cert);

              IF Ok THEN
              BEGIN
                 PAdES.KeyFilePath := Fichier_Cle;
                 PAdES.CertFilePath := Fichier_Cert;
                 PAdES.PKCS11Param.isToken := false;

                 Temp :=    'xxx\Fichier de test pour signature.pdf';
                 Source :=    'xxx\Fichier de test pour signature_sign.pdf';


                 PAdES.PathToOriginalFile := ExtractFilePath(Temp);

                 PAdES.GenerateSignature(Temp, Source);
                 Result := True;
              END ELSE
              BEGIN
                  Result := False;
                  RAISE System.SysUtils.Exception.Create(_('Les fichiers key ou crt sont introuvables'));
              END;   //   Fin de IF
           END
           ELSE
           BEGIN
              Result := False;
               RAISE System.SysUtils.Exception.Create(_('Le fichier PDF a eu un problème'));
           END;   //   Fin de IF
        EXCEPT ON E: System.SysUtils.Exception DO
           BEGIN
              Result := False;
                  TMSLogger.ErrorFormat(
                            'Invisible -{%s}- {%s} avec le message: {%s}',
                            ['I10', E.ClassName, E.Message]);
           END;
        END;   //   Fin de EXCEPT
    FINALLY
       PAdES.Free;
    END;   //   Fin de FINALLY
END;    // Fin de FUNCTION

Please note, if I used your demo using the same key, crt and pdf file to generathe the pdf file signed, it works. I dond't understand :frowning:

Thanks in advance
olivier

Hi,
Can you provide details on the certificate type and key size that you are using.
Also, what line is raising the exception?

ERangeError indicates that an index is out of bounds in a table or similar. Do you know which one?

Thanks.
benrard

Hi

Thanks for your quick answer.

The pb occurs at that line :

PAdES.GenerateSignature(Temp, Source);

key and crt files are generated by this procedure :

    X509Cert := TX509Certificate.Create;
    TRY
        X509Cert.RootCAPath := Commun.FichierGestBag + 'RootCA\\'; // Dans le repertoire generale de l'appli pour tous   '..\\..\\RootCA\\';
        X509Cert.Unicode := yesUni;

        IF vDirecteur.text = '' THEN
        BEGIN
...
        END
        ELSE
        BEGIN
            X509Cert.KeyFilePath :=xxx + 'xxx.key'; // Fichier de la cle;
            X509Cert.CrtFilePath := xxx + 'xxx.crt'; // Fichier du certificat;

            X509Cert.signatureAlgorithm := TSignAlgo.sa_sha256rsa;
            X509Cert.hashFunction := TX509HashFunction.sha256;
            X509Cert.BitSizeEncryptionAlgorithm := 2048;
            X509Cert.countryName := vCodePays.text;
            X509Cert.stateName := vPays.text;
            X509Cert.localityName := vVille.text;
            X509Cert.OrganizationName := vStructure.text;
            X509Cert.OrganizationUnitName := vUnite.text;
            X509Cert.commonName := vDirecteur.text;
            X509Cert.AltName1 := vMail.text;
            X509Cert.isCA := False;

            TRY
               X509Cert.GenerateSelfSigned;
            EXCEPT ON E: System.SysUtils.Exception DO
               BEGIN
                    IF Commun.Log THEN
                          TMSLogger.ErrorFormat(
                            'Options : {%s}, {%s} avec le message : {%s}',
                            ['-O56g1c-', E.ClassName, E.Message]);
               END;
            END;   //   Fin de EXCEPT
        END; // Fin de IF
    FINALLY
        Screen.Cursor := crDefault;
        X509Cert.Free;
    END; // Fin de FINALLY

The size of the key file is 2590o and the crt = 1266o

I can send them to you if it's help ?

also note when I used your demo (uCryptoDemo) with the same key, crt, and pdf files, it works

olivier

Could you compile in debug mode and identify the faulty line in PAdES.GenerateSignature?

Yes of course.
Here the informations :

Unit PAdESObj

procedure TPAdES.GenerateSignature(InStream: TStream; OutStream: TStream);
line 158 : s1 := FirstPart(ts);

function TPAdES.FirstPart(ts: TStringList): string;
...
line 745 : FNumberObj := ComputeSize(ts.Strings[1], ts.Strings[7]);

ts.Strings[1] = 'trailer'#$D#$A'<</Size 24/Root 1 0 R/Info 9 0 R/ID[<46BCBBAA531A104F9763C9BF3C787E12><46BCBBAA531A104F9763C9BF3C787E12>] >>'

ts.Strings[7] = ' ' (blank)

unit System.Classes;
...
function TStringList.Get(Index: Integer): string;
begin
  if Cardinal(Index) >= Cardinal(FCount) then
    TStrings_IndexError(Self, Index, FCount - 1);
  Result := FList[Index].FString;  -> **Here line 7661**
end;

What is the size of the faulty string? There is a limit at 1088 characters in the current RSA version for strings.

What do you mean by "faulty string" ?

The one that raises the exception.

As I mentionned yesterday, The same key and crt files works perfectly

and the value of ts.Strings[1] =

'trailer'#$D#$A'<</Size 24/Root 1 0 R/Info 9 0 R/ID[<46BCBBAA531A104F9763C9BF3C787E12>>><46BCBBAA531A104F9763C9BF3C787E12>] >>

and ts.Strings[7] = ' ' (blank)

That is exactly the same string as with my project !!!

I go foward that in the procedure ComputeSize, where the exception occurs (line 717)

function TPAdES.ComputeSize(s: string; n: string): string;
var
  i, j: integer;
begin
  i := Pos('/Size', s);
  j := i + 1;
  while s[j] <> '/' do
    j := j + 1;

  Result := copy(s, i + 6, j - i - 6);
  j := 1;
  while TryStrToInt(Result[j], i) = true do   // Exception HERE
    j := j + 1;
  Result := copy(Result, 0, j - 1);

  if n <> '' then
  begin
    Result := n + Result;
  end;

  if Result[1] = ' ' then
  begin
    Result := copy(Result, 2);
  end;
end;

Result = 24
turn1 with j := 1
TryStrToInt(Result[j], i) = true do ==> Result[j] = '2', i := 2, and true thus j := j+1 (2)

turn 2 with j = 2
TryStrToInt(Result[j], i) = true do ==> Result[j] = '4', i := 4, and true thus j := j+1 (3)

turn 3 with j = 3 (exeption occurs now)
TryStrToInt(Result[j], i) = true do ==> Result[j] = '#0' == > exception

But the same action with your demo at this turn 3
TryStrToInt(Result[j], i) = true do ==> Result[j] = '#0' i:= and False

Then goes to line 719 as planned.

So, I goes forward from the turn 3 when result[j] equal '#0' and with "step by step" (F7), I reached this procedure in unit System

procedure _BoundErr;
{$IFDEF PUREPASCAL}
begin
  ErrorAt(Byte(reRangeError), ReturnAddress);
end;
{$ELSE !PUREPASCAL}

I don't understand

I modify you code in that way

function TPAdES.ComputeSize(s: string; n: string): string;
....
  TRY
  while TryStrToInt(Result[j], i) = true do
    j := j + 1;
  EXCEPT 
  END;  
...

But an exception occur a little bit further at line

while (FNumberObj[i] <> ' ') and (i > 0) do

and i modfied your code like this :

function TPAdES.FirstPart(ts: TStringList): string;
...
  try
  while (FNumberObj[i] <> ' ') and (i > 0) do
  begin
    temp := FNumberObj[i] + temp;
    i := i - 1;
  end;
  except

  end;

...

And it works even if it is a nonsense !!!

why when Result[j] = '#0' or FNumberObj[i] = '#0' cause an exception ??

It looks like '#0' is interpreted as the end of the string and then is an illegal value for an index position, hence the exception.
does it work with your fix?

Yes it works

But it remains a nonsense to me because with you demo I obtained the same value ('#0') [of course] and it works without the necessity to use the "try except end"

a mistery (for me)
olivier

Hi

Do you thing to "correct" you code in a next update ?
Becase I had to reinstall these componants, and the pb reappeared.
Anyway, I modified your code as below and it works again

Regards
Olivier

I am sorry, but no info about this pb and possible correction in future ?