デジタル証明書からカスタム拡張機能を読み取ろうとしています。値がDERでエンコードされたGeneralStringであることはわかっています。正しくデコードしてJava文字列を取得する簡単な方法はありますか?次のことを試しましたが、「s」には文字列の先頭にジャンク文字としてエンコードメタデータの一部が含まれています。
byte[] ext = cert.getExtensionValue("1.2.3.4");
String s= new String(ext);
System.out.println(s);
これを行うための迅速で簡単な方法はありますか?それとも、本格的なASN.1ライブラリを使用する必要が本当にありますか?
ありがとう!
BouncyCastle は(他のすべての中で):
エンコードされたASN.1オブジェクトを読み書きするためのライブラリ。
次のページに含まれている手順を使用して、いくつかの変更を加えましたが、コードは正常に機能しました。
以前の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();
}
これは、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();
}
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以降は使用しないでください。
弾む城はこれに対する適切な解決策です。
JcaX509ExtensionUtils
は、上記の回答が行うことをはるかに簡単な方法で行います。
X509Certificate certificate;
byte[] encodedExtensionValue = certificate.getExtensionValue(oid);
if (encodedExtensionValue != null) {
ASN1Primitive extensionValue = JcaX509ExtensionUtils
.parseExtensionValue(encodedExtensionValue);
String values = extensionValue.toString();
}