【发布时间】:2012-02-25 20:00:26
【问题描述】:
android.security.KeyChain#getCertificateChain 需要一个别名。但我想安装所有 X509Certificate。
【问题讨论】:
标签: android certificate x509
android.security.KeyChain#getCertificateChain 需要一个别名。但我想安装所有 X509Certificate。
【问题讨论】:
标签: android certificate x509
您可以使用类似的方法列出受信任的证书。虽然没有完全记录,所以它可能会在未来的版本中中断。
KeyStore ks = KeyStore.getInstance("AndroidCAStore");
ks.load(null, null);
Enumeration aliases = ks.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
X509Certificate cert = (X509Certificate)
ks.getCertificate(alias);
Log.d(TAG, "Subject DN: " +
cert.getSubjectDN().getName());
Log.d(TAG, "Subject SN: " +
cert.getSerialNumber().toString());
Log.d(TAG, "Issuer DN: " +
cert.getIssuerDN().getName());
}
【讨论】:
public void PrintInstalledCertificates( ){
try
{
KeyStore ks = KeyStore.getInstance("AndroidCAStore");
if (ks != null)
{
ks.load(null, null);
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements())
{
String alias = (String) aliases.nextElement();
java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate) ks.getCertificate(alias);
//To print System Certs only
if(cert.getIssuerDN().getName().contains(“system”))
{
System.out.println(cert.getIssuerDN().getName());
}
//To print User Certs only
if(cert.getIssuerDN().getName().contains(“user”))
{
System.out.println(cert.getIssuerDN().getName());
}
//To print all certs
System.out.println(cert.getIssuerDN().getName());
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (java.security.cert.CertificateException e) {
e.printStackTrace();
}
}
public boolean checkCACertificateInstalled(javax.security.cert.X509Certificate x509){
boolean isCACertificateInstalled = false;
try
{
String name = x509.getIssuerDN().getName();
KeyStore ks = KeyStore.getInstance("AndroidCAStore");
if (ks != null)
{
ks.load(null, null);
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements())
{
String alias = (String) aliases.nextElement();
java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate) ks.getCertificate(alias);
if (cert.getIssuerDN().getName().contains(name))
{
isCACertificateInstalled = true;
break;
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (java.security.cert.CertificateException e) {
e.printStackTrace();
}
return isCACertificateInstalled;
}
【讨论】:
{Distinguished Name, Serial Number} 对,而不仅仅是Distinguished Name。例如,请参阅超级用户上的 How to troubleshoot “Secure Connection Failed” in Firefox?。在该问题中,赛门铁克重新颁发了具有相同专有名称和相同主题公钥的证书。唯一不同的是序列号(以及从从属 CA 升级为自签名根 CA)。
cert.getSerialNumber().equals(x509.getSerialNumber()) 条件和cert.getIssuerDN().getName().contains(name) 来检查特定CA 的可用性。
{DN,SN} 匹配,我认为返回true 是合适的。我认为如果只有{DN} 匹配,warn 并可能返回true 是一个好主意,因为它可能是出乎意料的,比如重新颁发了证书。通常,“重新颁发的证书”很难追踪,因为它的使用规则很少有人知道。例如,{DN,SN} 的模糊规则在 RFC 4158, Certification Path Building 中。
{Issuer DN, SN} 使证书独一无二。所以也许更准确地说,它是三元组{Issuer DN, SN, Subject DN}。这是因为证书不存在于真空中——发行者和主体之间存在关系。当事情横向发展时,它真的是一团糟。无论如何,很抱歉使讨论复杂化......
你不能 - android.security.KeyChain 没有任何方法来检索所有别名,更重要的是 - 甚至没有与之通信的服务(IKeyChainService AIDL 接口的实现KeyChain 应用程序)公开了一个列出所有别名的方法 - 因此授权和密钥库是该应用程序的内部。
【讨论】: