EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Signed data saving failed

Also by EldoS: Solid File System
A virtual file system that offers a feature-rich storage for application documents and data with built-in compression and encryption.
#15558
Posted: 01/19/2011 09:47:56
by Ken Ivanov (EldoS Corp.)

As we actually are not sure whether the problem you are encountering is related to some limitations of the token or it's driver, let's start from a small experiment:
1) Remove TfrmSelWinCert form from your project (comment out it's Application.CreateF
orm() statement in the project source code),
2) Instead of using the form, find the signing certificate automatically in the storage at the beginning of the Sign() method and destroy the storage at the end of the Sign() method:
Code
function Sign(): boolean;
var
  Cert : TElX509Certificate;
  Storage : TElWinCertStorage;
begin
  Cert := nil;
  Storage := TElWinCertStorage.Create(nil);
  try
    for I := 0 to Storage.Count - 1 do
      if Storage.Certificate[I].SubjectName.CommonName = 'EldoS Corporation' then
    begin
      Cert := Storage.Certificates[I];
      Break;
    end;
    if Cert = nil then Exit;
  
    < your signing code here>

  finally
    FreeAndNil(Storage);
  end;
end;


3) Run Sign() operation in a long loop and check if it exposes the issues occur.
#15559
Posted: 01/19/2011 11:04:19
by Kiril Drumev (Standard support level)
Joined: 12/28/2010
Posts: 24

Ok I'll try that, meanwhile attached is the bugreport of one of the errors.
I've signed batch of 145 files and got the error three times.
I hope this will help.


[ Download ]
#15560
Posted: 01/19/2011 11:20:29
by Ken Ivanov (EldoS Corp.)

Thank you for the information, it fits more or less into my assumption. So we are looking forward to seeing the results of your testing.
#15565
Posted: 01/20/2011 06:59:39
by Kiril Drumev (Standard support level)
Joined: 12/28/2010
Posts: 24

I did it and I got the attached error.


[ Download ]
#15566
Posted: 01/20/2011 07:02:10
by Kiril Drumev (Standard support level)
Joined: 12/28/2010
Posts: 24

There are two errors, pls. consider 'Bufer too small' one.
#15567
Posted: 01/20/2011 08:30:26
by Ken Ivanov (EldoS Corp.)

Thank you for checking. Could you please run one more test for us? Please run the below code and check if it exposes the same problems (replace certificate identifiers to match your certificate):
Code
procedure SignLoop;
var
  CertStorage : TElWinCertStorage;
  I, J : integer;
  Cert : TElX509Certificate;
  Crypto : TElRSAPublicKeyCrypto;
  InBuf, OutBuf : ByteArray;
  InSize, OutSize : integer;
begin
  for I := 0 to 200 do
  begin
    Cert := nil;
    CertStorage := TElWinCertStorage.Create(nil);
    try
      CertStorage.SystemStores.Add('MY');
      for J := 0 to CertStorage.Count - 1 do
        if CertStorage.Certificates[J].SubjectName.CommonName = 'EldoS Corporation' then // <--- check this
        begin
          Cert := CertStorage.Certificates[J];
          Break;
        end;
      if Cert <> nil then
      begin
        Crypto := TElRSAPublicKeyCrypto.Create();
        try
          Crypto.KeyMaterial := Cert.KeyMaterial;
          Crypto.InputIsHash := true;
          Crypto.UseAlgorithmPrefix := true;
          Crypto.HashAlgorithm := SB_ALGORITHM_DGST_SHA1;
          InSize := 20;
          SetLength(InBuf, InSize);
          SBRndGenerate(@InBuf[0], Length(InBuf));
          OutSize := 0;
          Crypto.SignDetached(@InBuf[0], Length(InBuf), nil, OutSize);
          SetLength(OutBuf, OutSize);
          Crypto.SignDetached(@InBuf[0], Length(InBuf), @OutBuf[0], OutSize);
        finally
          FreeAndNil(Crypto);
        end;
      end;
    finally
      FreeAndNil(CertStorage);
    end;
  end;
end;
#15568
Posted: 01/20/2011 08:40:10
by Kiril Drumev (Standard support level)
Joined: 12/28/2010
Posts: 24

This code runs without errors.
#15569
Posted: 01/20/2011 09:01:36
by Ken Ivanov (EldoS Corp.)

This means that the token works as expected if each signing operation is performed from within a separate session (the code above forces CryptoAPI to release the session by freeing the TElWinCertStorage object and thus disposing of all the acquired key objects).

