elliptic
elliptic copied to clipboard
ECDH P-521 public key point not on curve according to java (clojure)
Hello, thanks for a very nice library!
I'm trying to get interop working with Java/Clojure but the Java side seems to think the public key point is off the curve. I am passing the public key as a JWT, and have verified the transferred values on both sides. Has anyone run into this before?
This is the (PoC) code generating the x
and y
parameters on the js side:
import { toByteArray, fromByteArray } from 'base64-js';
var EC = require('elliptic').ec;
...
const ec = new EC('p521');
const devKeys = ec.genKeyPair();
...
const b1 = {
kty: 'EC',
crv: 'P-521',
x: b64url(fromByteArray(devKeys.getPublic().x.toArray('be', 66))),
y: b64url(fromByteArray(devKeys.getPublic().y.toArray('be', 66))),
};
Test code on the clojure/java side:
(comment
(def bob {:kty "EC",
:crv "P-521",
:x "AZu6pcaeecNKGWtSwDalY4fCIIQg8cqEwgPMJM4moPEdYqtbWwKtBIN6DKmrWEoFzt7kjdFaslBwR7_vlx_KAKjW",
:y "AH46YUDN-x5U9MOh1KMUji2HvDJZ9yQGEyD6tAciQsIzhX14KR82gg8V4bWpJOzZqE3mnGcKuIMp2h-3Ln9t-Ud9"})
(def kex-keys
(.genKeyPair (doto (KeyPairGenerator/getInstance "EC" "BC")
(.initialize (ECGenParameterSpec. "secp521r1")))))
(require '[buddy.core.keys :as jwks])
(require '[buddy.core.keys.jwk.proto :as proto])
(require '[clojure.stacktrace :refer :all])
(import '(java.security AlgorithmParameters KeyFactory))
(import '(java.security.spec ECPoint ECParameterSpec ECGenParameterSpec ECPublicKeySpec))
(def curvename "secp521r1")
;; The following crashes on eval:
;; CompilerException java.security.spec.InvalidKeySpecException: invalid KeySpec: Point not on curve, compiling: (form-init18432719393428711312.clj:99:15)
(def bob-bc (jwks/jwk->public-key bob))
;; Trying to create the pubkey using the Sun KeyFactory works...
(def bob-key
(let [x (#'proto/b64str->bigint (:x bob))
y (#'proto/b64str->bigint (:y bob))
ep (ECPoint. x y)
ap (AlgorithmParameters/getInstance "EC" "BC")
_ (.init ap (ECGenParameterSpec. "P-521"))
spec (.getParameterSpec ap ECParameterSpec)
kf (KeyFactory/getInstance "EC")]
(.generatePublic kf (ECPublicKeySpec. ep spec))))
;; But then fails when trying to generate the secret (first SUN, then BC):
;; IllegalStateException sun.security.ec.ECDHKeyAgreement.deriveKey (ECDHKeyAgreement.java:-2))
;; IllegalArgumentException Point not on curve org.bouncycastle.crypto.params.ECDomainParameters.validate (:-1))
(.generateSecret (doto
(KeyAgreement/getInstance "ECDH" "BC")
(.init (.getPrivate kex-keys))
(.doPhase bob-key true))))
Key encode/decode validation, JavaScript console.log:
x.toString(10): 5520384585226061860861016712844415904332744268642487830784964263472479827114973512952462183886998417222925704887623095254979323861686451102672365831980099798
y.toString(10): 1692441402377204147483647184756084090339425195378381520289392248650907750070458328167918004923929199266654445903593074962074030360595496599592484315258767229
And decoded by buddy.core.keys.jwk.proto/b64->bigint
on the clojure side:
x: 5520384585226061860861016712844415904332744268642487830784964263472479827114973512952462183886998417222925704887623095254979323861686451102672365831980099798
y: 1692441402377204147483647184756084090339425195378381520289392248650907750070458328167918004923929199266654445903593074962074030360595496599592484315258767229
I have the same problem with secp256k1 and python
js code `var EC = require('elliptic').ec;
var ec = new EC("secp256k1");
var ephemPrivKey = ec.keyFromPrivate(ethUtil.crypto.randomBytes(32));
var ephemPubKey = ephemPrivKey.getPublic();`
I get for the public key x=22474296688176133235257927448115289531934523642673351395474950275971993172788 y=18286832999795836373485244560314749276966435227077866247734288217041016719268
putting it into the python `from Crypto.PublicKey import ECC
ECC.construct(curve='secp256r1', point_x=22474296688176133235257927448115289531934523642673351395474950275971993172788, point_y=18286832999795836373485244560314749276966435227077866247734288217041016719268)`
I got
ValueError: The point is not on the curve
and if I create a key in Python importing the private key, the point computed as public key (x,y) is different from the one from the JS
Got the same issue with python and p521