Verify RSA signature with LockBox

883 Views Asked by At

I would like to verify a digital signature with LockBox3 (or LockBox2 if version 3 isn't suitable for whatever reason).

I have a public key file in PEM form (I can't create new keys with LockBox, because I need to use and existing key pair that is used in other places already):

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEDtIRT57TJAfmub2RsIM32jdo
8ijsds/u1fpY6hwtkC01/LFJkNTXqSwvpaO5tp86o0SlzBHdF0WxPtsKqdc8F7kQ
uHm7hUTLX0zPGRdGCsy9q/PIGlVGAFTBSVXl+grmGGZuS1CHI13L/oulBGENQOxO
8r6D1RyPjt6z0BAndQIDAQAB
-----END PUBLIC KEY-----

I don't know which format to provide to LockBox as a public key. I tried converting PEM to XML and used the RSAKeyValue>Modulus part, because it looks close to what is used in the test case, but it didn't work either. (The public keys here are only an example and have been taken from the converter I've used: https://superdry.apphb.com/tools/online-rsa-key-converter)

Unfortunately, whatever I've tried, I didn't manage to use it as the public key in LockBox to verify a signature of a message.

This is what I have so far based on uLockBox_Signatory_TestCases.pas:

function VerifySignatureLockBox(const AMessage, ASignature: String): Boolean;
const
  //MyPublicKey = 'MIGfMA0GC...';
  MyPublicKey =
    'xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6' +
    'WjubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpV' +
    'RgBUwUlV5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U=';
var
  Lib: TCryptographicLibrary;
  Signatory: TSignatory;
  Codec: TCodec;
  MessageStream, SignatureStream: TStringStream;
  KeyStream: TMemoryStream;
begin
  Lib := TCryptographicLibrary.Create(nil);
  Codec := TCodec.Create(nil);
  Signatory := TSignatory.Create(nil);

  MessageStream := TStringStream.Create(AMessage);
  SignatureStream := TStringStream.Create(ASignature);
  KeyStream := TMemoryStream.Create;
  try
    Base64_to_stream(AnsiBytesOf(MyPublicKey), KeyStream);

    MessageStream.Position := 0;
    SignatureStream.Position := 0;
    KeyStream.Position := 0;

    Codec.CryptoLibrary := Lib;
    Codec.StreamCipherId := RSA_ProgId;
    Codec.ChainModeId:= CBC_ProgId;
    Codec.AsymetricKeySizeInBits := 256;

    Signatory.Codec := Codec;
    Signatory.LoadKeysFromStream(KeyStream, [partPublic]); //<-- ERROR

    Result := Signatory.Verify(MessageStream, SignatureStream) = vPass;
  finally
    Codec.Burn;
    Lib.Free;
    Codec.Free;
    Signatory.Free;

    MessageStream.Free;
    SignatureStream.Free;
    KeyStream.Free;
  end;
end;

This fails at LoadKeysFromStream(), more specifically at StoreStream.ReadBuffer( L, SizeOf( L)); in uTPLb_RSA_Engine / LoadHugeCardinal_IfNotAlready() with a EStreamError exception.

What am I doing wrong? Could someone please provide a working example?

1

There are 1 best solutions below

1
On

Look at this method:

LoadKeysFromStream(KeyStream, [partPublic]);

The KeyStream must not contain only binary public key. It tries to load from stream some information about version, header, PartSet and other.