EldoS | Feel safer!

Software components for data protection, secure storage and transfer

String sign

Also by EldoS: CallbackFilter
A component to monitor and control disk activity, track file and directory operations (create, read, write, rename etc.), alter file data, encrypt files, create virtual files.
#13836
Posted: 07/07/2010 06:17:53
by Guilherme Soares (Standard support level)
Joined: 01/09/2008
Posts: 6

I create a self signed certificate, when i sign an string with openssl for windows with the command

echo "-->Message to sign<--" | openssl dgst -sha1 -sign privatekey.pem | openssl enc -base64


i get a result diferent from the one i get using pkibackbox


var
Crypto : TElPublicKeyCrypto;
KeyMaterial : TElPublicKeyMaterial;
Cert : TElX509Certificate;
StringStream, StringStreamSignature : TStringStream;


begin
StringStream := TStringStream.create('"-->Message to sign<--"');
StringStreamSignature := TStringStream.create('');

Cert.LoadFromStreamPEM(StreamKey, '');

KeyMaterial := TElRSAKeyMaterial.Create;
KeyMaterial.Assign(Cert.KeyMaterial)

Crypto := TElRSAPublicKeyCrypto.Create();
Crypto.OutputEncoding := pkeBase64;
Crypto.SignDetached(StringStream, StringStreamSignature);

----------------

The StringStreamSignature.DataString value is diferent from the result of openssl command

What's wrong?
#13838
Posted: 07/07/2010 06:26:31
by Ken Ivanov (EldoS Corp.)

Thank you for contacting us.

Some parameter (e.g UseAlgorithmPrefix) is likely to be set to a wrong value. Could you please post the following files here or to the Helpdesk:
1) signature created with OpenSSL,
2) signature created with SBB,
3) the certificate?
#13842
Posted: 07/07/2010 06:42:29
by Eugene Mayevski (EldoS Corp.)

Also be sure to set the license key. Low-level crypto classes don't check the license key presence, yet they produce the wrong result when no key is set.


Sincerely yours
Eugene Mayevski
#13849
Posted: 07/07/2010 09:37:11
by Guilherme Soares (Standard support level)
Joined: 01/09/2008
Posts: 6

The code i use to create the certificate and private key is the following

Code
procedure CreateCACertificate;
Var
    FilePath : String;
    CertNew : TElX509Certificate;
    StringStream : TStringStream;
    FileStream : TFileStream;
    j : Integer;

    Procedure AddToRDN(OID:TBufferTypeConst;Value:String; RejectEmpty : boolean = true);
    Var
        i : Integer;
    begin
        if RejectEmpty and (Value='') then
            exit;
        i := CertNew.SubjectRDN.Count;
        CertNew.SubjectRDN.Count := i+1;
        CertNew.SubjectRDN.OIDs[i] := OID;
        CertNew.SubjectRDN.Values[i] := value;
        CertNew.SubjectRDN.Tags[i] := SB_ASN1_PRINTABLESTRING;
    end;


