如何在 Java 中解码 DER 编码的字符串?
Posted
技术标签:
【中文标题】如何在 Java 中解码 DER 编码的字符串?【英文标题】:How do I decode a DER encoded string in Java? 【发布时间】:2011-01-25 11:04:20 【问题描述】:我正在尝试从数字证书中读取自定义扩展。我知道该值是用 DER 编码的 GeneralString。有没有一种简单的方法可以正确解码并获取 Java 字符串?我尝试了以下方法,但“s”在字符串开头包含一些编码元数据作为垃圾字符。
byte[] ext = cert.getExtensionValue("1.2.3.4");
String s= new String(ext);
System.out.println(s);
有没有快速简便的方法来做到这一点?还是我真的需要使用一些成熟的 ASN.1 库?
谢谢!
【问题讨论】:
【参考方案1】:使用下一页中包含的说明,我进行了一些更改,并且代码对我来说运行良好。
从早期的 BC 版本移植到 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://***.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();
【讨论】:
【参考方案2】:事实证明,这对于 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();
【讨论】:
嗨,看来 DERObject 已被弃用。您可以随时更新代码示例。认为您现在必须改用 org.bouncycastle.sasn1.Asn1Object,但我还不能让它工作。 @user1513388 抱歉,这是 2 年前的事了。我现在什至没有在任何事情上使用 Java,所以我不确定是否/何时可以再次尝试。 迟了,但是使用 ASN1Primitive 而不是 DerObject。请关注链接:bouncycastle.org/wiki/display/JA1/…【参考方案3】:JcaX509ExtensionUtils
以更简单的方式完成上述答案的工作。
X509Certificate certificate;
byte[] encodedExtensionValue = certificate.getExtensionValue(oid);
if (encodedExtensionValue != null)
ASN1Primitive extensionValue = JcaX509ExtensionUtils
.parseExtensionValue(encodedExtensionValue);
String values = extensionValue.toString();
【讨论】:
【参考方案4】:在 Oracle VM (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 开始以后。
Bouncy Castle 是解决此问题的正确方法。
【讨论】:
以上是关于如何在 Java 中解码 DER 编码的字符串?的主要内容,如果未能解决你的问题,请参考以下文章
Java中字节流如何转字符流,OutputStreamWriter用法