将 P-256 DH java 字符串转换为 java 公钥

Convert P-256 DH java string to java PublicKey

我正在尝试向我的浏览器发送网络推送通知,并且能够成功订阅。我得到一个带有 "an elliptic curve Diffie–Hellman public key on P-256 curve".

的订阅对象

我想将此字符串转换为 Java 中的 public 键,但一直收到无效的键格式异常。

这是我正在尝试的代码:

  String publicK = "BBoN_OkTfE_0uObues82qHr96z8x3nepYoUwCBoftFDS_Vgx2MUHN1vAFxc1eDiyDrvmZ2bQ4sJq3F8Qz71RWI0=";
  byte[] publicBytes = publicK.getBytes();
  X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
  KeyFactory keyFactory = KeyFactory.getInstance("DiffieHellman");
  PublicKey pubKey = keyFactory.generatePublic(keySpec);

有人可以帮我解决这个问题吗?加密菜鸟在这里:/

对于我的代码,我使用了 java 1.7BouncyCastle 库。如果你使用maven,只需添加到你的pom.xml:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk16</artifactId>
    <version>1.46</version>
</dependency>

或在 BouncyCastle 站点下载 jar。这是 java 的密码学 API,有很多有用的东西(包括 类 来处理椭圆曲线密钥)。

读取public键并转换为对象的代码为:

import java.security.KeyFactory;
import java.security.Security;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;

import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.ECPointUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.util.encoders.Base64;


// you need to add the BouncyCastle provider to use its functionalities
Security.addProvider(new BouncyCastleProvider());

String publicK = "BBoN_OkTfE_0uObues82qHr96z8x3nepYoUwCBoftFDS_Vgx2MUHN1vAFxc1eDiyDrvmZ2bQ4sJq3F8Qz71RWI0=";
// publicK is encoded in base64, so you need to decode it first
byte[] publicBytes = Base64.decode(publicK.getBytes());

// spec for P-256 curve
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("prime256v1");
// create a KeyFactory with ECDSA (Elliptic Curve Diffie-Hellman) algorithm and use BouncyCastle as the provider
KeyFactory kf = KeyFactory.getInstance("ECDSA", BouncyCastleProvider.PROVIDER_NAME);

// code below just creates the public key from the bytes contained in publicK
// using the curve parameters (spec variable)
ECNamedCurveSpec params = new ECNamedCurveSpec("prime256v1", spec.getCurve(), spec.getG(), spec.getN());
ECPoint point = ECPointUtil.decodePoint(params.getCurve(), publicBytes);
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params);
ECPublicKey pk = (ECPublicKey) kf.generatePublic(pubKeySpec);

System.out.println(pk.toString());

输出:

EC Public Key
            X: 1a0d00e9137c4034b8e6ee7acf36a87afdeb3f31de77a9628530081a1fb450d2
            Y: 15831d8c507375bc01717357838b20ebbe66766d0e2c26adc5f10cfbd51588d

备注:

  • 我不了解椭圆曲线密钥背后的所有数学知识,只了解基本概念。我知道曲线具有 Gn 等参数(通过 getG()getN() 方法获得)并且有一些 "standard pre-defined" 曲线(例如P-256),你可以使用 ECNamedCurveTable.getParameterSpec().

  • 您可以查看所有 math details if you want. There is also a list of different standard curves 以及哪些被认为是安全的。

  • ECPublicKey 扩展了 PublicKey,因此您可以像 PublicKey

  • 一样使用它