EldoS | Feel safer!

Software components for data protection, secure storage and transfer

extracting private key from X509 certificate pfx file

Also by EldoS: CallbackRegistry
A component to monitor and control Windows registry access and create virtual registry keys.
#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: MsgConnect
Cross-platform protocol-independent communication framework for building peer-to-peer and client-server applications and middleware components.

Reply

Statistics

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