问题描述
我知道EC公钥的曲线名称( secp256k1
)和 X
和 Y
坐标.
I know the curve name (secp256k1
) and the X
and Y
coordinates of the EC public key.
如何从其中制作一个 org.bouncycastle.jce.interfaces.ECPublicKey
?
我已阅读 https://stackoverflow.com/a/29355749/5453873 ,但其中的代码使用 java.security ...
而不是 org.bouncycastle ...
,而ECPublicKey是 org.bouncycastle ...
中的接口,不是可实例化的类
I've read https://stackoverflow.com/a/29355749/5453873 but the code there uses java.security...
instead of org.bouncycastle...
and ECPublicKey is an interface in org.bouncycastle...
not an instantiable class.
推荐答案
使用Bouncy Castle生成ECPublicKey
这将生成JCE/JCA中使用的EC公共密钥.有弹性的城堡提供程序可以直接使用这些软件密钥.否则,Bouncy仅用于生成生成公钥所需的参数.
Generating ECPublicKey using Bouncy Castle
This generates the EC public key as used in the JCE/JCA. The Bouncy Castle provider can directly use these software keys. Otherwise Bouncy is just used to generate the parameters required to generate the public key.
package nl.owlstead.stackoverflow;
import static java.nio.charset.StandardCharsets.US_ASCII;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.Security;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
import javax.crypto.Cipher;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.util.encoders.Hex;
public class ECPublicKeyFactory {
public static void main(String[] args) throws Exception {
String name = "secp256r1";
Security.addProvider(new BouncyCastleProvider());
// === NOT PART OF THE CODE, JUST GETTING TEST VECTOR ===
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC");
ECGenParameterSpec ecGenParameterSpec = new ECGenParameterSpec(name);
kpg.initialize(ecGenParameterSpec);
ECPublicKey key = (ECPublicKey) kpg.generateKeyPair().getPublic();
byte[] x = key.getW().getAffineX().toByteArray();
byte[] y = key.getW().getAffineY().toByteArray();
// === here the magic happens ===
KeyFactory eckf = KeyFactory.getInstance("EC");
ECPoint point = new ECPoint(new BigInteger(1, x), new BigInteger(1, y));
ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec(name);
ECParameterSpec spec = new ECNamedCurveSpec(name, parameterSpec.getCurve(), parameterSpec.getG(), parameterSpec.getN(), parameterSpec.getH(), parameterSpec.getSeed());
ECPublicKey ecPublicKey = (ECPublicKey) eckf.generatePublic(new ECPublicKeySpec(point, spec));
System.out.println(ecPublicKey.getClass().getName());
// === test 123 ===
Cipher ecies = Cipher.getInstance("ECIESwithAES", "BC");
ecies.init(Cipher.ENCRYPT_MODE, ecPublicKey);
byte[] ct = ecies.doFinal("owlstead".getBytes(US_ASCII));
System.out.println(Hex.toHexString(ct));
}
}
生成Bouncy Castle ECPublicKeyParameters
最初,我认为需要特定于Bouncy Castle的密钥,因此以下代码生成了在Bouncy Castle轻量级API中使用的EC公钥.
Generating Bouncy Castle ECPublicKeyParameters
Initially I thought that a Bouncy Castle specific key was required, so the following code generates the EC public key as used in the Bouncy Castle lightweight API.
package nl.owlstead.stackoverflow;
import java.math.BigInteger;
import java.security.KeyPairGenerator;
import java.security.Security;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECGenParameterSpec;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.params.ECNamedDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
public class BC_EC_KeyCreator {
public static void main(String[] args) throws Exception {
String name = "secp256r1";
// === NOT PART OF THE CODE, JUST GETTING TEST VECTOR ===
Security.addProvider(new BouncyCastleProvider());
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC");
kpg.initialize(new ECGenParameterSpec(name));
ECPublicKey key = (ECPublicKey) kpg.generateKeyPair().getPublic();
byte[] x = key.getW().getAffineX().toByteArray();
byte[] y = key.getW().getAffineY().toByteArray();
// assumes that x and y are (unsigned) big endian encoded
BigInteger xbi = new BigInteger(1, x);
BigInteger ybi = new BigInteger(1, y);
X9ECParameters x9 = ECNamedCurveTable.getByName(name);
ASN1ObjectIdentifier oid = ECNamedCurveTable.getOID(name);
ECCurve curve = x9.getCurve();
ECPoint point = curve.createPoint(xbi, ybi);
ECNamedDomainParameters dParams = new ECNamedDomainParameters(oid,
x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
ECPublicKeyParameters pubKey = new ECPublicKeyParameters(point, dParams);
System.out.println(pubKey);
// some additional encoding tricks
byte[] compressed = point.getEncoded(true);
System.out.println(Hex.toHexString(compressed));
byte[] uncompressed = point.getEncoded(false);
System.out.println(Hex.toHexString(uncompressed));
}
}
这主要是棘手的,因为我不想包含任何JCE特定的代码,并且 X9ECParameters
不是 ECDomainParameters
的子类.因此,我使用了从Bouncy Castle代码库中其他位置复制的 ECNamedDomainParameters
的转换.
This was mostly tricky because I didn't want to include any JCE specific code, and X9ECParameters
is not a subclass of ECDomainParameters
. So I used a conversion to ECNamedDomainParameters
copied from elsewhere in the code base of Bouncy Castle.
这篇关于如何制作充气城堡ECPublicKey的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!