【问题标题】:How I get a certificate list installed in Android 4.0?如何获取安装在 Android 4.0 中的证书列表?
【发布时间】:2012-02-25 20:00:26
【问题描述】:

android.security.KeyChain#getCertificateChain 需要一个别名。但我想安装所有 X509Certificate。

【问题讨论】:

    标签: android certificate x509


    【解决方案1】:

    您可以使用类似的方法列出受信任的证书。虽然没有完全记录,所以它可能会在未来的版本中中断。

    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());
    }
    

    【讨论】:

      【解决方案2】:

      列出可用的证书:

      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)。
      • @jww - 我们可以添加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}。这是因为证书不存在于真空中——发行者和主体之间存在关系。当事情横向发展时,它真的是一团糟。无论如何,很抱歉使讨论复杂化......
      • 您对比较两个证书之间的MD5SHAthumbprints有何看法?它会更精确。
      【解决方案3】:

      不能 - android.security.KeyChain 没有任何方法来检索所有别名,更重要的是 - 甚至没有与之通信的服务(IKeyChainService AIDL 接口的实现KeyChain 应用程序)公开了一个列出所有别名的方法 - 因此授权和密钥库是该应用程序的内部。

      【讨论】:

      • 谢谢。我有另一个问题。如何在 Android 上验证给定的 x509 证书?我可以使用系统上安装的证书或特定于我的应用程序的证书。
      猜你喜欢
      • 2016-07-22
      • 2023-01-05
      • 2011-05-26
      • 2014-01-27
      • 2018-11-16
      • 2012-05-19
      • 2022-12-13
      • 2011-01-27
      • 2012-08-21
      相关资源
      最近更新 更多