elliptic icon indicating copy to clipboard operation
elliptic copied to clipboard

Montgomery Curve25519 is not openssl compatible

Open jc-lab opened this issue 3 years ago • 5 comments

import * as elliptic from 'elliptic';

    const ec = new elliptic.ec('curve25519');
    const privateKey = ec.keyFromPrivate('0843f2237a9597939c62512ab405e1d92838044b757e1395dbc8e3deeb4e9f9c', 'hex');
    /*
It is converted as below. (See You can check it through https://lapo.it/asn1js/ )
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VuBCIEIAhD8iN6lZeTnGJRKrQF4dkoOARLdX4TldvI497rTp+c
-----END PRIVATE KEY-----

Expected Output (OpenSSL's Output)
$ openssl pkey -in a.pem -pubout
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VuAyEAYt0EgkDficTmquiGJommRI6zRhxIFJkSgnfWjFtUIRM=
-----END PUBLIC KEY-----
=> 0062dd048240df89c4e6aae8862689a6448eb3461c481499128277d68c5b542113
     */
    const publicKey = privateKey.getPublic();
    console.log('public key : ' + publicKey.encode('hex', false));
    // public key : 79a24c01a2fa3db176de2c27dc57856abfb2eb25634abe803e7d940399f8fc98
    // !=           62dd048240df89c4e6aae8862689a6448eb3461c481499128277d68c5b542113

Java(Bouncycastle) also same

import org.bouncycastle.jcajce.interfaces.XDHPublicKey;
import org.bouncycastle.jcajce.provider.asymmetric.edec.BCXDHPrivateKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

public class Main {
    public static String toHex(byte[] data) {
        StringBuilder sb = new StringBuilder();
        sb.append(data.length + " : ");
        for (byte b: data) sb.append(String.format("%02x", b&0xff));
        return sb.toString();
    }

    public static void main(String[] args) throws Exception {
        BouncyCastleProvider bouncyCastleProvider = new BouncyCastleProvider();
        KeyFactory keyFactory = KeyFactory.getInstance("X25519", bouncyCastleProvider);
        BCXDHPrivateKey privateKey = (BCXDHPrivateKey)keyFactory.generatePrivate(new PKCS8EncodedKeySpec(
                Base64.getDecoder().decode("MC4CAQAwBQYDK2VuBCIEIAhD8iN6lZeTnGJRKrQF4dkoOARLdX4TldvI497rTp+c")
        ));
        XDHPublicKey publicKey = privateKey.getPublicKey();
        System.out.println("publicKey = " + publicKey);
//        System.out.println("publicKey = " + toHex(publicKey.getEncoded()));
    }
}

// OUTPUT:
// publicKey = X25519 Public Key [86:4a:7f:9b:bd:8e:ad:81:53:96:cd:49:6e:e0:e1:6e:29:d6:70:9c]
//    public data: 62dd048240df89c4e6aae8862689a6448eb3461c481499128277d68c5b542113

The value obtained by changing the private key to public key through OpenSSL and the value obtained by obtaining the public key through elliptic library are different. So ECDH also fails.

Note: This is different from the issue in #122.

It seems to be related to #94 issue. Currently, the above test fails. Isn't this repo's X25519 implementation not standard?

jc-lab avatar Dec 28 '20 06:12 jc-lab