I am implementing a 192 bit ECDSA signature in C# using BouncyCastle. It was specified in text by my customer. They sent me a spec in OpenSSL after I started implementing in BouncyCastle. Now I'm having trouble moving keys between OpenSSL and BouncyCastle. I think I must be missing the point of something, and am asking your help to understand how ECDSA 192 works across the two libraries.
The first line of the spec is:
openssl ecparam -name secp192r1 -genkey -noout -out priv.pem
The resulting priv.pem contains a Base64 string that decodes to 97 bytes. When I feed that key to BouncyCastle using a 192 bit curve, I get exceptions.
ECDomainParameters spec = GetEcdsaCurveParamsForInit();
// D is the Private Key
BigInteger d = new BigInteger(tbSigKeyHex.Text, 16);
ECPrivateKeyParameters sKey = new ECPrivateKeyParameters("ECDSA", d, spec);
ECPublicKeyParameters vKey = GL_ECKeyPairGenerator.GetCorrespondingPublicKey(sKey); // EXCEPT on d > 24byte max value
The specific exception is System.InvalidOperationException on this line of EcKeyPairGenerator.cs:
ECPoint q = new FixedPointCombMultiplier().Multiply(ec.G, privKey.D);
If I truncate the Ascii-hex input string to 48 bytes, so privKey.D is never more than the max value of 24 bytes, everything runs ok. But now my code differs from spec.
I also notice that BouncyCastle makes 24 byte keys with 192 bit curves:
AsymmetricCipherKeyPair keyPair = GenerateKeys(192); // bit length selects curve in GL_ECKeyPairGenerator
ECPrivateKeyParameters sKey = (ECPrivateKeyParameters)keyPair.Private;
string szD = sKey.D.ToString(16);
PrintToFeedback(string.Format("Generated Private D Key {0} bytes: {1}", szD.Length/2, szD));
ECPublicKeyParameters vKey = (ECPublicKeyParameters)keyPair.Public;
prints out:
Generated Private D Key 24 bytes: 92e67f4a42c3031349f7e88d082a8e1f122eaee8d8b0823d
When I break and inspect sKey, I don't see anything that looks like a 97 byte number. I see how 24 bytes maps to 192 bits, but not 97. Since my customer says OpenSSL is the spec, I have to assume that's correct. But I'm a little lost. Before they sent me the OpenSSL spec, I had convinced myself that ECDSA192 uses 24 byte private keys (and 48 byte public keys, more or less), but this 97 byte OpenSSL key throws everything into doubt again. My expertise is in realtime and RFID, not so much crypto.
Can someone help me understand how to use the OpenSSL 97 byte key with BouncyCastle? Or should I just rip up BouncyCastle and rewrite with OpenSSL.Net?
I am running in a Cygwin bash window under Win10, openssl version is:
OpenSSL 1.0.2o 27 Mar 2018
Thank you.
The file priv.pem
that results from your openssl ecparam
command contains more than just the bytes that make up the private part of the key. In particular, it also includes the public part of the key pair, and some information about what kind of curve the key is on. You can see this when you do
$ openssl ec -in priv.pem -noout -text
read EC key
Private-Key: (192 bit)
priv:
74:6b:13:17:a5:6e:bb:8e:76:b1:65:a2:c2:59:16:
72:36:56:ee:42:b9:91:26:53
pub:
04:9b:d5:f3:61:6b:06:86:c2:d2:1b:c8:1f:86:ae:
ee:58:8a:ac:b3:04:2b:93:c5:8c:1b:24:6e:90:2d:
9c:aa:69:7e:30:15:86:48:06:97:b6:78:35:a6:48:
46:1a:2c:4e
ASN1 OID: prime192v1
So to use the private part separately, you will have to extract it first.
To get a lower level understanding about what is exactly stored in priv.pem
, you can use the asn1parse
application:
$ openssl asn1parse -in priv.pem -dump
0:d=0 hl=2 l= 95 cons: SEQUENCE
2:d=1 hl=2 l= 1 prim: INTEGER :01
5:d=1 hl=2 l= 24 prim: OCTET STRING
0000 - 74 6b 13 17 a5 6e bb 8e-76 b1 65 a2 c2 59 16 72 tk...n..v.e..Y.r
0010 - 36 56 ee 42 b9 91 26 53- 6V.B..&S
31:d=1 hl=2 l= 10 cons: cont [ 0 ]
33:d=2 hl=2 l= 8 prim: OBJECT :prime192v1
43:d=1 hl=2 l= 52 cons: cont [ 1 ]
45:d=2 hl=2 l= 50 prim: BIT STRING
0000 - 00 04 9b d5 f3 61 6b 06-86 c2 d2 1b c8 1f 86 ae .....ak.........
0010 - ee 58 8a ac b3 04 2b 93-c5 8c 1b 24 6e 90 2d 9c .X....+....$n.-.
0020 - aa 69 7e 30 15 86 48 06-97 b6 78 35 a6 48 46 1a .i~0..H...x5.HF.
0030 - 2c 4e ,N
Or if you are on Windows, try this excellent ASN.1 Editor tool.