Your code actually should work as well... Can it be that some TElX509Certificate object remains alive after signing? Token session won't be freed until all the relevant key contexts are disposed of.
#15570
Posted: 01/20/2011 09:23:22
by Kiril Drumev (Standard support level)
Joined: 12/28/2010
Posts: 24

No, it's disposed, we've tried that with the first code you've sent me.
The problem is in the following line:
Signer.Save(SigNode);
In the LoopSign procedure there is no such line and we have no problem.
The fact that LoopSign runs doesn't prove anything, because it's doing something different.
What I've understood is that the certificate storage object has nothing to do with the problem we have.
#15571
Posted: 01/20/2011 09:56:58
by Ken Ivanov (EldoS Corp.)

The code above is just a very simplified clone of what is actually done inside the TElXMLSigner. Okay, could you please try the following code as well (remember to adjust certificate subject and XML file name values):
Code
function SignXML(XMLDocument : TElXMLDOMDocument; Cert : TElX509Certificate): boolean;
var
  Signer: TElXMLSigner;
  X509KeyData: TElXMLKeyInfoX509Data;
  SigNode: TElXMLDOMNode;
  Ref: TElXMLReference;
  Refs: TElXMLReferenceList;
  C14NTransform: TElXMLC14NTransform;
begin
  Result := true;
  X509KeyData := nil;
  Refs := TElXMLReferenceList.Create;
  try
    Ref := TElXMLReference.Create;
    Ref.DigestMethod := xdmSHA1;
    Ref.URINode := XMLDocument.DocumentElement;
    Ref.URI := '';

    Ref.TransformChain.Add(TElXMLEnvelopedSignatureTransform.Create);

    C14NTransform := TElXMLC14NTransform.Create;
    C14NTransform.CanonicalizationMethod := xcmCanonComment;
    Ref.TransformChain.Add(C14NTransform);

    Refs.Add(Ref);

    Signer := TElXMLSigner.Create(nil);
    try
      Signer.SignatureType := xstEnveloped;
      Signer.CanonicalizationMethod := xcmCanon;
      Signer.SignatureMethodType := xmtSig;
      Signer.SignatureMethod := xsmRSA_SHA1;
      Signer.MACMethod := xmmHMAC_SHA1;
      Signer.References := Refs;
      Signer.KeyName := '';
      Signer.IncludeKey := True;
      if Assigned(Cert) and Cert.PrivateKeyExists then
      begin
        X509KeyData := TElXMLKeyInfoX509Data.Create(False);
        X509KeyData.Certificate := Cert;
        X509KeyData.IncludeDataParams:=X509KeyData.IncludeDataParams - [xkidX509IssuerSerial] - [xkidX509SubjectName];
        Signer.KeyData := X509KeyData;
      end;
      Signer.UpdateReferencesDigest;
      Signer.Sign;
      Signer.Signature.SignaturePrefix := 'ds';
      SigNode := XMLDocument.DocumentElement;
      try
        Signer.Save(SigNode);
      except
        on E: Exception do
        begin
          MessageDlg(E.Message, mtError, [mbOk], 0);
          Result:=False;
          Exit;
        end;
      end;
    finally
      FreeAndNil(Signer);
      FreeAndNil(X509KeyData);
    end;
  finally
    FreeAndNil(Refs);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  CertStorage : TElWinCertStorage;
  I, J : integer;
  Cert : TElX509Certificate;
  Doc : TElXMLDOMDocument;
  F : TFileStream;
begin
  for I := 0 to 200 do
  begin
    Cert := nil;
    CertStorage := TElWinCertStorage.Create(nil);
    try
      CertStorage.SystemStores.Add('MY');
      for J := 0 to CertStorage.Count - 1 do
        if CertStorage.Certificates[J].SubjectName.CommonName = 'EldoS Corporation' then
        begin
          Cert := CertStorage.Certificates[J];
          Break;
        end;
      if Cert <> nil then
      begin
        Doc := TElXMLDOMDocument.Create();
        try
          F := TFileStream.Create('settings.xml', fmOpenRead);
          try
            Doc.LoadFromStream(F, false, [], 'utf-8');
          finally
            FreeAndNil(F);
          end;
          SignXML(Doc, Cert);
          F := TFileStream.Create('settings.signed.xml', fmCreate);
          try
            Doc.SaveToStream(F);
          finally
            FreeAndNil(F);
          end;
        finally
          FreeAndNil(Doc);
        end;
      end;
    finally
      FreeAndNil(CertStorage);
    end;
  end;
end;
Also by EldoS: CallbackRegistry
A component to monitor and control Windows registry access and create virtual registry keys.

Reply

Statistics

Topic viewed 11365 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!