Sample code for 30+ languages & platforms
Delphi DLL

Set .pfx/.p12 Safe Bag Attributes

See more PFX/P12 Examples

Demonstrates how to set safebag attributes in a .pfx/.p12. This example creates a .pfx from a .pem containing a private key and certificates, but also sets PFX safebag attributes before writing the .pfx.

Chilkat Delphi DLL Downloads

Delphi DLL
uses
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Pfx, StringBuilder, JsonObject;

...

procedure TForm1.Button1Click(Sender: TObject);
var
success: Boolean;
pfx: HCkPfx;
sbPem: HCkStringBuilder;
password: PWideChar;
forPrivateKey: Boolean;
keyIdx: Integer;
certIdx: Integer;
pfx2: HCkPfx;
json: HCkJsonObject;

begin
success := False;

// We have a PEM containing one private key, and two certificates:
// The private key is an ECDSA private key.
// The private key is associated with the 1st certificate.
// The 2nd certificate is the issuer of the 1st certificate.

// -----BEGIN PRIVATE KEY-----
// ME0CAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEMzAxAgEBBCDgAn4Dal+0iEhIsYBk
// 6SdSR344vyj0suhOIxsjmM19s6AKBggqhkjOPQMBBw==
// -----END PRIVATE KEY-----
// -----BEGIN CERTIFICATE-----
// MIIBXzCCAQSgAwIBAgIUGp2obfF61BG7QTsqpyT+VvxxJC0wCgYIKoZIzj0EAwIw
// DTELMAkGA1UEAwwCQ0EwHhcNMjAwMzI5MTU1MTEwWhcNMzAwMzI3MTU1MTEwWjAN
// MQswCQYDVQQDDAJFRTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABEil+DhBUss8
// kMCjEWvZHA+jdy1mQ76a2HFd+5p+AcFGQxNeG8/HXZax7FFzcrczWrli25R8P8j1
// cqhwPY4HtwujQjBAMB0GA1UdDgQWBBTenwm6x4A4W5BzZ2OckKA2IFtPSTAfBgNV
// HSMEGDAWgBTx1U/gWiRhAASl6FV04DxP3XmcazAKBggqhkjOPQQDAgNJADBGAiEA
// rkqbz5t1M/CjqXSKE5ebBLQ3npF+q7GRC8C2ovDi/xoCIQDGve7OP/ppIDcCNonr
// +WSRf5M/6Wvw1lnEsAXf3nLTeQ==
// -----END CERTIFICATE-----
// -----BEGIN CERTIFICATE-----
// MIIBcDCCARWgAwIBAgIUAnQiKKy/PdLnH0A6vYKBq21w1JAwCgYIKoZIzj0EAwIw
// DTELMAkGA1UEAwwCQ0EwHhcNMjAwMzI5MTU1MTEwWhcNMzAwMzI3MTU1MTEwWjAN
// MQswCQYDVQQDDAJDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPB6yVvqt8cL
// EneRtnjoi87H0ATi+JP1w2qkz4GLOaPtFxAnV0LdQCuN91SGbAlKrSkhFyWWimjh
// Rqe9+b/1WCijUzBRMB0GA1UdDgQWBBTx1U/gWiRhAASl6FV04DxP3XmcazAfBgNV
// HSMEGDAWgBTx1U/gWiRhAASl6FV04DxP3XmcazAPBgNVHRMBAf8EBTADAQH/MAoG
// CCqGSM49BAMCA0kAMEYCIQCcIfssfrOruVYvqhxbLGeyc5ppEX53zUU35wIE2t7C
// fAIhAKhOTEvN+pdEn+cNwW3AEi7D08ZUQx3P80i4EnFPs0OQ
// -----END CERTIFICATE-----

pfx := CkPfx_Create();
sbPem := CkStringBuilder_Create();
success := CkStringBuilder_LoadFile(sbPem,'qa_data/pfx/test_ecdsa.pem','utf-8');
if (success = False) then
  begin
    Memo1.Lines.Add('Failed to load the PEM file.');
    Exit;
  end;

