EldoS | Feel safer!

Software components for data protection, secure storage and transfer

extracting private key from X509 certificate pfx file

Also by EldoS: MsgConnect
Cross-platform protocol-independent communication framework for building peer-to-peer and client-server applications and middleware components.
#27066
Posted: 11/01/2013 05:23:17
by Jacob jvandiermen (Standard support level)
Joined: 08/09/2013
Posts: 55

Hello Eldos,

I have a pfx certificate which contains a public&private key.
When I want to extract the private key I can use these two function:

Code
function getPublicKeyBlobAsString(fileNameCertificate,password: string): AnsiString;
var
  elX509Certificate: TElX509Certificate;
  hashFunction: TElHashFunction;
  blobBufferType: RawByteString;
  certificateByteArray: ByteArray;
  blobSize: Integer;
begin
  elX509Certificate:= TElX509Certificate.Create(nil);
  elX509Certificate:= getX509Certificate(fileNameCertificate,password);
  if assigned(elX509Certificate) then
    begin
      blobBufferType:= '';
      try
        hashFunction:= TElHashFunction.Create(SB_ALGORITHM_DGST_SHA1);
        try
          blobSize:= 0;
          elX509Certificate.GetPublicKeyBlob(nil , blobSize);
          SetLength(certificateByteArray, blobSize);
          elX509Certificate.GetPublicKeyBlob(@certificateByteArray[0] , blobSize);
          hashFunction.Update(@certificateByteArray[0] , blobSize);
          blobBufferType:= hashFunction.Finish();
          result:= SBEncoding.Base64EncodeArray(certificateByteArray,False);
        finally
          FreeAndNil(hashFunction);
        end;
      except
        result:= strEmptyString;
      end;
    end
  else
    result:= strEmptyString;
  FreeAndNil(elX509Certificate);
end;

function getPublicKeyInfoAsString(fileNameCertificate,password: string): AnsiString;
var
  elX509Certificate: TElX509Certificate;
begin
  elX509Certificate:= TElX509Certificate.Create(nil);
  elX509Certificate:= getX509Certificate(fileNameCertificate,password);
  if assigned(elX509Certificate) then
    result:= SBEncoding.Base64EncodeArray(elX509Certificate.GetFullPublicKeyInfo,False)
  else
    result:= strEmptyString;

  FreeAndNil(elX509Certificate);
end;


When I extract the public key the result of the two function are indentical for the pfx file.
But when I use the pfx file to generate a xml signature the public key is placed as a text value of the <X509Certificate> element.
When I compare this text value with the result of my functions there are not equal.
How can that be?
Is it possible to extract the text value of the <X509Certificate> element from the pfx file?

Regards

Jacob
#27067
Posted: 11/01/2013 05:29:16
by Vsevolod Ievgiienko (EldoS Corp.)

Thank you for contacting us.

<X509Certificate> element contains Base64 encoded certificate but not only a public key. You should save a certificate to DER format using TElX509Certificate.SaveToBuffer method and then encode it to Base64. This way you should get the same result.
#27078
Posted: 11/01/2013 07:38:37
by Jacob jvandiermen (Standard support level)
Joined: 08/09/2013
Posts: 55

Hello Vsevolod,

I tried to use TElX509Certificate.SaveToBuffer method with several input variabel: TBytes, ByteArray etc. But every time I get the following compiler message [DCC Error] XMLSignature.pas(2796): E2197 Constant object cannot be passed as var parameter!. How and what type of variabel must I use for the method. I set te length of the variabel to the certificatesize property. And then use the variabel along with the certificatesize property as input for the TElX509Certificate.SaveToBuffer method.

Regards,

Jacob
#27079
Posted: 11/01/2013 07:41:53
by Vsevolod Ievgiienko (EldoS Corp.)

Please refer to the documentation: https://www.eldos.com/documentation/sb...uffer.html
#27080
Posted: 11/01/2013 09:18:59
by Jacob jvandiermen (Standard support level)
Joined: 08/09/2013
Posts: 55

Hello Vsevolod ,

I read the documentation.
I tried the following but this gives me the same E2197 Constant object cannot be passed as var parameter compiler error.Tried several other things with the same result.

Code
elX509Certificate: TElX509Certificate;
certificateByteArray: ByteArray;

//load the pfx file into TElX509Certificate object
elX509Certificate:= getX509Certificate('location of the pfx file','keyname');
SetLength(certificateByteArray,elX509Certificate.CertificateSize);

elX509Certificate.SaveToBuffer(@certificateByteArray[0] ,
                               elX509Certificate.CertificateSize);


Don't know how to fill the buffer.
In my function getPublicKeyBlobAsString it work to fill a ByteArray variabel.

Regards,

Jacob
#27081
Posted: 11/01/2013 09:22:32
by Vsevolod Ievgiienko (EldoS Corp.)

Here is the code sample:

Code
var Buf: ByteArray;
  Sz: integer;
begin
  Sz := 0;
  elX509Certificate.SaveToBuffer(nil, Sz);
  SetLength(Buf, Sz);
  elX509Certificate.SaveToBuffer(@Buf[0], Sz);
  SetLength(Buf, Sz);
  // now Buf contains certificate in DER format
