【问题标题】:Can somebody help me to implement extension Subject Alternative Names using BouncyCastle?有人可以帮助我使用 BouncyCastle 实现扩展主题备用名称吗?
【发布时间】:2017-11-09 10:02:13
【问题描述】:

我有一些字符串,用逗号分隔。我必须为主题备用名称扩展添加与任何 GeneralName 匹配的所有扩展。有人可以帮我完成 for 循环吗?

    @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

该功能的其余部分正在工作。

我在 Java 中使用 BouncyCastle。 altSubName 是一个数组,由一些字符串组成。并且应该以某种方式检查这些字符串是哪个 SubjectAlternativeName,并且应该添加包含所有通用名称的扩展。

【问题讨论】:

  • 有人可以帮我完成 for 循环吗? 我们不是为您提供远程编程工具,请您自己完成。停止使用 StackOverflow 作为你懒惰的捷径。
  • 我并不懒惰,我尝试了一些不正确的方法。我可以只发布我不正确的功能,这不是问题吗?我真的需要这个帮助。因为我在 Internet 上找到的所有内容都是关于仅添加一个备用名称。
  • 我有一个想法,那就是使用正则表达式并检查备用名称的类型,如果有更好的解决方案,我很感兴趣?
  • GeneralName 可以有很多不同的类型(dnsName、ipAddress、rfc822name 等等),你知道你的字符串应该是什么吗?你说“应该以某种方式检查字符串它们是哪个 SubjectAlternativeName” - 你有一些字符串的例子以及它是如何决定它们的类型的吗?
  • 您使用的是哪个版本的 BouncyCastle?

标签: java certificate x509certificate bouncycastle subject-alternative-name


【解决方案1】:

根据RFC 5280Subject Alternative Name 扩展的某些字段具有定义的格式:

等等(看看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 = "test_ad.fade@mail.com";
if (s.matches(rfc822Regex)) {
    // is valid email
}

对于其他字段,您可以搜索每种特定格式的正则表达式。我认为唯一的问题是 otherName 字段,因为它可以具有 any 格式(必须为每个证书颁发机构指定):

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, "user@mail.com"));
} 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);

【讨论】:

  • 非常感谢!你知道其他一些通用名称的更多正则表达式吗?
  • 很遗憾,我不知道,但应该不难找到(它们都是众所周知的标准,甚至 BouncyCastle 都有,但我不确定)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-31
  • 1970-01-01
  • 1970-01-01
  • 2017-12-09
  • 1970-01-01
相关资源
最近更新 更多