Pergunta

Eu estou tentando ler uma extensão personalizada de um certificado digital. Eu sei o valor é um GeneralString codificado em DER. Existe uma maneira fácil de decodificar corretamente e obter uma String Java? Eu tentei o seguinte, mas 's' inclui alguns dos metadados de codificação como caracteres lixo no início da cadeia.

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

Existe uma maneira rápida e fácil de fazer isso? Ou eu realmente precisa usar alguma biblioteca ASN.1 de pleno direito?

Obrigado!

Foi útil?

Solução

BouncyCastle é (entre tudo o resto):

Uma biblioteca para ler e escrever objetos ASN.1 codificados.

Outras dicas

Usando instruções contidas na página seguinte eu fiz algumas mudanças eo código funcionou bem para mim.

Portando a partir de versões anteriores BC para 1,47 e, mais tarde - A Legião do Castelo Bouncy http://www.bouncycastle.org/ wiki / display / JA1 / Portando + de + antes + BC + lançamentos + a + 1,47 + e + mais 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();
}

Este acaba por ser bastante simples com 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 faz o que as respostas acima fazer de uma maneira muito mais simples.

X509Certificate certificate;
byte[] encodedExtensionValue = certificate.getExtensionValue(oid);
if (encodedExtensionValue != null) {
    ASN1Primitive extensionValue = JcaX509ExtensionUtils
            .parseExtensionValue(encodedExtensionValue);
    String values = extensionValue.toString();          
}

No 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: A pergunta original pediu uma solução "rápida e suja", então eu acho que isso estava de volta válida então, mas uma vez que se baseia na API interna Sun, não deve ser mais utilizado especialmente desde JDK 9 em diante.

Bouncy Castle é a solução adequada para isso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top