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

huangapple go评论86阅读模式
英文:

Given a DSAPrivateKey, how to compute corresponding DSAPublicKey?

问题

在Java中,我有一个DSAPrivateKey,它有一个X参数,还有一个带有PQG参数的DSAParams。我想要计算相应的DSAPublicKey。我知道如果我知道YPQG,我可以构造一个DSAPublicKeySpec,然后我可以使用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 the 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类回答我也可以接受,但是如果不使用BouncyCastle的答案我也可以接受。

英文:

In Java, I have a DSAPrivateKey, which has an X parameter, and also a DSAParams with P, Q and G parameters. I want to compute the corresponding DSAPublicKey. I know I can construct a DSAPublicKeySpec if I know Y, P, Q, and G, and then I can use the KeyFactory.generatePublic(KeySpec) method to turn that into a DSAPublicKey.

The thing I'm not sure about, is how to compute Y given knowledge of X, P, Q and G. I guessed the answer was:

BigInteger y = g.multiply(x).mod(p);

But that produces exception:

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.&lt;init&gt;(Unknown Source)
	at org.bouncycastle.jcajce.provider.ProvDSAPublicKey.&lt;init&gt;(Unknown Source)

So obviously that guess isn't right. I also tried:

BigInteger y = g.modPow(x, p);

which gives the same exception.

I'm using BouncyCastle FIPS version 1.0.2, so I'd be happy with an answer that uses BouncyCastle classes, but I'd also be happy with one that doesn't use BouncyC

答案1

得分: 2

你在用乘法得到值 y 时是正确的。我找到了一个非常方便的解决方案,它适用于原生的 Java。

安全警告:示例程序没有异常处理,仅供教育目的。

祝你周末愉快!

以下是我示例程序的(简短)结果:

从 PrivateKey 派生 DSA PublicKey
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("从 PrivateKey 派生 DSA PublicKey");

        KeyPair keyPair = generateDsaKeyPair(2048);
        PublicKey publicKeyOriginal =  keyPair.getPublic(); // 用于比较的原始公钥
        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;
    }
}
英文:

You were right with the multiplication to get the value y. I found a very handy solution that does work with native Java.

Security warning: the sample program has no exception handling and is for educational purposes only.

Have a nice weekend!

Here is the (short) result of my example program:

Derive DSA PublicKey from PrivateKey
publicKey equals publicKeyDerived: true

full code:

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(&quot;Derive DSA PublicKey from PrivateKey&quot;);
KeyPair keyPair = generateDsaKeyPair(2048);
PublicKey publicKeyOriginal =  keyPair.getPublic(); // original for comparison
PublicKey publicKeyDerived = deriveDsaPublicKeyFromPrivatekey(keyPair.getPrivate());
System.out.println(&quot;publicKey equals publicKeyDerived: &quot; + Arrays.equals(publicKeyOriginal.getEncoded(), publicKeyDerived.getEncoded()));
}
public static KeyPair generateDsaKeyPair(int keylengthInt)
throws NoSuchAlgorithmException, NoSuchProviderException {
KeyPairGenerator keypairGenerator = KeyPairGenerator.getInstance(&quot;DSA&quot;, &quot;SUN&quot;);
SecureRandom random = SecureRandom.getInstance(&quot;SHA1PRNG&quot;, &quot;SUN&quot;);
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(&quot;DSA&quot;);
try {
publicKey = keyFactory.generatePublic(keySpec);
} catch (Exception e) {
throw new RuntimeException(e);
}
return publicKey;
}
}

huangapple
  • 本文由 发表于 2020年8月22日 13:57:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/63533035.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定