给定一个 DSAPrivateKey,如何计算对应的 DSAPublicKey?
Given a DSAPrivateKey, how to compute corresponding DSAPublicKey?
在Java中,我有一个DSAPrivateKey
,它有一个X
参数,还有一个DSAParams
和P
,Q
和 G
参数。我想计算相应的 DSAPublicKey
。我知道我可以构造一个 DSAPublicKeySpec
如果我知道 Y
、P
、Q
和 G
,然后我可以使用 KeyFactory.generatePublic(KeySpec)
将其转换为 DSAPublicKey
.
的方法
我不确定的是如何根据 X
、P
、Q
和 G
的知识计算 Y
。我猜答案是:
BigInteger y = g.multiply(x).mod(p);
但这会产生异常:
Caused by: java.lang.IllegalArgumentException: Y value does not appear to be in correct group
at org.bouncycastle.crypto.asymmetric.KeyUtils.validated(Unknown Source)
at org.bouncycastle.crypto.asymmetric.AsymmetricDSAPublicKey.<init>(Unknown Source)
at org.bouncycastle.jcajce.provider.ProvDSAPublicKey.<init>(Unknown Source)
所以显然那个猜测是不对的。我也试过:
BigInteger y = g.modPow(x, p);
给出了同样的例外。
我正在使用 BouncyCastle FIPS 1.0.2 版,所以我很乐意使用 BouncyCastle 类 的答案,但我也很乐意使用不使用 BouncyC 的答案
你用乘法得到值 y 是正确的。我找到了一个非常方便的解决方案,它适用于原生 Java.
安全警告:示例程序无异常处理,仅供学习使用
周末愉快!
这是我的示例程序的(简短)结果:
Derive DSA PublicKey from PrivateKey
publicKey equals publicKeyDerived: true
完整代码:
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.DSAParams;
import java.security.interfaces.DSAPrivateKey;
import java.security.spec.DSAPublicKeySpec;
import java.util.Arrays;
public class DSA_RetrievePublicKeyFromPrivateKey {
public static void main(String[] args) throws NoSuchProviderException, NoSuchAlgorithmException {
System.out.println("Derive DSA PublicKey from PrivateKey");
KeyPair keyPair = generateDsaKeyPair(2048);
PublicKey publicKeyOriginal = keyPair.getPublic(); // original for comparison
PublicKey publicKeyDerived = deriveDsaPublicKeyFromPrivatekey(keyPair.getPrivate());
System.out.println("publicKey equals publicKeyDerived: " + Arrays.equals(publicKeyOriginal.getEncoded(), publicKeyDerived.getEncoded()));
}
public static KeyPair generateDsaKeyPair(int keylengthInt)
throws NoSuchAlgorithmException, NoSuchProviderException {
KeyPairGenerator keypairGenerator = KeyPairGenerator.getInstance("DSA", "SUN");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
keypairGenerator.initialize(keylengthInt, random);
return keypairGenerator.generateKeyPair();
}
public static PublicKey deriveDsaPublicKeyFromPrivatekey (PrivateKey privateKey) throws NoSuchAlgorithmException {
DSAPrivateKey dsaPrivateKey = (DSAPrivateKey) privateKey;
DSAParams params = dsaPrivateKey.getParams();
BigInteger y = params.getG().modPow(dsaPrivateKey.getX(), params.getP());
DSAPublicKeySpec keySpec = new DSAPublicKeySpec(y, params.getP(), params.getQ(), params.getG());
PublicKey publicKey;
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
try {
publicKey = keyFactory.generatePublic(keySpec);
} catch (Exception e) {
throw new RuntimeException(e);
}
return publicKey;
}
}
在Java中,我有一个DSAPrivateKey
,它有一个X
参数,还有一个DSAParams
和P
,Q
和 G
参数。我想计算相应的 DSAPublicKey
。我知道我可以构造一个 DSAPublicKeySpec
如果我知道 Y
、P
、Q
和 G
,然后我可以使用 KeyFactory.generatePublic(KeySpec)
将其转换为 DSAPublicKey
.
我不确定的是如何根据 X
、P
、Q
和 G
的知识计算 Y
。我猜答案是:
BigInteger y = g.multiply(x).mod(p);
但这会产生异常:
Caused by: java.lang.IllegalArgumentException: Y value does not appear to be in correct group
at org.bouncycastle.crypto.asymmetric.KeyUtils.validated(Unknown Source)
at org.bouncycastle.crypto.asymmetric.AsymmetricDSAPublicKey.<init>(Unknown Source)
at org.bouncycastle.jcajce.provider.ProvDSAPublicKey.<init>(Unknown Source)
所以显然那个猜测是不对的。我也试过:
BigInteger y = g.modPow(x, p);
给出了同样的例外。
我正在使用 BouncyCastle FIPS 1.0.2 版,所以我很乐意使用 BouncyCastle 类 的答案,但我也很乐意使用不使用 BouncyC 的答案
你用乘法得到值 y 是正确的。我找到了一个非常方便的解决方案,它适用于原生 Java.
安全警告:示例程序无异常处理,仅供学习使用
周末愉快!
这是我的示例程序的(简短)结果:
Derive DSA PublicKey from PrivateKey
publicKey equals publicKeyDerived: true
完整代码:
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.DSAParams;
import java.security.interfaces.DSAPrivateKey;
import java.security.spec.DSAPublicKeySpec;
import java.util.Arrays;
public class DSA_RetrievePublicKeyFromPrivateKey {
public static void main(String[] args) throws NoSuchProviderException, NoSuchAlgorithmException {
System.out.println("Derive DSA PublicKey from PrivateKey");
KeyPair keyPair = generateDsaKeyPair(2048);
PublicKey publicKeyOriginal = keyPair.getPublic(); // original for comparison
PublicKey publicKeyDerived = deriveDsaPublicKeyFromPrivatekey(keyPair.getPrivate());
System.out.println("publicKey equals publicKeyDerived: " + Arrays.equals(publicKeyOriginal.getEncoded(), publicKeyDerived.getEncoded()));
}
public static KeyPair generateDsaKeyPair(int keylengthInt)
throws NoSuchAlgorithmException, NoSuchProviderException {
KeyPairGenerator keypairGenerator = KeyPairGenerator.getInstance("DSA", "SUN");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
keypairGenerator.initialize(keylengthInt, random);
return keypairGenerator.generateKeyPair();
}
public static PublicKey deriveDsaPublicKeyFromPrivatekey (PrivateKey privateKey) throws NoSuchAlgorithmException {
DSAPrivateKey dsaPrivateKey = (DSAPrivateKey) privateKey;
DSAParams params = dsaPrivateKey.getParams();
BigInteger y = params.getG().modPow(dsaPrivateKey.getX(), params.getP());
DSAPublicKeySpec keySpec = new DSAPublicKeySpec(y, params.getP(), params.getQ(), params.getG());
PublicKey publicKey;
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
try {
publicKey = keyFactory.generatePublic(keySpec);
} catch (Exception e) {
throw new RuntimeException(e);
}
return publicKey;
}
}