如何在 Java 中解码 DER 编码的字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2409618/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I decode a DER encoded string in Java?
提问by Ragesh
I'm trying to read a custom extension from a digital certificate. I know the value is a GeneralString encoded in DER. Is there an easy way to correctly decode it and get a Java String? I tried the following, but 's' includes some of the encoding metadata as junk characters at the start of the string.
我正在尝试从数字证书中读取自定义扩展。我知道该值是在 DER 中编码的 GeneralString。有没有一种简单的方法可以正确解码它并获取 Java 字符串?我尝试了以下操作,但是 's' 在字符串的开头包含了一些作为垃圾字符的编码元数据。
byte[] ext = cert.getExtensionValue("1.2.3.4");
String s= new String(ext);
System.out.println(s);
Is there a quick and easy way to do this? Or do I really need to use some full fledged ASN.1 library?
有没有一种快速简便的方法来做到这一点?还是我真的需要使用一些成熟的 ASN.1 库?
Thanks!
谢谢!
采纳答案by Bozho
BouncyCastleis (among everything else):
BouncyCastle是(除其他外):
A library for reading and writing encoded ASN.1 objects.
用于读取和写入编码的 ASN.1 对象的库。
回答by Ragesh
This turns out to be quite straightforward with BouncyCastle:
事实证明,使用 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();
}
回答by agnoldo
Using instructions contained on the following page I've made some changes and the code worked fine with me.
使用下一页中包含的说明,我进行了一些更改,并且代码对我来说运行良好。
Porting from earlier BC releases to 1.47 and later - The Legion of the Bouncy Castlehttp://www.bouncycastle.org/wiki/display/JA1/Porting+from+earlier+BC+releases+to+1.47+and+later
从早期的 BC 版本移植到 1.47 及更高版本 - The Legion of the Bouncy Castle 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();
}
回答by varrunr
JcaX509ExtensionUtils
does what the answers above do in a much simpler way.
JcaX509ExtensionUtils
以更简单的方式完成上面的答案。
X509Certificate certificate;
byte[] encodedExtensionValue = certificate.getExtensionValue(oid);
if (encodedExtensionValue != null) {
ASN1Primitive extensionValue = JcaX509ExtensionUtils
.parseExtensionValue(encodedExtensionValue);
String values = extensionValue.toString();
}
回答by Jouni Aro
In Oracle VM (JDK 7):
在 Oracle VM (JDK 7) 中:
DerValue val = new DerValue(ext);
String s = val.getGeneralString();
http://www.docjar.com/docs/api/sun/security/util/DerValue.html
http://www.docjar.com/docs/api/sun/security/util/DerValue.html
NOTE: The original question called for a "quick-and-dirty" solution, so I think this was valid back then, but since it relies on the Sun internal API, it shouldn't be used anymore especially since JDK 9 onwards.
注意:最初的问题需要一个“快速而肮脏”的解决方案,所以我认为这在当时是有效的,但由于它依赖于 Sun 内部 API,因此不应再使用它,尤其是从 JDK 9 开始。
Bouncy Castle is the proper solution for this.
充气城堡是解决这个问题的正确方法。