使用给定私钥在椭圆曲线算法中生成公钥的代码

我需要使用jdk 1.7实现ECC(椭圆曲线加密)算法。 我尝试使用充气城堡,sunEC,但他们都给出了错误和错误。 我的目标是使用私钥生成椭圆曲线,我将被赋予系统。

因此,我需要使用jdk1.7获取使用给定私钥生成公钥的准确代码。 我使用的IDE是ecllipse。 我需要知道,除私钥外,我应该给出的其他参数是什么? 提供曲线点和私钥是否足够?

有人可以帮我从私钥生成公钥吗? 我可以管理其余的实现。

任何知道使用java实现Elliptic Curve Cryptography键的人,请告诉我这段代码是否正确?

public class ECCrypt { private ECPoint curve_point; public ECCrypt(ECPoint curve_point) { this.curve_point = curve_point; } public BigInteger makePublicKey(BigInteger privateKey) { ECPoint ecPublicKey = new ECPoint(curve_point); ecPublicKey.mult(privateKey); return ecPublicKey.pack(); } public static void main(String[] argv) throws Exception { java.util.Random rnd = new java.util.Random(); ECPoint cp = new ECPoint(); cp.random(rnd); ECCrypt ec = new ECCrypt(cp); BigInteger priv = new BigInteger(255,rnd); BigInteger pub = ec.makePublicKey(priv); } 

谢谢!

我写了一个示例程序,输出以下内容:

 FL261:java jvah$ javac -cp bcprov-ext-jdk15on-149.jar ECTest.java FL261:java jvah$ java -cp bcprov-ext-jdk15on-149.jar:. ECTest Private key: 7ba78909571fbc336b2b94054dfb745a6b0776ff36a8fa98a598dc32cb83cc8e Public key: 035b9e4a6148c9f9b08b573871ac66a832e6e9f63cf117545523a45b8017b7c43f Calculated public key: 035b9e4a6148c9f9b08b573871ac66a832e6e9f63cf117545523a45b8017b7c43f Congratulations, public keys match! FL261:java jvah$ 

代码应该足够清楚,以便您可以理解这里所做的事情。 请注意,您必须知道为您的私钥生成哪条曲线,否则无法生成匹配的公钥。 示例代码使用secp256r1曲线,这是很常用的。

