我试图在Java中以编程方式重现“openssl dhparam -out dh1024.pem 1024”命令的输出。代码段如下: -
DHParametersGenerator generator = new DHParametersGenerator();
generator.init(1024, 0, new SecureRandom());
DHParameters params = generator.generateParameters();
// Generator G is set as random in params, but it has to be 2 to conform to openssl
DHParameters realParams = new DHParameters(params.getP(), BigInteger.valueOf(2));
byte[] p = realParams.getP().toByteArray();
byte[] g = realParams.getG().toByteArray();
byte[] l = new byte[(byte) realParams.getL()];
byte[] pgl = new byte[p.length+g.length+l.length];
System.arraycopy(p, 0, pgl, 0, p.length);
System.arraycopy(g, 0, pgl, p.length, g.length);
System.arraycopy(l, 0, pgl, p.length+g.length, l.length);
所以基本上我在字节数组“pgl”中连接P,G和L参数的值,然后使用BC的PEMWriter类将其保存在文件中。但是当我尝试通过openssl使用它时,我收到以下错误: -
无法加载DH参数 /etc/openvpn/easy-rsa/keys/dh1024.pem: 错误:0D07207B:asn1编码 例程:ASN1_get_object:标题也是 long:错误:0D068066:asn1编码 例程:ASN1_CHECK_TLEN:坏对象 header:错误:0D07803A:asn1编码 例程:ASN1_ITEM_EX_D2I:嵌套asn1 错误:错误:0906700D:PEM 例程:PEM_ASN1_read_bio:ASN1 lib
....这让我相信我错误地编码了DH参数,但我无法找到正确的编码方式。任何人都可以帮助我吗?好几天我一直在城堡墙上弹跳,但无济于事....请帮忙:(
答案 0 :(得分:3)
感谢GregS,你的解决方案有效,但我最终使用BC的标准Java加PemWriter解决了它,虽然你不能用这种方法设置Generator G = 2,但它仍然适用于openssl和Java,这是我最初的目的无论如何:)
import java.io.FileWriter;
import java.io.IOException;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;
public class DHCredentials {
public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchProviderException, IOException
{
DHCredentials dhc = new DHCredentials();
System.out.println("This may take a long time ...");
dhc.saveDHParams("C:\\xxxDH.txt", dhc.genDHParams());
System.out.println("Done");
}
public byte[] genDHParams() throws IOException
{
AlgorithmParameterGenerator paramGen = null;
try
{
paramGen = AlgorithmParameterGenerator.getInstance("DH");
paramGen.init(1024, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
AlgorithmParameters params = paramGen.generateParameters();
return params.getEncoded();
}
public void saveDHParams(String filePath, byte[] DEREncodedDHParams)
{
PemWriter pemWrt;
try {
pemWrt = new PemWriter(new FileWriter(filePath));
pemWrt.writeObject(new PemObject("DH PARAMETERS", DEREncodedDHParams));
pemWrt.flush();
pemWrt.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
答案 1 :(得分:2)
这是一个例子。请注意,您不能在generator.init()
中将determinty参数设置为0,否则您将无法获得素数!我只是通过查看Bouncycastle源代码来找出大部分代码,例如查看PEMWriter类。
import java.math.BigInteger;
import java.security.SecureRandom;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.crypto.generators.DHParametersGenerator;
import org.bouncycastle.crypto.params.DHParameters;
import org.bouncycastle.util.encoders.Base64;
public class OpenSSLDHParamClone
{
public static void main(String[] args) throws Exception
{
DHParametersGenerator generator = new DHParametersGenerator();
generator.init(1024, 80, new SecureRandom());
DHParameters params = generator.generateParameters();
// Generator G is set as random in params, but it has to be 2 to conform to openssl
DHParameters realParams = new DHParameters(params.getP(), BigInteger.valueOf(2));
ASN1EncodableVector seq = new ASN1EncodableVector();
seq.add(new DERInteger(realParams.getP()));
seq.add(new DERInteger(realParams.getG()));
byte [] derEncoded = new DERSequence(seq).getDEREncoded();
System.out.println("-----BEGIN DH PARAMETERS-----");
String b64Encoded = new String(Base64.encode(derEncoded), "US-ASCII");
while (b64Encoded.length() > 0) {
int subStringLength = Math.min(64, b64Encoded.length());
System.out.println(b64Encoded.substring(0, subStringLength));
b64Encoded = b64Encoded.substring(subStringLength);
}
System.out.println("-----END DH PARAMETERS-----");
}
}