You are not logged in.
The other day I'm sitting on ECDSA cryptography, the hash signature I know how to do, but verification I can't get through. I couldn't find any example either on the forum or in the tests.
By the way of “guessing” I came to the code, which unfortunately returns False on data that was also generated by mORMot cryptography.
Verification receives on input the PEM certificate, signature (in Base64Uri) and input data, it is only supposed to check if the signature is correct.
Here is my function:
function VerifyECDSASignature_(const aInputString: string; const aPEMCertificate: string; const aBase64UriSignature: RawUtf8): boolean;
var
lECDSACrypter: TCryptAsym;
lCertificate: ICryptCert;
lDerEncodedSignatureRBS: RawByteString;
lPublicKeyRaw: RawByteString;
lInputDataRBS: RawByteString;
lInputUTF8: RawUtf8;
lRawSignature64RBS: RawByteString;
begin
Result := False;
lECDSACrypter := Asym('ES256');
if lECDSACrypter = nil then
begin
Exit;
end;
lInputUTF8 := StringToUtf8(aPEMCertificate);
lCertificate := X509Load(lInputUTF8);
if lCertificate = nil then
begin
Exit;
end;
lPublicKeyRaw := lCertificate.GetPublicKey;
if lPublicKeyRaw = '' then
begin
Exit;
end;
lRawSignature64RBS := Base64UriToBin(aBase64UriSignature, nil);
if Length(lRawSignature64RBS) <> SizeOf(TEccSignature) then
begin
Exit;
end;
lDerEncodedSignatureRBS := SetSignatureSecurityRaw(caaES256, lRawSignature64RBS);
if lDerEncodedSignatureRBS = '' then
begin
Exit;
end;
lInputDataRBS := StringToUtf8(aInputString);
Result := lECDSACrypter.Verify(lInputDataRBS, lPublicKeyRaw, lDerEncodedSignatureRBS, 'sha256');
end;
Here certificate:
-----BEGIN CERTIFICATE-----
MIIBlTCCATygAwIBAgIIDEBfo94mHR4wCgYIKoZIzj0EAwIwUTELMAkGA1UEBhMC
UEwxDTALBgNVBAMTBFRlc3QxGTAXBgNVBGETEFZBVFBMLTEyMzQ1Njc4OTAxGDAW
BgNVBAoTD1Rlc3Qgc3AuIHogby5vLjAeFw0yNTA3MzEyMjAwMDBaFw0yNTA5Mjky
MjAwMDBaMFExCzAJBgNVBAYTAlBMMQ0wCwYDVQQDEwRUZXN0MRkwFwYDVQRhExBW
QVRQTC0xMjM0NTY3ODkwMRgwFgYDVQQKEw9UZXN0IHNwLiB6IG8uby4wWTATBgcq
hkjOPQIBBggqhkjOPQMBBwNCAASPPWSOxfYmnUqCvRpzFaDsx3x79LW1/my7EJL+
scIig70NWNpujZ8MNDgrl6PW5R98VZEJMaekvGr1SM8/xQ/PMAoGCCqGSM49BAMC
A0cAMEQCIEHcvNzjR6huqWH6ZghMFWuXEVPtNiq5ZnRFqWnlYSR0AiAvYzI6FqjQ
a2s+JxK5/HbObIBdSDyKdalu3rLXuK1oyw==
-----END CERTIFICATE-----
What did I do wrong?
Offline
Why your function returns False
• Assumes signature is always raw 64 bytes (R||S)
• Your check Length(...) <> SizeOf(TEccSignature) exits early for any DER signature. OpenSSL (and many toolchains) output DER. So you never reach Verify for DER input.
• Public key format mismatch
• lCertificate.GetPublicKey returns the X.509 SubjectPublicKey (SPKI) in ASN.1. TCryptAsym.Verify expects EC public key in one of a few raw/PEM/DER encodings it can parse; SPKI isn’t always accepted directly by its low-level PemDerRawToEcc(). You either need to rewrap the SPKI to the EC compressed key DER, or use ICryptCert.Verify (which does that internally).
• Data bytes/encoding
---
credit: gpt
ps: I tested the code
@ab: do you think the ai-model hallucinated?
Offline
Why your function returns False
• lCertificate.GetPublicKey returns the X.509 SubjectPublicKey (SPKI) in ASN.1. TCryptAsym.Verify expects EC public key in one of a few raw/PEM/DER encodings it can parse; SPKI isn’t always accepted directly by its low-level PemDerRawToEcc(). You either need to rewrap the SPKI to the EC compressed key DER, or use ICryptCert.Verify (which does that internally).
Thanks a lot! That was a spot-on shot. Unfortunately cryptography is not my strongest point, I do it a bit on instinct, and the lack of documentation in this area does not help.
Thanks again, now it's ok.
Offline