Hi,
I upgraded to latest version, RSAOBj.pas Version 1.4.8 last modified: 16 November 2025.
I still get "Invalid Operation : -316" in Verify method.
Here is a very simple code to reproduce:
in uses, add
CryptoConst, MiscObj, RSAObj, RSACore;
Then drop a button and assign this code:
procedure TForm1.Button6Click(Sender: TObject);
var
rsa: TRSAEncSign;
RSASig: String;
begin
rsa = TRSAEncSign.Create(self);
rsa.KeyLength:= kl2048;
rsa.InputFormat:= raw; // default
rsa.OutputFormat:= base64;
rsa.GenerateKeys;
rsa.Unicode := yesUni;
rsa.hashFunction := sha256;
rsa.signType := pss;
edit1.Text := rsa.Sign('test');
if RSA.Verify('test', edit1.text) <> 0 then Caption := 'INVALID SIGNATURE';
rsa.Free;
end;
Clicking the button will cause error -316...
Using latest Delphi 13 with all updates, platform: Windows 64-bit.
On Windows 11.
What could be wrong?
Thank you!
Bernard
(Bernard)
December 1, 2025, 6:51am
2
Hi, you need to convert the signature to 'raw' before verifying it, as you selected 'base64' for the output with 'raw' as input'.
Selecting a format doesn't convert the value, it just tells the algorithm that it needs to convert data.
Add a TConvert:
var
conv: TConvert;
s: string;
conv := TConvert.Create(base64);
...
s := conv.FormatToChar(edit1.text);
if RSA.Verify('test', s) <> 0 then Caption := 'INVALID SIGNATURE';
You can also check the VCL demo from line 2040 to 2120.
Thank you for your answer. It makes sense, though
, if I change rsa.InputFormat:= base64, would it work without conv: TConvert ?
And suppose I want to set the keys without GenerateKeys and these keys are in hex.
Assigning them like this code doesn't work;
RSA.Modulus := 'B4C8691DB3F40D30CB5CB3D398A2DXXXXX';
RSA.PublicExponent := '00000000000000000000000000XXXX';
RSA.PrivateExponent := 'XXXXXX';
RSA.inputFormat := hexa;
What would be the proper way to do it?
Bernard
(Bernard)
December 1, 2025, 5:23pm
4
if I change rsa.InputFormat:= base64, would it work without conv: TConvert
If the input string is in base64, it will be converted to 'raw' within the RSA class.
if InputFormat <> raw then // RSAObj, line 559
m := conv.FormatToChar(m);
Keys are currently accepted in 'raw' format. However, you can do this:
var
conv: TConvert;
begin
conv := TConvert.Create(hexa);
RSA.Modulus := conv.ToCharString('B4C8691DB3F40D30CB5CB3D398A2DXXXXX');
RSA.PublicExponent := conv.FormatToChar('00000000000000000000000000010001');
RSA.PrivateExponent := conv.FormatToChar('XXXXXX');
...
Note that because conv.AType := 'hexa', FormatToChar and ToCharString are identical here.
1 Like
Thanks, but with
RSA.Modulus := conv.ToCharString('B4C8691DB3F40D30CB5CB3D398A2DXXXXX');
I now get this:
Modulus length incorrect, must be 512.
Bernard
(Bernard)
December 2, 2025, 5:18am
6
Logical. Try this.
var
conv: TConvert;
sig: string;
begin
conv := TConvert.Create(hexa);
rsa = TRSAEncSign.Create(self);
rsa.KeyLength:= kl2048;
rsa.InputFormat:= raw; // to load the keys
rsa.OutputFormat:= base64;
rsa.Modulus := conv.FormatToChar('B4C8691DB3F40D30CB5CB3D398A2DXXXXX');
rsa.PublicExponent := conv.FormatToChar('00000000000000000000000000010001');
rsa.PrivateExponent := conv.FormatToChar('XXXXXX');
rsa.InputFormat:= base64; // switch format for input
sig := rsa.sign(aBase64Input); // should generate a base64 signature from a base64 input
...
Hi Bernard,
Thank you but I still get Modulus length incorrect, must be 512.
RSA:= TRSAEncSign.Create(self);
RSA.Unicode := yesUni;
rsa.KeyLength:= kl2048;
conv := TConvert.Create(hexa);
RSA.Modulus := conv.FormatToChar('C4B7179296918317F15BCD8703D172CCA1096177F418B6AED4C8F6B0B09619291A7A63C57EB17E9FEC577F2872F3AE603CA4BE332A63A1D51A17918AD604573BB0DC93A9B7BD1CFB06ACC3DB744EE71E2DC2C8F2440CC6499F92000375D92A1ABAF416A12A4A95B6DDAF331D1BF4986A460954C2D7A28D4E48237CBA373E14F574EDC1BC5E7B363C2623544E1BB14B43B44B23C1B0E22FC96CD486AC6EF8DCBB3795EC8AD0F521C891E516AAD3F771531EE32C3BBFEBD9C56EFC41334CE99B850249A2DBECCA7AE162060ED6F040B41C49A5E207033DFD507ED4A2895C796C0A70B6001867F28CC937A920D13D6050646DA2C47E06F63436F7645E473111B2F5');
RSA.PublicExponent := conv.FormatToChar('0000080000000000040000080000000000000000000000001000004000000229');
RSA.PrivateExponent := conv.FormatToChar('53D76497A22E3104BB6711ED0EF583012DCE7001209384D817BFF55A6E04F1A2A8643C0F71504A7A0C09388BA58464D9DE027CA31252E38B388BBA2DF514C5035CC74EFC69F78E165A180554808612F486B68F5934F1D2B477C7ED216EF297A23AD5EFF3F0B3677645B8616F020542DC7C924CF2C35E86321B3FB02861902EF488840B61FB561D2B230F8D96BFF5F8F210AEC7822EFFD21128555F0235DAB1DD658D59F8834FE4B5DAA18969795D27FF02798DD51F4BFDA46826CE8216C638780366B537EF5564BD95E15C19F65ED8688EF4E49D982B6E5DEE3F57E39167B8A19B7EC6021D528E4BAB93698CF0B640E3D3D19776F65EA8FF3D76DF0BCFFFF131');
RSA.inputFormat := raw;
RSA.outputFormat := base64;
Edit1.Text := RSA.Sign('tQj2+0SClRgYfWjs7yPd0LB2AwI9f5yx6XGGN0mTFEA='); // Signe les données
if RSA.Verify('tQj2+0SClRgYfWjs7yPd0LB2AwI9f5yx6XGGN0mTFEA=', Edit1.Text) <> 0 then Caption := 'INVALID SIGNATURE';
RSA.Free;
Conv.Free;
The values above were generated with your CryptoDemo.
Bernard
(Bernard)
December 3, 2025, 7:34am
8
Hi,
That's normal because
RSA.inputFormat := raw;
needs to be placed BEFORE
RSA.Modulus := conv.FormatToChar('C4B7179296918317F15BCD8703D172CCA1096177F418B6AED4C8F6B0B09619291A7A63C57EB17E9FEC577F2872F3AE603CA4BE332A63A1D51A17918AD604573BB0DC93A9B7BD1CFB06ACC3DB744EE71E2DC2C8F2440CC6499F92000375D92A1ABAF416A12A4A95B6DDAF331D1BF4986A460954C2D7A28D4E48237CBA373E14F574EDC1BC5E7B363C2623544E1BB14B43B44B23C1B0E22FC96CD486AC6EF8DCBB3795EC8AD0F521C891E516AAD3F771531EE32C3BBFEBD9C56EFC41334CE99B850249A2DBECCA7AE162060ED6F040B41C49A5E207033DFD507ED4A2895C796C0A70B6001867F28CC937A920D13D6050646DA2C47E06F63436F7645E473111B2F5');
and then
rsa.InputFormat:= base64; // switch format for input
needs to be placed BEFORE
Edit1.Text := RSA.Sign('tQj2+0SClRgYfWjs7yPd0LB2AwI9f5yx6XGGN0mTFEA='); // Signe les données
Here is a revised version.
RSA:= TRSAEncSign.Create(self);
RSA.Unicode := yesUni;
rsa.KeyLength:= kl2048;
conv := TConvert.Create(hexa);
RSA.inputFormat := raw;
RSA.Modulus := conv.FormatToChar('C4B7179296918317F15BCD8703D172CCA1096177F418B6AED4C8F6B0B09619291A7A63C57EB17E9FEC577F2872F3AE603CA4BE332A63A1D51A17918AD604573BB0DC93A9B7BD1CFB06ACC3DB744EE71E2DC2C8F2440CC6499F92000375D92A1ABAF416A12A4A95B6DDAF331D1BF4986A460954C2D7A28D4E48237CBA373E14F574EDC1BC5E7B363C2623544E1BB14B43B44B23C1B0E22FC96CD486AC6EF8DCBB3795EC8AD0F521C891E516AAD3F771531EE32C3BBFEBD9C56EFC41334CE99B850249A2DBECCA7AE162060ED6F040B41C49A5E207033DFD507ED4A2895C796C0A70B6001867F28CC937A920D13D6050646DA2C47E06F63436F7645E473111B2F5');
RSA.PublicExponent := conv.FormatToChar('0000080000000000040000080000000000000000000000001000004000000229');
RSA.PrivateExponent := conv.FormatToChar('53D76497A22E3104BB6711ED0EF583012DCE7001209384D817BFF55A6E04F1A2A8643C0F71504A7A0C09388BA58464D9DE027CA31252E38B388BBA2DF514C5035CC74EFC69F78E165A180554808612F486B68F5934F1D2B477C7ED216EF297A23AD5EFF3F0B3677645B8616F020542DC7C924CF2C35E86321B3FB02861902EF488840B61FB561D2B230F8D96BFF5F8F210AEC7822EFFD21128555F0235DAB1DD658D59F8834FE4B5DAA18969795D27FF02798DD51F4BFDA46826CE8216C638780366B537EF5564BD95E15C19F65ED8688EF4E49D982B6E5DEE3F57E39167B8A19B7EC6021D528E4BAB93698CF0B640E3D3D19776F65EA8FF3D76DF0BCFFFF131');
RSA.inputFormat := base64;
RSA.outputFormat := base64;
Edit1.Text := RSA.Sign('tQj2+0SClRgYfWjs7yPd0LB2AwI9f5yx6XGGN0mTFEA=');
if RSA.Verify('tQj2+0SClRgYfWjs7yPd0LB2AwI9f5yx6XGGN0mTFEA=', Edit1.Text) <> 0 then Caption := 'INVALID SIGNATURE';
RSA.Free;
Conv.Free;
Hi Bernard,
I thought it would make it finally, but with your last code, the exception is back.
Invalid Operation : -316.
This time, the error occurs on RSA.Verify()
I just copied/pasted the code you wrote. Any further idea?
Thank you!
Bernard
(Bernard)
December 3, 2025, 3:07pm
10
Looks like there is a regression. I am investigating it.
1 Like
Bernard
(Bernard)
December 4, 2025, 1:43pm
11
OK, the good news is that the RSA algorithm is fine.
This code works for me (reverse the byte ordre for each 'key'):
...
conv := TConvert.Create(hexa);
RSA.inputFormat := raw;
RSA.Modulus := conv.reverse(conv.FormatToChar('C4B7179296918317F15BCD8703D172CCA1096177F418B6AED4C8F6B0B09619291A7A63C57EB17E9FEC577F2872F3AE603CA4BE332A63A1D51A17918AD604573BB0DC93A9B7BD1CFB06ACC3DB744EE71E2DC2C8F2440CC6499F92000375D92A1ABAF416A12A4A95B6DDAF331D1BF4986A460954C2D7A28D4E48237CBA373E14F574EDC1BC5E7B363C2623544E1BB14B43B44B23C1B0E22FC96CD486AC6EF8DCBB3795EC8AD0F521C891E516AAD3F771531EE32C3BBFEBD9C56EFC41334CE99B850249A2DBECCA7AE162060ED6F040B41C49A5E207033DFD507ED4A2895C796C0A70B6001867F28CC937A920D13D6050646DA2C47E06F63436F7645E473111B2F5'));
RSA.PublicExponent := conv.reverse(conv.FormatToChar('0000080000000000040000080000000000000000000000001000004000000229'));
RSA.PrivateExponent := conv.reverse(conv.FormatToChar('53D76497A22E3104BB6711ED0EF583012DCE7001209384D817BFF55A6E04F1A2A8643C0F71504A7A0C09388BA58464D9DE027CA31252E38B388BBA2DF514C5035CC74EFC69F78E165A180554808612F486B68F5934F1D2B477C7ED216EF297A23AD5EFF3F0B3677645B8616F020542DC7C924CF2C35E86321B3FB02861902EF488840B61FB561D2B230F8D96BFF5F8F210AEC7822EFFD21128555F0235DAB1DD658D59F8834FE4B5DAA18969795D27FF02798DD51F4BFDA46826CE8216C638780366B537EF5564BD95E15C19F65ED8688EF4E49D982B6E5DEE3F57E39167B8A19B7EC6021D528E4BAB93698CF0B640E3D3D19776F65EA8FF3D76DF0BCFFFF131'));
RSA.inputFormat := base64;
RSA.outputFormat := base64;
...
1 Like
Thanks but still no luck. Same error.
procedure TForm1.Button6Click(Sender: TObject);
var
RSA: TRSAEncSign;
RSASig, S, msgRaw, sigRaw: String;
conv: TConvert;
begin
RSA:= TRSAEncSign.Create(self);
RSA.Unicode := yesUni;
rsa.KeyLength:= kl2048;
conv := TConvert.Create(hexa);
RSA.inputFormat := raw;
RSA.Modulus := conv.reverse(conv.FormatToChar('C4B7179296918317F15BCD8703D172CCA1096177F418B6AED4C8F6B0B09619291A7A63C57EB17E9FEC577F2872F3AE603CA4BE332A63A1D51A17918AD604573BB0DC93A9B7BD1CFB06ACC3DB744EE71E2DC2C8F2440CC6499F92000375D92A1ABAF416A12A4A95B6DDAF331D1BF4986A460954C2D7A28D4E48237CBA373E14F574EDC1BC5E7B363C2623544E1BB14B43B44B23C1B0E22FC96CD486AC6EF8DCBB3795EC8AD0F521C891E516AAD3F771531EE32C3BBFEBD9C56EFC41334CE99B850249A2DBECCA7AE162060ED6F040B41C49A5E207033DFD507ED4A2895C796C0A70B6001867F28CC937A920D13D6050646DA2C47E06F63436F7645E473111B2F5'));
RSA.PublicExponent := conv.reverse(conv.FormatToChar('0000080000000000040000080000000000000000000000001000004000000229'));
RSA.PrivateExponent := conv.reverse(conv.FormatToChar('53D76497A22E3104BB6711ED0EF583012DCE7001209384D817BFF55A6E04F1A2A8643C0F71504A7A0C09388BA58464D9DE027CA31252E38B388BBA2DF514C5035CC74EFC69F78E165A180554808612F486B68F5934F1D2B477C7ED216EF297A23AD5EFF3F0B3677645B8616F020542DC7C924CF2C35E86321B3FB02861902EF488840B61FB561D2B230F8D96BFF5F8F210AEC7822EFFD21128555F0235DAB1DD658D59F8834FE4B5DAA18969795D27FF02798DD51F4BFDA46826CE8216C638780366B537EF5564BD95E15C19F65ED8688EF4E49D982B6E5DEE3F57E39167B8A19B7EC6021D528E4BAB93698CF0B640E3D3D19776F65EA8FF3D76DF0BCFFFF131'));
RSA.inputFormat := base64;
RSA.outputFormat := base64;
Edit1.Text := RSA.Sign('tQj2+0SClRgYfWjs7yPd0LB2AwI9f5yx6XGGN0mTFEA=');
S := edit1.Text;
if RSA.Verify('tQj2+0SClRgYfWjs7yPd0LB2AwI9f5yx6XGGN0mTFEA=',S) <> 0 then Caption := 'INVALID SIGNATURE';
RSA.Free;
Conv.Free;
end;
Executing this code gives -316 error:
I took more time to study your conversion code in RSAObj and the one in the uCryptDemo.
I saw that you use the conversion to extract the bytes from the Modulus and PublicExponent strings.
If we always keep InputFormat as raw, then it finally works!
Here is the code working for me:
procedure TForm1.Button6Click(Sender: TObject);
var
RSA: TRSAEncSign;
S, sigRaw: String;
conv: TConvert;
inputMsg: String;
begin
RSA := TRSAEncSign.Create(self);
conv := TConvert.Create(hexa);
try
RSA.Unicode := yesUni;
RSA.KeyLength := kl2048;
RSA.inputFormat := raw;
RSA.Modulus := conv.reverse(conv.FormatToChar('C4B7179296918317F15BCD8703D172CCA1096177F418B6AED4C8F6B0B09619291A7A63C57EB17E9FEC577F2872F3AE603CA4BE332A63A1D51A17918AD604573BB0DC93A9B7BD1CFB06ACC3DB744EE71E2DC2C8F2440CC6499F92000375D92A1ABAF416A12A4A95B6DDAF331D1BF4986A460954C2D7A28D4E48237CBA373E14F574EDC1BC5E7B363C2623544E1BB14B43B44B23C1B0E22FC96CD486AC6EF8DCBB3795EC8AD0F521C891E516AAD3F771531EE32C3BBFEBD9C56EFC41334CE99B850249A2DBECCA7AE162060ED6F040B41C49A5E207033DFD507ED4A2895C796C0A70B6001867F28CC937A920D13D6050646DA2C47E06F63436F7645E473111B2F5'));
RSA.PublicExponent := conv.reverse(conv.FormatToChar('0000080000000000040000080000000000000000000000001000004000000229'));
RSA.PrivateExponent := conv.reverse(conv.FormatToChar('53D76497A22E3104BB6711ED0EF583012DCE7001209384D817BFF55A6E04F1A2A8643C0F71504A7A0C09388BA58464D9DE027CA31252E38B388BBA2DF514C5035CC74EFC69F78E165A180554808612F486B68F5934F1D2B477C7ED216EF297A23AD5EFF3F0B3677645B8616F020542DC7C924CF2C35E86321B3FB02861902EF488840B61FB561D2B230F8D96BFF5F8F210AEC7822EFFD21128555F0235DAB1DD658D59F8834FE4B5DAA18969795D27FF02798DD51F4BFDA46826CE8216C638780366B537EF5564BD95E15C19F65ED8688EF4E49D982B6E5DEE3F57E39167B8A19B7EC6021D528E4BAB93698CF0B640E3D3D19776F65EA8FF3D76DF0BCFFFF131'));
inputMsg := 'tQj2+0SClRgYfWjs7yPd0LB2AwI9f5yx6XGGN0mTFEA=';
RSA.inputFormat := raw;
RSA.outputFormat := base64;
S := RSA.Sign(inputMsg);
Edit1.Text := S;
conv.AType := base64;
sigRaw := conv.FormatToChar(S);
RSA.inputFormat := raw; // Must be raw here!!
if RSA.Verify(inputMsg, sigRaw) <> 0 then
Caption := 'INVALID SIGNATURE'
else
Caption := 'SIGNATURE VALID';
finally
RSA.Free;
Conv.Free;
end;
end;
system
(system)
Closed
December 5, 2025, 8:50pm
15
This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.