如何将OpenSSL指向Android设备上的根证书?
我已经设法交叉编译ARMv6的OpenSSL与the Android NDK一起使用,并让它在我的应用程序中运行。但是,尝试与知名主机(如https://google.com)建立HTTPS连接时,我总是收到错误“SSL证书无效”。如何将OpenSSL指向Android设备上的根证书?
但是,我在任何设备的浏览器(股票浏览器,Chrome,Firefox等)中显示安全页面并不困难。因此我只能假设OpenSSL没有找到存储在设备上的根证书。然后
我的问题分解成两个非常相关的子问题:
- 哪里的Android设备上存储的根证书?
- 我该如何将OpenSSL指向他们?
哪里的Android设备上存储的根证书?
它四处移动。随着冰淇淋三明治(ICS)的出现,使用了三家商店。这三个商店分别是/data/misc/keychain
(由Android提供),/data/misc/keychain/cacerts-added
(由用户添加的CA)和/data/misc/keychain/cacerts-removed
(CA由用户或更新删除)。
在ICS之前,他们使用位于/system/etc/security/cacerts.bks
的BouncyCastle商店。这是一个静态存储,无法修改。如果需要更改,则需要更新固件或映像。
有关商店的说明,请参见ICS Trust Store Implementation。它的Nikolay Elenkov的博客,他在讨论系统方面做得很好,而不仅仅是商店的位置。
我怎么可以指向OpenSSL的给他们?
你不能这么做,因为OpenSSL期望什么,Android呈现的是两种不同的表现/存储格式。 OpenSSL期望将PEM格式的信任锚集合在一起。但Android信任库不是这种格式。
通常会发生什么是您下载cacert.pem
。然后,通过指定cacert.pem
作为CAfile
参数,调用SSL_CTX_load_verify_locations
加载它们。
即使您从受信任的来源(例如Mozilla或cURL)下载cacert.pem
,仍应该通过它并确保您对信任锚的集合感到满意。有在包155个潜在的信任锚:
$ cat cacert.pem | grep BEGIN | wc -l
155
但是就像我在评论说,其隐含使用浏览器的安全模型,它不是一个特别好的办法做到的事情在许多情况下。
尝试建立HTTPS连接到公知的主机(如https://google.com),我总是收到错误时“SSL证书是无效的。”
要回答这个问题,只是使用Google Internet Authority或GeoTrust Global CA与SSL_CTX_load_verify_locations
。它可能是最好的使用Google互联网管理局,因为它限制了网络广播。
谷歌互联网管理局:
-----BEGIN CERTIFICATE-----
MIID8DCCAtigAwIBAgIDAjp2MA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
YWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTYxMjMxMjM1OTU5WjBJMQswCQYDVQQG
EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy
bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP
VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv
h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE
ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ
EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC
DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB5zCB5DAfBgNVHSMEGDAWgBTAephojYn7
qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD
VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwNQYDVR0fBC4wLDAqoCig
JoYkaHR0cDovL2cuc3ltY2IuY29tL2NybHMvZ3RnbG9iYWwuY3JsMC4GCCsGAQUF
BwEBBCIwIDAeBggrBgEFBQcwAYYSaHR0cDovL2cuc3ltY2QuY29tMBcGA1UdIAQQ
MA4wDAYKKwYBBAHWeQIFATANBgkqhkiG9w0BAQUFAAOCAQEAJ4zP6cc7vsBv6JaE
+5xcXZDkd9uLMmCbZdiFJrW6nx7eZE4fxsggWwmfq6ngCTRFomUlNz1/Wm8gzPn6
8R2PEAwCOsTJAXaWvpv5Fdg50cUDR3a4iowx1mDV5I/b+jzG1Zgo+ByPF5E0y8tS
etH7OiDk4Yax2BgPvtaHZI3FCiVCUe+yOLjgHdDh/Ob0r0a678C/xbQF9ZR1DP6i
vgK66oZb+TWzZvXFjYWhGiN3GhkXVBNgnwvhtJwoKvmuAjRtJZOcgqgXe/GFsNMP
WOH7sf6coaPo/ck/9Ndx3L2MpBngISMjVROPpBYCCX65r+7bU2S9cS+5Oc4wt7S8
VOBHBw==
-----END CERTIFICATE-----
GeoTrust的全球CA:
-----BEGIN CERTIFICATE-----
MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
-----END CERTIFICATE-----
在理想世界中,你运行一个私有PKI,和你只相信你PKI的根源在于认证网站和服务。您不要授予信任公共CA来证明任何事情,因为他们不对依赖方作任何保证。从本质上讲,公共CA告诉你他们的软件不好,即使他们卖给网站的目的也是如此。
在下一个最佳世界中,您只使用认证该网站的公共CA.这意味着您使用Google Internet Authority或GeoTrust Global CA来验证Google的资产;而不是,比如Diginotar。
还有其他不太容易出现的问题。 Google Internet Authority是无约束由GeoTrust认证的下属CA. Google可以为任何网站颁发证书,而不仅限于Google资产。通常情况下,RA会抓住这一点,RA实际上是一个独立的审计员,在签发之前验证对CA的签名请求。但在这种模式中,提出请求的组织(Google)与验证请求的组织(Google)是同一组织,而颁发证书的组织(Google)也是同一组织。浏览器,CA和PKI是我知道的唯一事例,独立审计师被彻底删除,作为一个制衡账号because it was too inconvenient。
如果你认为下属不会做这样的事情,那么你会很伤心地误会。 CNICC was just removed from a few browser trust stores,因为它的一个不受约束的下属被发现为其未被授权的网站和服务颁发证书。
如果浏览器的安全模型真的击穿了错误的CA能力来证明一个网站。它还包括对用户的成功钓鱼尝试。也就是说,浏览器会高兴地允许连接被拦截,因为用户被钓鱼了。
如果您认为即将推出的Public Key Pinning with Overrides会有所帮助,那么您会错误地误会。尽管他们几乎没有提到这些重叠,但攻击者可以打破已知的好针筒。更糟糕的是,报告功能已被禁用,因为一个破损的pinset与一个不必报告,所以浏览器是在掩盖同谋。
关于这个问题还有很多可用的阅读。对于初学者,请尝试Peter Gutmann的Engineering Security和AudunJøsang的Trust Extortion on the Internet。
- 哪里Android商店的根证书:
他们从周围版本根据有关添加证书在不同设备上本地密钥库的问题,负载迁移到版本和设备到设备。其中大多数需要设备被植根,随后的评论会谈论解决方案突破,因为他们在特定设备上移动或更改了格式。
- 我怎么可以指向OpenSSL的对他们说:
我不知道有一个“好”的方式,现在这样做的权利。我可以找到的最佳解决方法是this answer,然后将这些证书铲入openssl理解的您自己的应用程序专用存储中。
一个不完美的解决方案,但您可以使用的解决方案。
哪里Android商店的根证书:
体系证书:这些被存储在
System/etc/security/cacerts.bks
第三方证书:这些被存储在
data/misc/keystore
我怎么可以指向OpenSSL的对他们说:的this.You不必手动点它
与您的OpenSSL库结合了Android OS会照顾。
随着你给我写的信息在下面写。
考虑到您的应用程序是基于VPN或云的应用程序。
问题可能是由于您安装在设备中的无效SSL根CA检查SSL流量。
希望这有助于
哇 - 多么全面的答案 - 谢谢! – 2015-05-25 05:28:56