我已尝试使用此链接中提供的解决方案。
当我尝试读取 X.509 证书的主题替代名称时,出现以下错误
java.lang.NoSuchMethodError: org.bouncycastle.asn1.ASN1InputStream.readObject()Lorg/bouncycastle/asn1/DERObject;
在下面的代码行
ASN1InputStream 解码器 = new ASN1InputStream((byte[]) item.toArray());
DEREncodable 编码=解码器.readObject();
.der 文件用于创建证书,如下。
X509Certificate cert=null;
fis = new FileInputStream(file.getAbsoluteFile()); //.der file
bis = new BufferedInputStream(fis);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
while (bis.available() > 0) {
try{
cert = cf.generateCertificate(bis);
}
catch (CertificateException e) {
e.printStackTrace();
}
List list=getSubjectAlternativeNames((X509Certificate) cert);
下面是我从上面提到的链接得到的解决方案。
public static List<String> getSubjectAlternativeNames(X509Certificate certificate) {
List<String> identities = new ArrayList<String>();
try {
Collection<List<?>> altNames = certificate.getSubjectAlternativeNames();
// Check that the certificate includes the SubjectAltName extension
if (altNames == null)
return Collections.emptyList();
// Use the type OtherName to search for the certified server name
for (List item : altNames) {
Integer type = (Integer) item.get(0);
if (type == 0)
// Type OtherName found so return the associated value
try {
// Value is encoded using ASN.1 so decode it to get the server's identity
ASN1InputStream decoder = new ASN1InputStream((byte[]) item.toArray()[1]);
DEREncodable encoded = decoder.readObject();
encoded = ((DERSequence) encoded).getObjectAt(1);
encoded = ((DERTaggedObject) encoded).getObject();
encoded = ((DERTaggedObject) encoded).getObject();
String identity = ((DERUTF8String) encoded).getString();
// Add the decoded server name to the list of identities
identities.add(identity);
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
// log.error("Error decoding subjectAltName" + e.getLocalizedMessage(),e);
}
catch (Exception e) {
// log.error("Error decoding subjectAltName" + e.getLocalizedMessage(),e);
e.printStackTrace();
}
// Other types are not good for XMPP so ignore them
//log.warn("SubjectAltName of invalid type found: " + certificate);
}
}
catch (CertificateParsingException e) {
e.printStackTrace();
// log.error("Error parsing SubjectAltName in certificate: " + certificate + "\r\nerror:" + e.getLocalizedMessage(),e);
}
return identities;
}
是不是我没有使用正确的.jar文件?
我使用的.jar是--> bcprov-jdk16-1.45.jar建议我哪里出错了。
Internet Explorer -> Tools -> Internet Options -> Content -> Certificates -> Untrusted Publishers -> www.google.com
我将其导出为“.cer”,我对您的代码做了一些更改
public static List<String> getSubjectAlternativeNames(X509Certificate certificate) {
List<String> identities = new ArrayList<String>();
try {
Collection<List<?>> altNames = certificate.getSubjectAlternativeNames();
if (altNames == null)
return Collections.emptyList();
for (List item : altNames) {
Integer type = (Integer) item.get(0);
if (type == 0 || type == 2){
try {
ASN1InputStream decoder=null;
if(item.toArray()[1] instanceof byte[])
decoder = new ASN1InputStream((byte[]) item.toArray()[1]);
else if(item.toArray()[1] instanceof String)
identities.add( (String) item.toArray()[1] );
if(decoder==null) continue;
DEREncodable encoded = decoder.readObject();
encoded = ((DERSequence) encoded).getObjectAt(1);
encoded = ((DERTaggedObject) encoded).getObject();
encoded = ((DERTaggedObject) encoded).getObject();
String identity = ((DERUTF8String) encoded).getString();
identities.add(identity);
}
catch (UnsupportedEncodingException e) {
log.error("Error decoding subjectAltName" + e.getLocalizedMessage(),e);
}
catch (Exception e) {
log.error("Error decoding subjectAltName" + e.getLocalizedMessage(),e);
}
}else{
log.warn("SubjectAltName of invalid type found: " + certificate);
}
}
}
catch (CertificateParsingException e) {
log.error("Error parsing SubjectAltName in certificate: " + certificate + "\r\nerror:" + e.getLocalizedMessage(),e);
}
return identities;
}
我将文件保存到c:a1.cer
X509Certificate cert=null;
FileInputStream fis = new FileInputStream("c:\\aa1.cer");
BufferedInputStream bis = new BufferedInputStream(fis);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
if (bis.available() > 0)
try{
cert = (X509Certificate)cf.generateCertificate(bis);
}
catch (CertificateException e) {
e.printStackTrace();
}
System.out.println(CertificateInfo.getSubjectAlternativeNames(cert));
我得到的输出为 [www.google.com, google.com]
请检查您的证书,我认为问题出在您的证书上
GeneralName.dNSName
=
2
GeneralName.iPAddress
=
7
public static String[] parseHostNames(X509Certificate cert) {
List<String> hostNameList = new ArrayList<>();
try {
Collection<List<?>> altNames = cert.getSubjectAlternativeNames();
if (altNames != null) {
for(List<?> altName : altNames) {
if(altName.size()< 2) continue;
switch((Integer)altName.get(0)) {
case GeneralName.dNSName:
case GeneralName.iPAddress:
Object data = altName.get(1);
if (data instanceof String) {
hostNameList.add(((String)data));
}
break;
default:
}
}
}
System.out.println("Parsed hostNames: " + String.join(", ", hostNameList));
} catch(CertificateParsingException | IOException e) {
System.err.println("Can't parse hostNames from this cert.");
e.printStackTrace();
}
return hostNameList.toArray(new String[hostNameList.size()]);
}
注意: 接受的答案会检查 byte[]
,但不会在我的系统上编译。我通过调用
byte[]
找到了一些其他使用
new ASN1InputStream((byte[])data).readObject();
的示例,但我没有证书来测试它,所以我已将其从我的示例中删除。
bcprov-jdk15-1.46.jar
private String getOtherNameValue(X509Certificate certificate) {
final String method = "[getOtherNameValue] - ";
System.out.println(method + "START");
Collection<List<?>> altNames = null;
try {
altNames = certificate.getSubjectAlternativeNames();
} catch (CertificateParsingException e) {
e.printStackTrace();
}
if (altNames == null)
return "";
for (List item : altNames) {
Integer type = (Integer) item.get(0);
if (type == 0) {
try {
ASN1InputStream decoder = null;
if (item.toArray()[1] instanceof byte[])
decoder = new ASN1InputStream((byte[]) item.toArray()[1]);
if (decoder == null)
continue;
DEREncodable encoded = decoder.readObject();
encoded = ((DERSequence) encoded).getObjectAt(1);
encoded = ((DERTaggedObject) encoded).getObject();
encoded = ((DERTaggedObject) encoded).getObject();
String principalName = ((DERUTF8String) encoded).getString();
System.out.println(method + "END with principalName: " + principalName);
return principalName;
} catch (Exception e) {
System.out.println(method + "Exception decoding subjectAltName" + e.getLocalizedMessage());
e.printStackTrace();
}
}
}
System.out.println(method + "END");
return "";
}