begin
    FilePath := ExtractFilePath( Application.ExeName );

    CertNew := TElX509Certificate.Create( Application );

    CertNew.SerialNumber := '1';//'UserInfo.CertSerial';

    AddToRDN( SB_CERT_OID_COUNTRY , 'UserInfo.Country' );
    AddToRDN( SB_CERT_OID_COMMON_NAME , 'UserInfo.CommonName' );
    AddToRDN( SB_CERT_OID_LOCALITY , 'UserInfo.Locality' );
    AddToRDN( SB_CERT_OID_STATE_OR_PROVINCE , 'UserInfo.State' );
    AddToRDN( SB_CERT_OID_ORGANIZATION , 'UserInfo.Organization' );
    AddToRDN( SB_CERT_OID_ORGANIZATION_UNIT , 'UserInfo.OrgUnit' );
    AddToRDN( SB_CERT_OID_EMAIL , 'UserInfo.Email' );

    CertNew.ValidFrom := DateOf( IncDay( Now() , -1) ) + EncodeTime(0,0,0,0);

    CertNew.ValidTo := IncDay( IncYear( CertNew.ValidFrom , 3 ) , -1 );



    CertNew.Extensions.ClearExtensions;

    CertNew.Extensions.BasicConstraints.PathLenConstraint := 0;
    CertNew.Extensions.BasicConstraints.Critical := true;
    CertNew.Extensions.BasicConstraints.CA := true;
    CertNew.CAAvailable := false;

    CertNew.IssuerRDN.Count := CertNew.SubjectRDN.Count;
    for j:=0 to CertNew.SubjectRDN.Count-1 do
    begin
        CertNew.IssuerRDN.Tags[j] := SB_ASN1_PRINTABLESTRING;
        CertNew.IssuerRDN.OIDs[j] := CertNew.SubjectRDN.OIDs[j];
        CertNew.IssuerRDN.Values[j] := CertNew.SubjectRDN.Values[j];
    end;


    CertNew.Extensions.Included := [ ceKeyUsage , ceBasicConstraints, ceAuthorityKeyIdentifier, ceSubjectKeyIdentifier ];

    CertNew.Extensions.BasicConstraints.PathLenConstraint := 3;

    CertNew.Extensions.KeyUsage.Critical := True;
    CertNew.Extensions.KeyUsage.KeyCertSign := true;
    CertNew.Extensions.KeyUsage.CRLSign := true;

    CertNew.Extensions.KeyUsage.KeyAgreement := true;
    CertNew.Extensions.KeyUsage.EncipherOnly := true;
    CertNew.Extensions.KeyUsage.DecipherOnly := true;
    CertNew.Extensions.KeyUsage.DigitalSignature := true;
    CertNew.Extensions.KeyUsage.NonRepudiation := true;
    CertNew.Extensions.KeyUsage.DataEncipherment := true;


    CertNew.CAGenerate( SB_CERT_ALGORITHM_SHA1_RSA_ENCRYPTION , KeySize_CA div 32 );

    StringStream := TStringStream.Create( '' );
    CertNew.SaveToStreamPEM( StringStream , '' );
//    MessageDlg(StringStream.DataString, mtWarning, [mbOK], 0);
//    MessageDlg( IntToStr( CertNew.KeyMaterial.Bits ) , mtWarning, [mbOK], 0);

    // PEM
    FileStream := TFileStream.Create( FilePath+'Cert.pem' , fmCreate );
    CertNew.SaveToStreamPEM( FileStream , '' );
    FileStream.Destroy;

    // DER ???
    FileStream := TFileStream.Create( FilePath+'Cert.der' , fmCreate );
    CertNew.SaveToStream( FileStream );
    FileStream.Destroy;




    if CertNew.PrivateKeyExists and CertNew.PrivateKeyExtractable then
    begin
        FileStream := TFileStream.Create( FilePath+'PrivateKey.pem' , fmCreate );
        CertNew.SaveKeyToStreamPEM( FileStream ,  '' );
        FileStream.Destroy;

        FileStream := TFileStream.Create( FilePath+'PrivateKey.Der' , fmCreate );
        CertNew.SaveKeyToStream( FileStream );
        FileStream.Destroy;

    end;

    StringStream.Destroy;

    CertNew.Destroy;

end;


procedure CreateSignatureString;
var
    CertNew : TElX509Certificate;
    Crypto : TElPublicKeyCrypto;
    StringStream : TStringStream;
    SignStringStream : TStringStream;
    FileStream : TFileStream;
    FilePath : String;
    sz : integer;
