Может ли кто-нибудь помочь мне реализовать расширение Subject Alternative Names с помощью BouncyCastle?

У меня есть строка, разделенная запятой. Я должен добавить все расширения, которые соответствуют любому расширению GeneralName for Subject Alternative Names. Кто-нибудь может закончить цикл за меня?

    @Override
public boolean saveKeypair(String arg0) {

    KeyPair keyPair = generateKeyPair(Integer.parseInt(access.getPublicKeyParameter()));

    PrivateKey privateKey = keyPair.getPrivate();
    PublicKey publicKey = keyPair.getPublic();

    X500Name name = new X500Name(access.getSubject());
    BigInteger serial = new BigInteger(access.getSerialNumber());
    Date notBefore = access.getNotBefore();
    Date notAfter = access.getNotAfter();
    X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(name, serial, notBefore, notAfter, name,
            publicKey);

    // BEGIN extensions
    // certificate policies
    boolean isCritPol = access.isCritical(3);
    PolicyInformation[] policies = new PolicyInformation[1];
    policies[0] = new PolicyInformation(new ASN1ObjectIdentifier("2.16.840.1.101.2.1.11.5"),
            new DERSequence(new PolicyQualifierInfo(access.getCpsUri())));
    try {
        certBuilder.addExtension(Extension.certificatePolicies, isCritPol, new CertificatePolicies(policies));
    } catch (CertIOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

    // END CP

    // subject alternative name
    List<GeneralName> altNames = new ArrayList<GeneralName>();
    String [] altSubNames = access.getAlternativeName(5);

    for(String altName : altSubNames){
        // I NEED THIS LOOP, AND I DON'T KNOW HOW TO DO IT
    }

    // END SAN

    // END extensions


    try {
        // Content Signer
        Security.addProvider(new BouncyCastleProvider());
        ContentSigner sigGen = new JcaContentSignerBuilder(signatureAlgorithm).setProvider(providerName)
                .build(privateKey);

        // Certificate
        X509Certificate certificate = new JcaX509CertificateConverter().setProvider(providerName)
                .getCertificate(certBuilder.build(sigGen));

     certificate.verify(publicKey);

        X509Certificate[] chain = new X509Certificate[1];       
        chain[0] = certificate;
        keyStore.setKeyEntry(arg0, privateKey, password.toCharArray(), chain);

    } catch (OperatorCreationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (CertificateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchProviderException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (SignatureException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (KeyStoreException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return true;
}

// BEGIN of functions for saveKeypair

public KeyPair generateKeyPair(int keySize) {
    KeyPair keyPair = null;

    try {
        KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(algorithm);
        keyGenerator.initialize(keySize);
        keyPair = keyGenerator.generateKeyPair();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

    return keyPair;
}



// END of functions for saveKeypair

В остальном функция работает.

Я использую BouncyCastle в Java. altSubName - это массив из нескольких строк. И эти строки должны быть как-то проверены, какие из SubjectAlternativeName они являются, и должно быть добавлено расширение, содержащее все эти общие имена.


person Isidora Bojovic    schedule 07.06.2017    source источник
comment
Может ли кто-нибудь закончить цикл for для меня?? Мы не являемся для вас средством удаленного программирования, доделайте его сами. Прекратите использовать StackOverflow в качестве ярлыка для вашей лени.   -  person t0mm13b    schedule 08.06.2017
comment
Я не ленив, я пробовал некоторые способы, которые не являются правильными. Я мог просто опубликовать свою неправильную функцию, и чем это будет нормально, вопрос? Мне действительно нужна помощь с этим. Потому что все, что я нашел в Интернете, касается добавления только одного альтернативного имени.   -  person Isidora Bojovic    schedule 08.06.2017
comment
У меня есть одна идея: использовать регулярное выражение и проверить тип альтернативного имени. Мне интересно, есть ли какое-нибудь лучшее решение?   -  person Isidora Bojovic    schedule 08.06.2017
comment
GeneralName может иметь множество различных типов (dnsName, ipAddress, rfc822name и т. д.), знаете ли вы, какими именно должны быть ваши строки? Вы сказали, что строки должны быть каким-то образом проверены, какие из SubjectAlternativeName они являются - есть ли у вас несколько примеров строк и как определяется их тип?   -  person    schedule 08.06.2017
comment
А какую версию BouncyCastle вы используете?   -  person    schedule 08.06.2017
comment
Это может быть любая строка. Я должен распознать, является ли строка dnsName, ipAddress, rfc822name и т. д., и добавить ее.   -  person Isidora Bojovic    schedule 08.06.2017


Ответы (1)


Согласно RFC 5280, некоторые поля Subject Alternative Расширение имени имеет определенный формат:

  • rfc822Name: формат определен в RFC 2821.
  • IP-адрес: определен в RFC 791.
  • dnsName: RFC 1034

И так далее (взгляните на ссылку RFC 5280, там очень подробно).

Итак, чтобы узнать, какое поле соответствует каждому String, вы должны проверить, имеют ли они формат, определенный в каждом из полей.

Для rfc822Name я нашел это регулярное выражение монстра:

String rfc822Regex = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])";
String s = "[email protected]";
if (s.matches(rfc822Regex)) {
    // is valid email
}

Для других полей вы можете искать регулярные выражения для каждого конкретного формата. Думаю, проблема только в поле otherName, потому что оно может иметь любой формат (его надо указывать для каждого центра сертификации):

OtherName ::= SEQUENCE {
    type-id    OBJECT IDENTIFIER,
    value      [0] EXPLICIT ANY DEFINED BY type-id }

В любом случае, общий код будет таким (при условии, что вы уже искали, как проверить каждый из конкретных форматов):

// check the format and add with the correct field type
if (isValidEmail(altName)) {
    altNames.add(new GeneralName(GeneralName.rfc822Name, "[email protected]"));
} else if (isValidDnsName(altName)) {
    altNames.add(new GeneralName(GeneralName.dNSName, "test.com"));
} else if (isValidIpAddress(altName)) {
    altNames.add(new GeneralName(GeneralName.iPAddress, "127.0.0.1"));
}
// ... and so on, for all GeneralName types

Затем вы добавляете расширение к certBuilder:

GeneralNames subjectAltNames = GeneralNames.getInstance(new DERSequence((GeneralName[]) altNames.toArray(new GeneralName[] {})));
certBuilder.addExtension(Extension.subjectAlternativeName, false, subjectAltNames);
person Community    schedule 08.06.2017
comment
Большое спасибо! знаете ли вы еще какое-нибудь регулярное выражение для некоторых других GeneralNames? - person Isidora Bojovic; 08.06.2017
comment
К сожалению, я не знаю, но его нетрудно найти (все они очень известные стандарты, может быть, они есть даже в BouncyCastle, но я не уверен). - person ; 08.06.2017