-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DH->Curve25519->ServerKeyExchange->Bouncy Castle is not working #251
Comments
This is a point format and/or curve form mismatch. Skip to the last paragraph for the easy solution, or read on if you need to make things work via the provider code above. X25519 uses the Montgomery curve "Curve25519", and specifies the public key format as the (exactly) 32-byte X coordinate (little-endian). On the other hand, when you get an implementation of "Curve25519" (or any curve) from ECNamedCurveTable, it will be for a short-Weierstrass (SW) curve, and the expected public key format is from the SEC standards, so that it includes a format byte at the start, followed by the 32-byte X coordinate, and possibly the Y coordinate, both in big-endian order. This can be made to work by converting the input as follows:
Sample code:
If you want to also send a public key in X25519 format, you'll need to do a similar conversion (Xm = Xw - D mod P) from the point encoding you get from the Weierstrass curve. However I should point out that we have just committed a proper implementation of X25519 (1f559bb). We have more work to do on trying to present that in the provider and through the usual interfaces, but if you just want to do ECDH with X25519, you could use that class directly (copy it for now, or wait for the next release - or beta). |
Thanks for your answer. It was very accurate and also the explanation was good. But, I have another question: Now i need to generate X25519 public key. I'm generating that public key, using BC library. When i check the public key that i get from BC, then i can see that it is 64 bytes. According to your explanation I think that BC output it in short-Weierstrass format, while i need it in Montgomery curve format. How can i convert it to 32 bytes? This is my java code: X9ECParameters ecP = CustomNamedCurves.getByName("Curve25519"); ECParameterSpec ecSpec=new ECParameterSpec(ecP.getCurve(), ecP.getG(),ecP.getN(), ecP.getH(), ecP.getSeed()); KeyPairGenerator kpgen; The "public_key" returned here is 64 bytes! Please Advice! |
If you need to do the full X25519 ECDH, then I am going to strongly recommend that you use the classes added here: 1f559bb . It should be clear how to use it by referring to the X25519Test.testECDH method. The way that private keys are generated and/or used in X25519 have some subtle differences compared to JCE providers' behaviour for generic SW curves. Also, X25519 permits public keys on the twist of the curve, which will instead cause exceptions in SW implementations. So it's not clear to me that it can be made to work in the general case, without stepping outside of JCE and doing parts of the operations yourself. In which case, you may as well use the new code, which is a direct implementation of X25519, so requires no complicated adapters, and performs quite a bit faster besides. If you need any advice on using these classes would you please post further questions to the dev-crypto mailing list (http://bouncycastle.org/mailing_lists.html). |
@peterdettman I found this issue while trying to figure out how to create compatible keys between pointycastle and bouncycastle.
Is it possible to do the same in PointyCastle? If not can you suggest a way to do this using OpenSSL or Libsodium? |
@hamirshekhawat I assume you should be using |
Thanks @peterdettman for confirmation. |
I need to create a shared secret for the DH (Diffie–Hellman Key Exchange), using my private key and a public key that I receive from Apache Server. The code is written in Java + Bouncy Castle 1.57.
I have attached a screen shot from OpenSSL:
I have used openSSL in order to connect to a server, that implement, Curve25519. I have taken the public key, that have returned in the response and use it, as byte array, in the following code:
// **** START OF BOUNCY CASTLE CODE
byte[] publicKey = new byte[]{(byte)0xF1, (byte)0x6D, (byte)0x48, (byte)0x25, (byte)0x0C, (byte)0xE2, (byte)0xA2, (byte)0xA4, (byte)0xFD, (byte)0x4D, (byte)0x9B, (byte)0x08, (byte)0x57, (byte)0x7B, (byte)0x2D, (byte)0x3F, (byte)0x92, (byte)0xC6, (byte)0x4D, (byte)0x09, (byte)0x3C, (byte)0xD9, (byte)0x68, (byte)0xE6, (byte)0xC7, (byte)0x32, (byte)0x5E, (byte)0x40, (byte)0x30, (byte)0xB7, (byte)0xF2, (byte)0x06 };
ECParameterSpec ecP = ECNamedCurveTable.getParameterSpec(this.namedCarved);
ECPublicKeySpec pubKey = new
ECPublicKeySpec(ecP.getCurve().decodePoint(publicKey), ecP);
KeyFactory kf = KeyFactory.getInstance("ECDH", "BC");
return kf.generatePublic(pubKey);
// **** END OF BOUNCY CASTLE CODE
The problem it that the function ecP.getCurve().decodePoint(publicKey) throws an exception:
"java.lang.IllegalArgumentException: Invalid point encoding 0xF1"
The text was updated successfully, but these errors were encountered: