¿Cómo puedo descodificar una cadena codificada DER en Java?
Pregunta
Estoy intentando leer una extensión personalizada de un certificado digital. Sé que el valor es un GeneralString codificado en DER. ¿Hay una manera fácil de decodificar correctamente y obtener una cadena de Java? He intentado lo siguiente, pero 's' incluye algunos de los metadatos de codificación como caracteres basura en el inicio de la cadena.
byte[] ext = cert.getExtensionValue("1.2.3.4");
String s= new String(ext);
System.out.println(s);
¿Hay una manera rápida y fácil de hacer esto? O lo que realmente necesita utilizar alguna biblioteca completa ASN.1 hecho y derecho?
Gracias!
Solución
BouncyCastle es (entre todo lo demás):
Una biblioteca para la lectura y escritura codificada objetos ASN.1.
Otros consejos
El uso de las instrucciones contenidas en la página siguiente he hecho algunos cambios y el código trabajado bien para mí.
Trasladar desde versiones anteriores BC a 1,47 y más tarde - La legión del Castillo Hinchable http://www.bouncycastle.org/ wiki / pantalla / JA1 / Porting + de + + + BC anteriormente comunicados + a + 1,47 + y + tarde
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();
}
Esto resulta ser bastante sencillo con 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
hace lo que las respuestas anteriores hacen de una manera mucho más sencilla.
X509Certificate certificate;
byte[] encodedExtensionValue = certificate.getExtensionValue(oid);
if (encodedExtensionValue != null) {
ASN1Primitive extensionValue = JcaX509ExtensionUtils
.parseExtensionValue(encodedExtensionValue);
String values = extensionValue.toString();
}
En Oracle VM (JDK 7):
DerValue val = new DerValue(ext);
String s = val.getGeneralString();
http://www.docjar.com/docs /api/sun/security/util/DerValue.html
NOTA: La pregunta original pedido una solución "rápida y sucia", por lo que creo que esto era válido entonces, pero ya que se basa en la API interno de Sun, no debe utilizarse más especialmente desde JDK 9 en adelante.
Castillo Hinchable es la solución adecuada para esto.