EtheaDev / Delphi-SAML

A SAML implementation for Delphi developers
Apache License 2.0
25 stars 7 forks source link

Allow loading of password protected private keys #4

Closed HealthOneNZ closed 6 months ago

HealthOneNZ commented 6 months ago

The current implementation has a method to load private keys without requiring their password.

  ISignatureContext = interface
// snip
    procedure LoadKey(AStream: TStream; AFormat: TKeyDataFormat; AOwnsStream: Boolean);
// snip

The implementation class makes a call to the underlying xmlsec API, assuming there is no password

procedure TSignatureContext.LoadKey(AStream: TStream; AFormat: TKeyDataFormat;
  AOwnsStream: Boolean);
//snip
    // load private key, assuming that there is not password */
    dsigCtx.signKey := xmlSecCryptoAppKeyLoadMemory(data, dataSize, xmlSecKeyDataFormat(AFormat), nil, nil, nil);
// snip

I am proposing to overload the method to allow for a password to be provided.

HealthOneNZ commented 6 months ago

So the proposed change is to simply add an optional param to the method signature

  ISignatureContext = interface
// snip
    procedure LoadKey(AStream: TStream; AFormat: TKeyDataFormat; AOwnsStream: Boolean; APassword: string = '');

and to the concrete class

  TSignatureContext = class(TInterfacedObject, ISignatureContext)
//snip
    procedure LoadKey(AStream: TStream; AFormat: TKeyDataFormat; AOwnsStream: Boolean; APassword: string = '');
// snip

procedure TSignatureContext.LoadKey(AStream: TStream; AFormat: TKeyDataFormat; AOwnsStream: Boolean; APassword: string);
var
//snip
  Pass: PAnsiChar; // new var to hold password
begin
//snip
    Pass := PAnsiChar(Pointer(AnsiString(APassword)));  // convert password to xmlsec compatible type
    dsigCtx.signKey := xmlSecCryptoAppKeyLoadMemory(data, dataSize, xmlSecKeyDataFormat(AFormat), Pass, nil, nil);
//snip

This handles the case where the private key has not been protected with a password, also the case where there is a password.