web-dev-qa-db-ja.com

JavaでDERエンコードされた文字列をデコードするにはどうすればよいですか?

デジタル証明書からカスタム拡張機能を読み取ろうとしています。値がDERでエンコードされたGeneralStringであることはわかっています。正しくデコードしてJava文字列を取得する簡単な方法はありますか?次のことを試しましたが、「s」には文字列の先頭にジャンク文字としてエンコードメタデータの一部が含まれています。

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

これを行うための迅速で簡単な方法はありますか?それとも、本格的なASN.1ライブラリを使用する必要が本当にありますか?

ありがとう!

16
Ragesh

BouncyCastle は(他のすべての中で):

エンコードされたASN.1オブジェクトを読み書きするためのライブラリ。

7
Bozho

次のページに含まれている手順を使用して、いくつかの変更を加えましたが、コードは正常に機能しました。

以前のBCリリースから1.47以降への移植-弾む城の軍団http://www.bouncycastle.org/wiki/ display/JA1/Porting + from + Early + 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();
}
12
agnoldo

これは、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();
}
8
Ragesh

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に依存しているため、特にJDK9以降は使用しないでください。

弾む城はこれに対する適切な解決策です。

2
Jouni Aro

JcaX509ExtensionUtilsは、上記の回答が行うことをはるかに簡単な方法で行います。

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