【问题标题】:How to parse SAN from CSR using java or bouncy castle?如何使用 java 或充气城堡从 CSR 解析 SAN?
【发布时间】:2014-08-18 09:24:04
【问题描述】:

我已经使用 openssl 生成了 CSR。现在我想解析 CSR 并显示 CSR 中可用的 ipaddress、Othername。

我编写了以下代码。它能够正确显示 dns、url 但我无法以正确的格式显示 ipaddress 和 othername。

  public static void testReadCertificateSigningRequest()  {
     String csrPEM = null;
     try {
      FileInputStream fis = new FileInputStream("E://test.txt");
      csrPEM = IOUtils.toString(fis);
     } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
     }  

PKCS10CertificationRequest csr = convertPemToPKCS10CertificationRequest(csrPEM);

X500Name x500Name = csr.getSubject();
System.out.println("x500Name is: " + x500Name + "\n");


 Attribute[] certAttributes = csr.getAttributes();
 for (Attribute attribute : certAttributes) {
     if (attribute.getAttrType().equals(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest)) {
         Extensions extensions = Extensions.getInstance(attribute.getAttrValues().getObjectAt(0));
         //Extension ext = extensions.getExtension(Extension.subjectAlternativeName);
         GeneralNames gns = GeneralNames.fromExtensions(extensions,Extension.subjectAlternativeName);
         GeneralName[] names = gns.getNames();
         for(int k=0; k < names.length; k++) {
             String title = "";
             if(names[k].getTagNo() == GeneralName.dNSName) {
                 title = "dNSName";
             }
             else if(names[k].getTagNo() == GeneralName.iPAddress) {
                 title = "iPAddress";
                 names[k].toASN1Object();
             }
             else if(names[k].getTagNo() == GeneralName.otherName) {
                 title = "otherName";
             }
             System.out.println(title + ": "+ names[k].getName());
         } 
     }
}

}


// Method to convert PEM to PKCS10CertificationRequest
private static PKCS10CertificationRequest convertPemToPKCS10CertificationRequest(String pem) {
    PEMParser pRd = new PEMParser(new StringReader(pem));
    org.bouncycastle.pkcs.PKCS10CertificationRequest csr = null;
    try {
        csr = (org.bouncycastle.pkcs.PKCS10CertificationRequest) pRd.readObject();
    } catch (IOException e) {
        e.printStackTrace();
    } 
    return csr;
}

上面的代码打印 iPAddress,otherName 如下:

iPA地址:#c0a80701 IP地址:#00130000000000000000000000000017 otherName: [1.2.3.4, [0]其他标识符]

我怎样才能以正确的格式检索 ipAdress 和 othername?

谢谢。

【问题讨论】:

  • 感谢您发布此示例代码。我在将 SAN 从 pkcs10 中拉出时遇到了问题,您的示例对我帮助很大......虽然我有点担心“attribute.getAttrValues().getObjectAt(0)”这一点

标签: bouncycastle


【解决方案1】:

这是“正确”的格式。正如其他答案所暗示的,除了手动转换之外别无他法。

BouncyCastle 在 GeneralName.java 类构造函数中对其进行内部编码。

  153           else if (tag == iPAddress)
  154           {
  155               byte[] enc = toGeneralNameEncoding(name);
  156               if (enc != null)
  157               {
  158                   this.obj = new DEROctetString(enc);
  159               }
  160               else
  161               {
  162                   throw new IllegalArgumentException("IP Address is invalid");
  163               }
  164           }

见: http://www.docjar.org/html/api/org/bouncycastle/asn1/x509/GeneralName.java.html

当您从 CSR 中提取 GeneralNames 以将它们合并到证书中时,BouncyCastle 还会再次对其进行解码,因此原始值最终会出现在最终证书中。

关于 otherName 属性: “对于 x400Address、otherName 和 ediPartyName,没有定义通用的字符串格式。” 所以那里没有“正确”的格式。

见: http://www.eecs.berkeley.edu/~jonah/javadoc/org/bouncycastle/asn1/x509/GeneralName.html

【讨论】:

    【解决方案2】:

    为了将 iPAddress 从十六进制格式转换为点格式,我找到了这个解决方案: Convert hexadecimal string to IP Address

    InetAddress a = InetAddress.getByAddress(DatatypeConverter.parseHexBinary(names[k].getName().toString().substring(1)));
    

    然后

    name = a.toString();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-19
      • 1970-01-01
      • 2017-08-21
      • 2015-04-26
      • 2018-06-07
      • 2013-04-20
      • 1970-01-01
      相关资源
      最近更新 更多