我设法为ARMv6交叉编译OpenSSL以与the Android NDK一起使用,并让它在我的应用程序中运行。但是,在尝试与知名主机(例如https://google.com)建立HTTPS连接时,我始终收到错误“SSL证书无效。”
但是,我可以在任何设备的浏览器(股票浏览器,Chrome,Firefox等)中显示安全页面。因此,我只能假设OpenSSL没有找到存储在设备上的根证书。
然后我的问题分解为两个非常相关的子问题:
答案 0 :(得分:8)
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://google.com)建立HTTPS连接时,我始终收到错误“SSL证书无效。”
要回答这个问题,只需使用Google Internet Authority或GeoTrust Global CA与SSL_CTX_load_verify_locations
。最好使用 Google Internet Authority ,因为它限制了网络广播。
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 Global 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告诉您他们的warez不好,即使是他们将它们出售给站点的目的。
在下一个最好的世界中,您只使用认证该网站的公共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。更糟糕的是,对于带有 MUST NOT Report 的断开的pinset,报告功能被禁用,因此浏览器在掩盖中是同谋的。
有关该主题的更多阅读材料。首先,请尝试Peter Gutmann的Engineering Security和AudunJøsang的Trust Extortion on the Internet。
答案 1 :(得分:3)
根据将证书添加到不同设备上的本地密钥库的大量问题,他们从版本到版本以及设备到设备。其中大多数要求设备被植根,后来的评论谈论解决方案,因为他们在特定设备上移动或更改了格式。
我不确定现在是否有“好”的方法。我能找到的最佳解决方法是this answer,然后将这些证书铲入您自己的应用程序特定商店,openssl理解。
一个不完美的解决方案,但您可以使用它。
答案 2 :(得分:1)
android存储根证书的位置:
系统证书:这些证书存储在System/etc/security/cacerts.bks
ThirdParty证书:这些证书存储在data/misc/keystore
如何将openssl指向他们:
Android操作系统与你的openssl库一起处理这个问题。你不必手动指向它。
根据您提供的信息,我写在下面。
考虑到您的应用程序是VPN或基于云的应用程序。
问题可能是由于您在设备中安装了无效的SSL根CA 以检查SSL流量。
希望这有帮助