代码之家  ›  专栏  ›  技术社区  ›  Ragesh

如何解码Java中的DER编码字符串?

  •  14
  • Ragesh  · 技术社区  · 16 年前

    我正试图从数字证书中读取自定义扩展名。我知道这个值是一个按顺序编码的generalstring。有一种简单的方法来正确解码它并获得Java字符串吗?我尝试了以下操作,但是“s”在字符串的开头包含了一些编码元数据作为垃圾字符。

    byte[] ext = cert.getExtensionValue("1.2.3.4");
    String s= new String(ext);
    System.out.println(s);
    

    有什么简单快捷的方法可以做到这一点吗?或者我真的需要使用一些成熟的ASN.1库吗?

    谢谢!

    5 回复  |  直到 7 年前
        1
  •  6
  •   Bozho    16 年前

    BouncyCastle 是(除其他外):

    用于读取和写入编码的ASN.1对象的库。

        2
  •  11
  •   agnoldo    13 年前

    使用下一页中的说明,我做了一些更改,代码运行良好。

    从公元前早期的版本移植到1.47及以后的版本-弹性城堡军团 http://www.bouncycastle.org/wiki/display/JA1/Porting+from+earlier+BC+releases+to+1.47+and+later

    private String getExtensionValue(X509Certificate X509Certificate, String oid) throws IOException
    {
        String decoded = null;
        byte[] extensionValue = X509Certificate.getExtensionValue(oid);
    
        if (extensionValue != null)
        {
            ASN1Primitive derObject = toDERObject(extensionValue);
            if (derObject instanceof DEROctetString)
            {
                DEROctetString derOctetString = (DEROctetString) derObject;
    
                derObject = toDERObject(derOctetString.getOctets());
                if (derObject instanceof ASN1String)
                {
                    ASN1String s = (ASN1String)derObject;
                    decoded = s.getString();
                }
    
            }
        }
        return decoded;
    }
    
    /**
     * From http://stackoverflow.com/questions/2409618/how-do-i-decode-a-der-encoded-string-in-java
     */
    private ASN1Primitive toDERObject(byte[] data) throws IOException
    {
        ByteArrayInputStream inStream = new ByteArrayInputStream(data);
        ASN1InputStream asnInputStream = new ASN1InputStream(inStream);
    
        return asnInputStream.readObject();
    }
    
        3
  •  8
  •   Ragesh    16 年前

    这对bouncyCastle来说非常简单:

    private String getExtensionValue(X509Certificate X509Certificate, String oid) throws IOException
    {
        String decoded = null;
        byte[] extensionValue = X509Certificate.getExtensionValue(oid);
    
        if (extensionValue != null)
        {
            DERObject derObject = toDERObject(extensionValue);
            if (derObject instanceof DEROctetString)
            {
                DEROctetString derOctetString = (DEROctetString) derObject;
    
                derObject = toDERObject(derOctetString.getOctets());
                if (derObject instanceof DERUTF8String)
                {
                    DERUTF8String s = DERUTF8String.getInstance(derObject);
                    decoded = s.getString();
                }
    
            }
        }
        return decoded;
    }
    
    private DERObject toDERObject(byte[] data) throws IOException
    {
        ByteArrayInputStream inStream = new ByteArrayInputStream(data);
        ASN1InputStream asnInputStream = new ASN1InputStream(inStream);
    
        return asnInputStream.readObject();
    }
    
        4
  •  2
  •   varrunr    13 年前

    JcaX509ExtensionUtils 以一种更简单的方式做上面的答案。

    X509Certificate certificate;
    byte[] encodedExtensionValue = certificate.getExtensionValue(oid);
    if (encodedExtensionValue != null) {
        ASN1Primitive extensionValue = JcaX509ExtensionUtils
                .parseExtensionValue(encodedExtensionValue);
        String values = extensionValue.toString();          
    }
    
        5
  •  2
  •   Jouni Aro    7 年前

    在Oracle虚拟机(JDK 7)中:

        DerValue val = new DerValue(ext);
        String s = val.getGeneralString();
    

    http://www.docjar.com/docs/api/sun/security/util/DerValue.html

    注意:最初的问题需要一个“快速而肮脏”的解决方案,所以我认为这在当时是有效的,但是由于它依赖于sun内部api,所以不应该再使用它,特别是在jdk 9以后。

    弹跳城堡是解决这个问题的正确方法。

    推荐文章