begin
    FilePath := ExtractFilePath( Application.ExeName );

    StringStream := TStringStream.Create( '' );

    CertNew := TElX509Certificate.Create( Application );

    FileStream := TFileStream.Create( FilePath + 'Cert.pem' , fmOpenRead );
    CertNew.LoadFromStreamPEM( FileStream , '' );
    FileStream.Destroy;


    if not CertNew.PrivateKeyExists then
    begin
        FileStream := TFileStream.Create( FilePath + 'PrivateKey.pem' , fmOpenRead );
        CertNew.LoadKeyFromStreamPEM( FileStream , '' );
        FileStream.Destroy;
    end;

    if not CertNew.PrivateKeyExists then
    begin
        MessageDlg('Boing', mtWarning, [mbOK], 0);
        application.Terminate;
    end;


    Crypto := TElRSAPublicKeyCrypto.Create();
    try
        Crypto.KeyMaterial := CertNew.KeyMaterial;
        Crypto.InputEncoding := pkeBinary;
        Crypto.InputIsHash := false;
        Crypto.HashAlgorithm := SB_ALGORITHM_DGST_SHA1;

        Crypto.OutputEncoding := pkeBase64;

        StringStream := TStringStream.Create( '"Message to sign"' );
        SignStringStream := TStringStream.Create( '' );

        Crypto.SignDetached( StringStream , SignStringStream );

        MessageDlg( SignStringStream.DataString , mtWarning, [mbOK], 0);
    finally
        FreeAndNil(Crypto);
    end;


end;


the result i get from the CreateSignatureString procedure is diferent from the one i get from
echo "Message to sign" | openssl dgst -sha1 -sign PrivateKey.pem | openssl enc -base64
#13850
Posted: 07/07/2010 09:53:52
by Ken Ivanov (EldoS Corp.)

Thank you, but could you please just post the files? This will help to reproduce the issue and find the reason for it much faster.
#13851
Posted: 07/07/2010 10:00:14
by Guilherme Soares (Standard support level)
Joined: 01/09/2008
Posts: 6

Ok

The openssl result is

C:\Program Files\GnuWin32\bin>echo "Message to sign" | openssl dgst -sha1 -sign
privatekey.pem | openssl enc -base64


TorDo0K7PQUKrhZYXxbm65NPqGjrGweia9Yb4Fxcw0TLzMNNllZTqUvDISGpfYp+
Yz/OvZcf+znYO+PtOhICmQ==


[ Download ]
#13854
Posted: 07/07/2010 10:53:48
by Ken Ivanov (EldoS Corp.)

Thank you.

You are passing wrong data to the signing process. The "echo "Message to sign"" command returns the following sequence of bytes (that is further passed to OpenSSL message digest calculator):

"Message to sign"<SPACE><CR><LF>

You can check this by redirecting the output to the file, i.e.

C:\> echo "Message to sign" > Source

However, only the Message to sign string (no quotes, space and CRLF characters) is passed to SBB. That's why you are getting inconsistent results.
#13855
Posted: 07/07/2010 11:16:26
by Guilherme Soares (Standard support level)
Joined: 01/09/2008
Posts: 6

Hi again, thank you for your fast answerd


But if i add to the string i want to sign the <space><cr><lf> then result is still diferent.

StringStream := TStringStream.Create( '"Message to sign"'+chr(32)+chr(13)+chr(10) ); // Notice that i add quotes to the string
#13856
Posted: 07/07/2010 11:32:30
by Ken Ivanov (EldoS Corp.)

If you are using Unicode-capable Delphi (D2009/2010), then TStringStream is the problem. Please use TMemoryStream to keep the string:
Code
var
  S : AnsiString;
  MemStream : TMemoryStream;
...
S := '"Message to sign"'#32#13#10;
MemStream := TMemoryStream.Create();
MemStream.Write(S[1], Length(S));
MemStream.Position := 0;
Crypto.SignDetached(...);
#13857
Posted: 07/07/2010 12:15:22
by Guilherme Soares (Standard support level)
Joined: 01/09/2008
Posts: 6

Hi, i am getting crazy :D

So i tried another way,

I create an file ( filetosign )with 15 bytes ( Message to sign )


type \filetosign | openssl dgst -sha1 -sign privatekey.pem | openssl enc -base64


i also tried on a linux machine

cat \filetosign | openssl dgst -sha1 -sign privatekey.pem | openssl enc -base64


the results are the same

changing the code to

FileStream := TFileStream.Create( '\filetosign' , fmOpenRead );
Crypto.SignDetached( FileStream , SignStringStream );


produces an result diferent from the one i get on OpenSSL/Win or OpenSSL/Linux
Also by EldoS: MsgConnect
Cross-platform protocol-independent communication framework for building peer-to-peer and client-server applications and middleware components.

Reply

Statistics

Topic viewed 4504 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!