Как декодировать строку в кодировке DER на Java?
Вопрос
Я пытаюсь прочитать собственное расширение из цифрового сертификата.Я знаю, что значение представляет собой GeneralString, закодированное в DER.Есть ли простой способ правильно его декодировать и получить строку Java?Я попробовал следующее, но 's' включает в себя некоторые метаданные кодировки в виде ненужных символов в начале строки.
byte[] ext = cert.getExtensionValue("1.2.3.4");
String s= new String(ext);
System.out.println(s);
Есть ли быстрый и простой способ сделать это?Или мне действительно нужно использовать какую-то полноценную библиотеку ASN.1?
Спасибо!
Решение
НадувнойЗамок это (среди всего остального):
Библиотека для чтения и записи закодированных объектов ASN.1.
Другие советы
Используя инструкции, содержащиеся на следующей странице, я внес некоторые изменения, и код у меня работал нормально.
Портирование с более ранних выпусков 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();
}
С 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();
}
JcaX509ExtensionUtils
делает то, что делают ответы выше, гораздо проще.
X509Certificate certificate;
byte[] encodedExtensionValue = certificate.getExtensionValue(oid);
if (encodedExtensionValue != null) {
ASN1Primitive extensionValue = JcaX509ExtensionUtils
.parseExtensionValue(encodedExtensionValue);
String values = extensionValue.toString();
}
В Oracle VM (JDK 7):
DerValue val = new DerValue(ext);
String s = val.getGeneralString();
http://www.docjar.com/docs/api/sun/security/util/DerValue.html
ПРИМЕЧАНИЕ:Первоначальный вопрос требовал «быстрого» решения, поэтому я думаю, что тогда это было справедливо, но, поскольку оно опирается на внутренний API Sun, его больше не следует использовать, особенно начиная с JDK 9.
Надувной замок – подходящее решение для этой проблемы.