Stack Overflow Asked by Simon Kissane on December 17, 2020
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.<init>(Unknown Source)
at org.bouncycastle.jcajce.provider.ProvDSAPublicKey.<init>(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
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("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;
}
}
Correct answer by Michael Fehr on December 17, 2020
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP