Как правильно кодировать параметры DH, используя BouncyCastle в Java? - PullRequest
0 голосов
/ 27 апреля 2011

Я пытаюсь воспроизвести вывод команды "openssl dhparam -out dh1024.pem 1024" программно в Java. Фрагмент кода следующий: -

            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);

Так что в основном я объединяю значения параметров P, G и L в байтовом массиве "pgl", а затем сохраняю его в файле с использованием класса PEMWriter из BC. Но когда я пытаюсь использовать его через openssl, я получаю следующую ошибку: -

Невозможно загрузить параметры DH из /etc/openvpn/easy-rsa/keys/dh1024.pem: ошибка: 0D07207B: кодировка asn1 подпрограммы: ASN1_get_object: заголовок тоже long: ошибка: 0D068066: кодировка asn1 подпрограммы: ASN1_CHECK_TLEN: плохой объект заголовок: ошибка: 0D07803A: кодировка asn1 подпрограммы: ASN1_ITEM_EX_D2I: вложенный asn1 ошибка: ошибка: 0906700D: PEM подпрограммы: PEM_ASN1_read_bio: ASN1 lib

.... что заставляет меня поверить, что я неправильно кодирую параметры DH, но я не могу найти где-нибудь правильный способ кодировать это. Может ли кто-нибудь помочь мне в этом? Я уже несколько дней отскакиваю голову от стены замка, но безрезультатно .... помогите :(

Ответы [ 2 ]

3 голосов
/ 07 мая 2011

Благодаря GregS, ваше решение работает, но я в конце концов решил его, используя стандартную Java плюс PemWriter от BC, хотя вы не можете установить 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();
        }
    }
}
2 голосов
/ 29 апреля 2011

Вот пример. Обратите внимание, что вы не можете установить аргумент уверенности в 0 в generator.init(), иначе вы не получите простое число! Большую часть этого кода я понял, просто взглянув на исходный код 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-----");
    }
}
...