elliptic icon indicating copy to clipboard operation
elliptic copied to clipboard

ECDH P-521 public key point not on curve according to java (clojure)

Open slhabity opened this issue 5 years ago • 2 comments

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

slhabity avatar Feb 11 '20 12:02 slhabity

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

FlorianDubath avatar Mar 04 '20 09:03 FlorianDubath

Got the same issue with python and p521

julianhille avatar May 14 '21 00:05 julianhille