Sample code for 30+ languages & platforms
Pascal (Lazarus/Delphi)

Convert Java KeyStore to PKCS12 / PFX

See more Java KeyStore (JKS) Examples

Loads a Java keystore file and saves it as a PKCS12 / PFX. A Java keystore (JKS) can contain two types of entries: (1) trusted root certificates or (2) private keys + cert chains. Usually a JKS will contain all entries of one type or another (and thus a particular JKS serves one purpose or another; meaning that a JKS containing trusted roots is used as a source for verifying pre-trusted roots, and a JKS containing private keys (and cert chains) is used as a secure, encrypted store for private keys).

A PKCS12 / PFX typically contains one or more private keys, along with each private key's certificate chain. Therefore, it typically makes sense to only write the private key entries to a PKCS12 (and the associated certificate chains). If a JKS contains trusted root certificates, it makes more sense to conver it to a PEM file (such as the CA cert bundle in PEM format from mozilla.org).

Chilkat Pascal (Lazarus/Delphi) Downloads

Pascal (Lazarus/Delphi)
program ChilkatDemo;

// Demonstrates using the Chilkat Pascal wrapper via the C bridge DLL.
// Builds as a console application under Lazarus (FPC) or Delphi.

{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}
{$APPTYPE CONSOLE}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  SysUtils,
  CkDllLoader,
  Chilkat.Pfx,
  Chilkat.JavaKeyStore,
  Chilkat.PrivateKey,
  Chilkat.CertChain;

// ---------------------------------------------------------------------------

procedure RunDemo;
var
  success: Boolean;
  jks: TJavaKeyStore;
  jksPassword: string;
  pkcs12: TPfx;
  numPrivateKeys: Integer;
  i: Integer;
  privKey: TPrivateKey;
  certChain: TCertChain;
  pkcs12Password: string;

begin
  success := False;

  //  This requires the Chilkat API to have been previously unlocked.
  //  See Global Unlock Sample for sample code.

  jks := TJavaKeyStore.Create;

  jksPassword := 'myJksPassword';

  //  Load the Java keystore from a file.  The JKS file password is used
  //  to verify the keyed digest that is found at the very end of the keystore.
  //  It verifies that the keystore has not been modified.
  success := jks.LoadFile(jksPassword,'/someDir/keyStore.jks');
  if (success <> True) then
    begin
      WriteLn(jks.LastErrorText);
      Exit;
    end;

  //  To convert, we'll access the private key entries
  //  from the JKS, add each to the PKCS12, and then save the PKCS12.
  pkcs12 := TPfx.Create;

  numPrivateKeys := jks.NumPrivateKeys;

  //  For each private key entry, get the private key and
  //  the associated certificate chain.
  //  Each private key is password protected.  Usually it is the same
  //  password as used for the keyed digest of the entire JKS.  
  //  However, this does not have to be.  The password is passed
  //  here to handle the possibility of each private key requiring
  //  a different password.
  i := 0;
  while i < numPrivateKeys do
    begin
      privKey := jks.GetPrivateKey(jksPassword,i);
      WriteLn(jks.GetPrivateKeyAlias(i));
      certChain := jks.GetCertChain(i);

      //  Add the private key and it's associated certificate chain to the PKCS12.
      success := pkcs12.AddPrivateKey(privKey,certChain);
      if (success <> True) then
        begin
          WriteLn(pkcs12.LastErrorText);
          certChain.Free;
          privKey.Free;
          Exit;
        end;

      certChain.Free;
      privKey.Free;
      i := i + 1;
    end;

  //  Save the PKCS12 / PFX to a file.
  //  The password can be the same as the JKS password, or something new.
  //  (With the PKCS12 format, there is a single password for the entire contents
  //  of the file.  With the JKS format, there is flexibility in allowing each private key
  //  to have it's own password.)
  pkcs12Password := 'myNewPassword';
  success := pkcs12.ToFile(pkcs12Password,'/pkcs12_files/myPfx.p12');
  if (success <> True) then
    begin
      WriteLn(pkcs12.LastErrorText);
    end
  else
    begin
      WriteLn('Successfully saved to PKCS12 format.');
    end;


  jks.Free;
  pkcs12.Free;

end;

// ---------------------------------------------------------------------------

begin

  try
    RunDemo;
  except
    on E: Exception do
      WriteLn('Unhandled exception: ', E.ClassName, ': ', E.Message);
  end;

  WriteLn;
  {$IFDEF MSWINDOWS}
  WriteLn('Press Enter to exit...');
  ReadLn;
  {$ENDIF}
end.