end;
#27105
Posted: 11/05/2013 02:55:26
by Jacob jvandiermen (Standard support level)
Joined: 08/09/2013
Posts: 55

Hello Vsevolod ,

Thanks for your help. I managed to extract the public key from the pfx certificate!!


Regards,

Jacob
#27188
Posted: 11/07/2013 04:32:21
by Jacob jvandiermen (Standard support level)
Joined: 08/09/2013
Posts: 55

Hello Vsevolod & supporting team,

I managed to extract the public key in base64 encoding from the pfx file.
How can I extract the private key from the pfx file in base64 encoding?
Further more when I load a pfx file into a TElX509Certificate object with my function loadCertificate by using the password of the private key , do I load the private key & public key from the pfx file or only one of the two.
I assume that when you load a pfx file into a TElX509Certificate object you are loading the private key certificate because the properties X509Certificate.PrivateKeyExtractable and X509Certificate.PrivateKeyExists are true;

Code
function getX509Certificate(filename: string; password: AnsiString): TElX509Certificate;
var
  fileStream: TFileStream;
  bKeyLoaded: Boolean;
  certificateType : TSBCertFileFormat;
  errorMsg : string;
begin
  try
  // load certificate/key
    bKeyLoaded := false;
    errorMsg := 'Can''t load Certificate because ';
    result:= TElX509Certificate.Create(nil);
    fileStream:= TFileStream.Create(filename, fmOpenRead or fmShareDenyWrite);
    try
      try
        certificateType:= getSBCertFileFormatTypeFromFile(filename);
        //certificateType:= result.DetectCertFileFormat(fileStream);
        case certificateType of
          cfDER:
            try
              result.LoadFromStream(fileStream);
              bKeyLoaded := true;
            except
              on E : Exception do
                begin
                  errorMsg := errorMsg + E.Message;
                  bKeyLoaded := false;
                end;
            end;
          cfPFX :
            try
              result.LoadFromStreamPFX(fileStream,password);
              bKeyLoaded := true;
            except
              on E : Exception do
                begin
                  errorMsg := errorMsg + E.Message;
                  bKeyLoaded := false;
                end;
            end;
          cfPEM :
            try
              result.LoadFromStreamPEM(fileStream,password);
              bKeyLoaded := true;
            except
              on E : Exception do
                begin
                  errorMsg := errorMsg + E.Message;
                  bKeyLoaded := false;
                end;
            end;
          cfSPC :
            try
              result.LoadFromStreamSPC(fileStream);
              bKeyLoaded := true;
            except
              on E : Exception do
                begin
                  errorMsg := errorMsg + E.Message;
                  bKeyLoaded := false;
                end;
            end;
        else
          errorMsg := errorMsg + 'invalid certificate or certificate extension is not der, pem, spc or pfx';
        end;
        if not bKeyLoaded then
          raise Exception.Create(errorMsg);
      except
        on E : Exception do
          MessageDlg(errorMsg, mtInformation, [mbOk], 0)
      end;

    finally
      FreeAndNil(fileStream);
    end
  except
    on E : Exception do
      begin
        result:= nil;
        MessageDlg(errorMsg + E.Message, mtInformation, [mbOk], 0);
      end;
  end;
end;


Now I use this function to extract the private key certificate from the pfx file

Code

function getPrivateKeyCertificateAsString(certificateFileName, password: String): AnsiString;
var
  certificateByteArray: ByteArray;
  size: Integer;
  elX509Certificate: TElX509Certificate;
begin
  result:= '';
  try
    elX509Certificate:= getX509Certificate(certificateFileName, password);
    if Assigned(elX509Certificate) then
      begin
        if (elX509Certificate.PrivateKeyExists and elX509Certificate.PrivateKeyExtractable) then
          begin
            size:= 0;
            elX509Certificate.SaveKeyToBuffer(nil, size);
            SetLength(certificateByteArray,size);
            elX509Certificate.SaveKeyToBuffer(@certificateByteArray[0],size);
            SetLength(certificateByteArray,size);
            result:= SBEncoding.Base64EncodeArray(certificateByteArray,True);
          end;
      end;
  finally
    FreeAndNil(elX509Certificate);
  end;

end;


When I use openssl to exract the private key as a pem, crt or key file
and open it in notepad++ the certificate value isn't the same as the output of the function getPrivateKeyCertificateAsString. How can that be?

Regards,

Jacob
#27219
Posted: 11/13/2013 02:56:14
by Jacob jvandiermen (Standard support level)
Joined: 08/09/2013
Posts: 55

Hello Eldos,

Is it possible to extract the private key as a base64 encoded value from a pfx file? Tried it with my function getPrivateKeyCertificateAsString. But the value that I get isn't the same as the value in pem, crt or key file that I got when I extracted the private key with openssl from the pfx file.


Regards,

Jacob
#27220
Posted: 11/13/2013 03:03:55
by Vsevolod Ievgiienko (EldoS Corp.)

Could you post here a command line for OpenSSL that produces output that you need.
Also by EldoS: Callback File System
Create virtual file systems and disks, expose and manage remote data as if they were files on the local disk.

Reply

Statistics

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