// The PEM in this example is unencrypted.  There is no password.
password := '';
success := CkPfx_LoadPem(pfx,CkStringBuilder__getAsString(sbPem),password);
if (success = False) then
  begin
    Memo1.Lines.Add(CkPfx__lastErrorText(pfx));
    Exit;
  end;

// Let's add some safebag attributes for the private key...
forPrivateKey := True;
keyIdx := 0;
success := CkPfx_SetSafeBagAttr(pfx,forPrivateKey,keyIdx,'localKeyId','16777216','decimal');
if (success = False) then
  begin
    Memo1.Lines.Add(CkPfx__lastErrorText(pfx));
    Exit;
  end;

success := CkPfx_SetSafeBagAttr(pfx,forPrivateKey,keyIdx,'keyContainerName','{B99EB9E7-6AF7-42AF-A43A-D4B2225B7605}','ascii');
if (success = False) then
  begin
    Memo1.Lines.Add(CkPfx__lastErrorText(pfx));
    Exit;
  end;

success := CkPfx_SetSafeBagAttr(pfx,forPrivateKey,keyIdx,'storageProvider','Microsoft Software Key Storage Provider','ascii');
if (success = False) then
  begin
    Memo1.Lines.Add(CkPfx__lastErrorText(pfx));
    Exit;
  end;

// Add the localKeyId safebag attribute to the 1st certificate.
forPrivateKey := False;
certIdx := 0;
success := CkPfx_SetSafeBagAttr(pfx,forPrivateKey,certIdx,'localKeyId','16777216','decimal');
if (success = False) then
  begin
    Memo1.Lines.Add(CkPfx__lastErrorText(pfx));
    Exit;
  end;

// Write the pfx.
success := CkPfx_ToFile(pfx,'secret','qa_output/ee.pfx');
if (success = False) then
  begin
    Memo1.Lines.Add(CkPfx__lastErrorText(pfx));
    Exit;
  end;

// Let's load the .pfx we just wrote to see if the safebag attributes exist.
pfx2 := CkPfx_Create();
success := CkPfx_LoadPfxFile(pfx2,'qa_output/ee.pfx','secret');
if (success = False) then
  begin
    Memo1.Lines.Add(CkPfx__lastErrorText(pfx2));
    Exit;
  end;

// Information about the contents of the PFX was collected in the call to LoadPfxFile.
json := CkJsonObject_Create();
CkPfx_GetLastJsonData(pfx2,json);

CkJsonObject_putEmitCompact(json,False);
Memo1.Lines.Add(CkJsonObject__emit(json));

// Shows what's in the PFX just loaded:

// {
//   "authenticatedSafe": {
//     "contentInfo": [
//       {
//         "type": "Data",
//         "safeBag": [
//           {
//             "type": "pkcs8ShroudedKeyBag",
//             "attrs": {
//               "keyContainerName": "{B99EB9E7-6AF7-42AF-A43A-D4B2225B7605}",
//               "msStorageProvider": "Microsoft Software Key Storage Provider",
//               "localKeyId": "16777216"
//             }
//           }
//         ]
//       },
//       {
//         "type": "EncryptedData",
//         "safeBag": [
//           {
//             "type": "certBag",
//             "attrs": {
//               "localKeyId": "16777216"
//             },
//             "subject": "EE",
//             "serialNumber": "1a9da86df17ad411bb413b2aa724fe56fc71242d"
//           },
//           {
//             "type": "certBag",
//             "subject": "CA",
//             "serialNumber": "02742228acbf3dd2e71f403abd8281ab6d70d490"
//           }
//         ]
//       }
//     ]
//   }
// }

CkPfx_Dispose(pfx);
CkStringBuilder_Dispose(sbPem);
CkPfx_Dispose(pfx2);
CkJsonObject_Dispose(json);

end;