如何存储和加载 cacerts.pem for gSoap-OpenSSL Android 应用程序
How to store and load cacerts.pem for gSoap-OpenSSL Android app
我正在开发一个C++Android应用程序,该应用程序使用gSOAP和OpenSSL。要启用 OpenSSL 以验证服务器证书,我需要为其提供cacerts.pem
文件的位置,否则所有 HTTPS 连接都将失败。
我的问题是:在Android上存储和加载cacerts.pem
的正确方法是什么?
-
我可以通过将
cacerts.pem
复制到APK根目录中,将其放置在src/resources
或res/raw/
或assets/
中。但是SSL_CTX_load_verify_locations(ctx, "cacerts.pem", nullptr)
找不到该文件。如何使OpenSSL能够读取APK中的PEM文件? -
有没有办法将
cacerts.pem
存储为字符串缓冲区,从而避免在APK中携带它?
我的应用需要与 SharePoint 联机网站通信(https://*.example.com/)
在Android上存储和加载cacerts.pem的正确方法是什么?
您必须加载验证主机证书所需的一个 CA。
您可以加载构建从主机到 CA 的路径所需的中间体,但这是可选的。配置良好的服务器将发送所需的中间证书,但并非所有中间证书都配置良好。
您不会加载cacert.pem
或等效项。 cacert.pem
包含数百个证书,除了一个证书外,所有证书都是错误的。
我是否需要以某种方式将cacerts.pem复制到.APK(如何做到这一点?)并提供文件的路径到SSL_CTX_load_verify_locations()?
不。您通常需要一个证书,即认证主机证书的 CA。它可以是公共CA,如Comodo,也可以是组织内部的私有CA。
您通常将其放在res/
或assets/
文件夹中。另请参阅 堆栈溢出上的/res 和/assets 目录之间的区别。
有没有办法将cacerts.pem存储为字符串缓冲区,从而避免将其携带在..APK?
是的,但您可能必须获取字符串,将其写入文件系统,然后将该文件用于SSL_CTX_load_verify_locations
。所以最后,最好把它放在 res/
或 assets/
.
。SharePoint Online sites (https://*.example.com/)
主机名验证的一个重要说明。OpenSSL 1.0.2 及更早版本不执行名称匹配。它执行其他常规检查,例如确保存在从最终实体证书(主机)到 CA 证书(信任根)的路径,并且证书未过期。但它不执行主机名匹配。
OpenSSL 1.1.0 确实执行主机名匹配。它将很快发布。
作为权宜之计,您通常会从像 cURL
这样的库中获取丢失的代码。 cURL 执行主机名匹配,Daniel Stenberg 很乐意分享代码。我认为它位于ssl.c
,如果没记错的话。
另请参阅 OpenSSL wiki 上的 TLS 客户端。
我终于能够让它工作了。我是一个完整的Android新手,所以在这里发布我的笔记,以防它们对像我这样的其他人有用。
正如@jww建议的那样,我将在发货前从我的cacerts.pem文件中删除所有不必要的证书。
我有 3 个选择将我的 cacerts.pem 放在 ..APK。
- 在根目录(将文件放在 src\main\resources 中(不是 src\main\res)将导致它被放置在 apk 的根目录) In res\raw
- (把文件放在 src\main\res\raw 中)
- 在资产中(将文件放在 src\main\assets 中)
在我的简短研究中,我找不到一种使用 c++ API 直接从 apk 根目录或从 res\raw 读取文件的方法。所以我继续#3。
现在资产文件也不能使用"标准"c++ 函数直接读取(如果我错了,请纠正我),所以我在 Java 层中使用此代码将文件从 assets 文件夹复制到外部位置。
try
{
AssetManager assetManager = this.getAssets();
File file = new File(getFilesDir(), "cacerts.pem");
InputStream in = assetManager.open("cacerts.pem");
OutputStream out = new FileOutputStream(file);
byte[] buffer = new byte[65536 * 2];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
out.flush();
out.close();
}
catch (Exception e)
{
}
在此之后,我将此文件位置传递给我的c ++代码,并能够进行此调用
SSL_CTX_load_verify_locations(ctx, "/data/user/0/com.company.app/files/cacerts.pem", NULL)
注意:这不是最终的生产代码。现阶段只是概念验证。请随时指出您看到的任何错误或您的建议。
注意:有一段时间 openssl 仍然无法读取文件,所以我验证了该文件是否已正确创建并使用 ifstream file("/data.../cacerts.pem") 可用,并且它就在那里。这个错误后来以某种方式解决了。
- 将TPM公钥序列化为DER或PEM
- SSLeay 读取 PEM 文件
- 如何使用openssl续订过期的证书密钥或创建自签名证书密钥any.pem Poco c ++
- C++/OpenSSL 将 PEM 加载到 STACK_OF(X509) 中
- 将 PFX 证书转换为 PEM 格式
- 如何在C++中将 JWK 公钥转换为 PEM 格式
- 使用密码将 RSA 私钥写入 PEM 文件
- 如何将cacert.pem与vs2015 curl项目一起包含,因此无需指定Cainfo curl选项
- 在C++中将 PEM 转换为 DER
- 如何使用OpenSSL API从其PEM格式字符串中读取RSA公钥
- 如何从连接的 SSL 会话获取 base64 编码证书 (PEM)
- 获得谷歌搜索 ssl pem 证书
- 带有SSL的libWebsocks服务器不输入PEM密码短语
- 如何存储和加载 cacerts.pem for gSoap-OpenSSL Android 应用程序
- 在 Windows CE 3 上将 PEM 转换为 DER
- 防止提示输入 PEM 密码
- curl_easy_setopt的默认路径是什么(卷曲、CURLOPT_CAINFO "cacert.pem");
- 使用 .pfx (pkcs12) 文件而不是 .pem 文件建立 SSL 连接的编程方式
- 如何使用WinCrypt和C++导入PEM格式的私钥
- 将windows存储中的私钥转换为PEM(适用于OpenSSL)