给定一个 DSAPrivateKey,如何计算对应的 DSAPublicKey?

Given a DSAPrivateKey, how to compute corresponding DSAPublicKey?

在Java中,我有一个DSAPrivateKey,它有一个X参数,还有一个DSAParamsPQG 参数。我想计算相应的 DSAPublicKey。我知道我可以构造一个 DSAPublicKeySpec 如果我知道 YPQG,然后我可以使用 KeyFactory.generatePublic(KeySpec)将其转换为 DSAPublicKey.

的方法

我不确定的是如何根据 XPQG 的知识计算 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;
    }
}