0

我需要将一些简单的 KeyPair 创建从 Javascript 迁移到 Java。使用 NodeJS 加密包,这非常简单:

const keyPair = crypto.createECDH("prime256v1");
keyPair.generateKeys();

然后,您可以使用生成的 keyPair 生成公钥和私钥,以与我们的服务器交换数据。

我发现了几个用 Java 编写的代码示例,它们使用 BouncyCastle 生成 ECDH 密钥对,但它们都抛出以下异常:

java.security.InvalidKeyException:没有安装的提供程序支持此密钥:org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey

看起来这应该像在 Node.js 中一样微不足道。我错过了什么?

我尝试了建议的代码,我得到了 [similar] 异常:

java.security.InvalidKeyException: No installed provider supports this key: sun.security.ec.ECPrivateKeyImpl
        at javax.crypto.Cipher.chooseProvider(Cipher.java:896)
        at javax.crypto.Cipher.init(Cipher.java:1399)
        at javax.crypto.Cipher.init(Cipher.java:1330)
        at com.strivve.Encryption.encryptAES256(Encryption.java:42)
        at com.strivve.App.go(App.java:26)
        at com.strivve.App.main(App.java:14)
4

1 回答 1

0

在 NodeJs 中生成 ECDH 密钥对几乎很容易,但您需要知道 Java 中使用的曲线名称。曲线“prime256v1”在 Java 中被称为“secp256r1”,SunEC 加密提供者有一个实现。

这是以下程序的结果(Java 详细打印出同义词曲线名称):

Java generate an EC keypair
privateKey: sun.security.ec.ECPrivateKeyImpl@ffff97b7
publicKey: Sun EC public key, 256 bits
  public x coord: 41232853336475799847910994406242230229392118856956796272263514934771986125833
  public y coord: 39545744123202785115112968739657610229201870815399428487100236626986481235670
  parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)

没有任何异常处理的完整代码:

import java.security.*;
import java.security.spec.ECGenParameterSpec;

public class Main {
    public static void main(String[] args) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
        System.out.println("Java generate an EC keypair");
        String ecdhCurvenameString = "secp256r1";
        // standard curvennames
        // secp256r1 [NIST P-256, X9.62 prime256v1]
        // secp384r1 [NIST P-384]
        // secp521r1 [NIST P-521]
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "SunEC");
        ECGenParameterSpec ecParameterSpec = new ECGenParameterSpec(ecdhCurvenameString);
        keyPairGenerator.initialize(ecParameterSpec);
        KeyPair ecdhKeyPair = keyPairGenerator.genKeyPair();
        PrivateKey privateKey = ecdhKeyPair.getPrivate();
        PublicKey publicKey = ecdhKeyPair.getPublic();
        System.out.println("privateKey: " + privateKey);
        System.out.println("publicKey: " + publicKey);
    }
}

编辑:2021 年 2 月 7 日:代码在包含 SunEC 提供程序的 Open Java 11 上运行,这就是为什么您看不到要导入的任何其他库的原因。也许您的 Java 不包含提供程序或它已被禁用,请运行我的简单提供程序测试 - 这是 Java 11 上的结果:

Provider: SUN version: 11.0
Provider: SunRsaSign version: 11.0
Provider: SunEC version: 11.0
Provider: SunJSSE version: 11.0
Provider: SunJCE version: 11.0
Provider: SunJGSS version: 11.0
Provider: SunSASL version: 11.0
Provider: XMLDSig version: 11.0
Provider: SunPCSC version: 11.0
Provider: JdkLDAP version: 11.0
Provider: JdkSASL version: 11.0
Provider: SunPKCS11 version: 11.0

代码:

import java.security.Provider;
import java.security.Security;
 
public class A05_CryptoProvider {
    
    public static void main(String[] args) {
        // source https://stackoverflow.com/questions/3683302/how-to-find-out-what-algorithm-encryption-are-supported-by-my-jvm/3683915#3683915
        for (Provider provider : Security.getProviders()) {
            System.out.println("Provider: " + provider.getName() + " version: " + provider.getVersion());
        }
    }
}
于 2021-02-05T10:16:57.773 回答