How to sign and verify an ECDSA with SHA256 signature in C#
Mr Polk is correct, you need to use verifier.blockUpdate
with the data, and then use the signature bytes in VerifySignature
.
Signatures cannot be verified on their own. The algorithm requires the data as input to calculate the hash value before entering the validation state. Of course having the signature verified without the data only provides limited value: you can just prove that the private key was used.
With ECDSA there is also no real option to verify any part of the signature without the hash
RSA / PKCS#1 in theory would allow you to verify that the contents of the signature are at least created by the private key, even though the contents are unknown. As you can retrieve the full hash value, it is possible to guess the data input without having to go through the signature verification phase for each possible input value. Most API's are of course not geared towards such use of signatures as this is specific to certain schemes.
Related videos on Youtube
qgoehrig
Updated on June 04, 2022Comments
-
qgoehrig almost 2 years
I have a file containing an EC private key:
-----BEGIN EC PRIVATE KEY----- <data> -----END EC PRIVATE KEY-----
I have a certificate with a public key that corresponds to the private key:
In pem format:
-----BEGIN CERTIFICATE----- <data> -----END CERTIFICATE-----
In txt format:
Certificate: Data: Version: 3 (0x2) Serial Number: 80:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:15 Signature Algorithm: ecdsa-with-SHA256 Issuer: CN = MyIssuer Validity Not Before: Jan 27 19:33:43 2020 GMT Not After : Jun 10 19:33:43 2021 GMT Subject: CN = MyIssuer MyCert Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (256 bit) pub: 04:6a:9c:40:7b:71:06:3a:7f:3a:1e:4c:5c:60:9e: d0:c4:a0:c0:c7:39:ec:6d:f1:5b:27:5a:5f:3b:f8: 77:29:7e:38:8e:e6:77:cf:d2:9c:77:c2:43:f4:92: 73:a8:10:d2:e9:f2:bb:d7:4d:97:76:07:d0:1f:16: 7b:01:d3:35:26 ASN1 OID: prime256v1 NIST CURVE: P-256 X509v3 extensions: X509v3 Basic Constraints: critical CA:FALSE X509v3 Authority Key Identifier: keyid:E0:1C:E6:36:88:8B:3D:77:A6:9D:80:8B:7B:9B:1D:1E:FF:24:74:B3 X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication X509v3 Subject Key Identifier: 49:57:2F:01:37:1B:E2:B6:9C:1A:C7:A9:03:9A:D1:61:7E:9B:4A:84 X509v3 Key Usage: critical Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment Signature Algorithm: ecdsa-with-SHA256 30:44:02:20:2c:1a:5c:ee:4a:58:59:f1:5a:4a:93:ed:e0:24: 70:9d:15:11:5e:11:df:30:5a:0f:54:a0:9f:95:c4:eb:f9:6d: 02:20:17:fe:e4:8c:ef:ef:34:56:fb:5d:79:40:f8:fc:f4:2f: 97:90:4b:ac:cb:b6:64:c0:58:3e:2d:fe:7b:4f:ea:19 -----BEGIN CERTIFICATE----- MIIBrTCCAVSgAwIBAgIVAIAAAAAAAAAAAAAAAAAAAAAAAAAVMAoGCCqGSM49BAMC MBIxEDAOBgNVBAMMB0lzc3VlckMwHhcNMjAwMTI3MTkzMzQzWhcNMjEwNjEwMTkz MzQzWjAaMRgwFgYDVQQDDA9Jc3N1ZXJDIERldmljZTMwWTATBgcqhkjOPQIBBggq hkjOPQMBBwNCAARqnEB7cQY6fzoeTFxgntDEoMDHOext8VsnWl87+HcpfjiO5nfP 0px3wkP0knOoENLp8rvXTZd2B9AfFnsB0zUmo38wfTAMBgNVHRMBAf8EAjAAMB8G A1UdIwQYMBaAFOAc5jaIiz13pp2Ai3ubHR7/JHSzMB0GA1UdJQQWMBQGCCsGAQUF BwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUSVcvATcb4racGsepA5rRYX6bSoQwDgYD VR0PAQH/BAQDAgTwMAoGCCqGSM49BAMCA0cAMEQCICwaXO5KWFnxWkqT7eAkcJ0V EV4R3zBaD1Sgn5XE6/ltAiAX/uSM7+80VvtdeUD4/PQvl5BLrMu2ZMBYPi3+e0/q GQ== -----END CERTIFICATE-----
I am trying to accomplish two things:
- Sign an array of bytes using the private key using the ecdsa-with-SHA256 signing algorithm
- Verify the signature is correct using the public key within the certificate
I have tried using the Bouncy Castle library. Here is what I have so far. My assertion is failing.
[TestMethod] public void TestSignAndVerify() { var data = new byte[] {6, 5, 4, 3, 2}; var keyPair = GetKeyPair(); var signature = SignData(data, keyPair.Private); var valid = VerifySignature(signature, keyPair.Public); Assert.IsTrue(valid); } // get key pair from two local files private AsymmetricCipherKeyPair GetKeyPair() { AsymmetricKeyParameter privateKey, publicKey; var privateKeyString = File.ReadAllText("C:\\privatekey.pem"); using (var textReader = new StringReader(privateKeyString)) { // Only a private key var pseudoKeyPair = (AsymmetricCipherKeyPair)new PemReader(textReader).ReadObject(); privateKey = pseudoKeyPair.Private; } var certificateString = File.ReadAllText("C:\\publicCert.pem"); using (var textReader = new StringReader(certificateString)) { // Only a private key Org.BouncyCastle.X509.X509Certificate bcCertificate = (X509Certificate)new PemReader(textReader).ReadObject(); publicKey = bcCertificate.GetPublicKey(); } return new AsymmetricCipherKeyPair(publicKey, privateKey); } public byte[] SignData(byte[] data, AsymmetricKeyParameter privateKey) { var signer = SignerUtilities.GetSigner("SHA-256withECDSA"); signer.Init(true, privateKey); signer.BlockUpdate(data, 0, data.Length); return signer.GenerateSignature(); } public bool VerifySignature(byte[] signature, AsymmetricKeyParameter publicKey) { var verifier = SignerUtilities.GetSigner("SHA-256withECDSA"); verifier.Init(false, publicKey); verifier.BlockUpdate(signature, 0, signature.Length); return verifier.VerifySignature(signature); }
-
President James K. Polk about 4 yearsumm... you didn't actually use the data in your verification code.
-
qgoehrig almost 2 yearsYes this was the issue! :)