 import java.math.BigInteger; import java.security.SecureRandom; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECKeyGenerationParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.bouncycastle.math.ec.ECPoint; class ECTest { public static String toHex(byte[] data) { StringBuilder sb = new StringBuilder(); for (byte b: data) { sb.append(String.format("%02x", b&0xff)); } return sb.toString(); } public static void main(String[] argv) { // Get domain parameters for example curve secp256r1 X9ECParameters ecp = SECNamedCurves.getByName("secp256r1"); ECDomainParameters domainParams = new ECDomainParameters(ecp.getCurve(), ecp.getG(), ecp.getN(), ecp.getH(), ecp.getSeed()); // Generate a private key and a public key AsymmetricCipherKeyPair keyPair; ECKeyGenerationParameters keyGenParams = new ECKeyGenerationParameters(domainParams, new SecureRandom()); ECKeyPairGenerator generator = new ECKeyPairGenerator(); generator.init(keyGenParams); keyPair = generator.generateKeyPair(); ECPrivateKeyParameters privateKey = (ECPrivateKeyParameters) keyPair.getPrivate(); ECPublicKeyParameters publicKey = (ECPublicKeyParameters) keyPair.getPublic(); byte[] privateKeyBytes = privateKey.getD().toByteArray(); // First print our generated private key and public key System.out.println("Private key: " + toHex(privateKeyBytes)); System.out.println("Public key: " + toHex(publicKey.getQ().getEncoded(true))); // Then calculate the public key only using domainParams.getG() and private key ECPoint Q = domainParams.getG().multiply(new BigInteger(privateKeyBytes)); System.out.println("Calculated public key: " + toHex(Q.getEncoded(true))); // The calculated public key and generated public key should always match if (!toHex(publicKey.getQ().getEncoded(true)).equals(toHex(Q.getEncoded(true)))) { System.out.println("ERROR: Public keys do not match!"); } else { System.out.println("Congratulations, public keys match!"); } } } 

我使用此方法从ECPrivateKey恢复ECPublicKey。 最后,主要的Routinecertificate它有效。 它是没有任何外部库的普通java。

 public final class MULT { private static ECPoint doublePoint(final BigInteger p, final BigInteger a, final ECPoint R) { if (R.equals(ECPoint.POINT_INFINITY)) return R; BigInteger slope = (R.getAffineX().pow(2)).multiply(FieldP._3); slope = slope.add(a); slope = slope.multiply((R.getAffineY().multiply(FieldP._2)).modInverse(p)); final BigInteger Xout = slope.pow(2).subtract(R.getAffineX().multiply(FieldP._2)).mod(p); final BigInteger Yout = (R.getAffineY().negate()).add(slope.multiply(R.getAffineX().subtract(Xout))).mod(p); return new ECPoint(Xout, Yout); } private static ECPoint addPoint (final BigInteger p, final BigInteger a, final ECPoint r, final ECPoint g) { if (r.equals(ECPoint.POINT_INFINITY)) return g; if (g.equals(ECPoint.POINT_INFINITY)) return r; if (r==g || r.equals(g)) return doublePoint(p, a, r); final BigInteger gX = g.getAffineX(); final BigInteger sY = g.getAffineY(); final BigInteger rX = r.getAffineX(); final BigInteger rY = r.getAffineY(); final BigInteger slope = (rY.subtract(sY)).multiply(rX.subtract(gX).modInverse(p)).mod(p); final BigInteger Xout = (slope.modPow(FieldP._2, p).subtract(rX)).subtract(gX).mod(p); BigInteger Yout = sY.negate().mod(p); Yout = Yout.add(slope.multiply(gX.subtract(Xout))).mod(p); return new ECPoint(Xout, Yout); } public static ECPoint scalmult (final EllipticCurve curve, final ECPoint g, final BigInteger kin) { final ECField field = curve.getField(); if(!(field instanceof ECFieldFp)) throw new UnsupportedOperationException(field.getClass().getCanonicalName()); final BigInteger p = ((ECFieldFp)field).getP(); final BigInteger a = curve.getA(); ECPoint R = ECPoint.POINT_INFINITY; BigInteger k = kin.mod(p); final int length = k.bitLength(); final byte[] binarray = new byte[length]; for(int i=0;i<=length-1;i++){ binarray[i] = k.mod(FieldP._2).byteValue(); k = k.shiftRight(1); } for(int i = length-1;i >= 0;i--){ R = doublePoint(p, a, R); if(binarray[i]== 1) R = addPoint(p, a, R, g); } return R; } public static ECPublicKey getPublicKey(final ECPrivateKey pk) throws GeneralSecurityException { final ECParameterSpec params = pk.getParams(); final ECPoint w = scalmult(params.getCurve(), pk.getParams().getGenerator(), pk.getS()); final KeyFactory kg = KeyFactory.getInstance("EC"); return (ECPublicKey)kg.generatePublic (new ECPublicKeySpec (w, params)); } 

}

从ECPrivateKey对Genemark ECPublicKey的@markw的答案进行了一些改进,扩展了@ bas-goossen的曲线名称检测: 如何从ECPublicKey中找到匹配的曲线名称

 public static ECPublicKey publicFromPrivate(final ECPrivateKey privateKey) throws Exception { ECParameterSpec params = privateKey.getParams(); org.bouncycastle.jce.spec.ECParameterSpec bcSpec = org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util .convertSpec(params, false); org.bouncycastle.math.ec.ECPoint q = bcSpec.getG().multiply(privateKey.getS()); org.bouncycastle.math.ec.ECPoint bcW = bcSpec.getCurve().decodePoint(q.getEncoded(false)); ECPoint w = new ECPoint( bcW.getAffineXCoord().toBigInteger(), bcW.getAffineYCoord().toBigInteger()); ECPublicKeySpec keySpec = new ECPublicKeySpec(w, tryFindNamedCurveSpec(params)); return (ECPublicKey) KeyFactory .getInstance("EC", org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME) .generatePublic(keySpec); } @SuppressWarnings("unchecked") public static ECParameterSpec tryFindNamedCurveSpec(ECParameterSpec params) { org.bouncycastle.jce.spec.ECParameterSpec bcSpec = org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util.convertSpec(params, false); for (Object name : Collections.list(org.bouncycastle.jce.ECNamedCurveTable.getNames())) { org.bouncycastle.jce.spec.ECNamedCurveParameterSpec bcNamedSpec = org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec((String) name); if (bcNamedSpec.getN().equals(bcSpec.getN()) && bcNamedSpec.getH().equals(bcSpec.getH()) && bcNamedSpec.getCurve().equals(bcSpec.getCurve()) && bcNamedSpec.getG().equals(bcSpec.getG())) { return new org.bouncycastle.jce.spec.ECNamedCurveSpec( bcNamedSpec.getName(), bcNamedSpec.getCurve(), bcNamedSpec.getG(), bcNamedSpec.getN(), bcNamedSpec.getH(), bcNamedSpec.getSeed()); } } return params; }