Rob*_*hou 13 openssl libcurl android-ndk
我在Android上用openssl-1.0.1h成功构建了libcurl-7.36.0.我运行了一个示例代码来测试HTTPS连接.默认情况下启用SSL_VERIFYPEER.Android上的证书路径是/ system/etc/security/cacerts,因此我将CURLOPT_CAPATH设置为/ system/etc/security/cacerts.
ls -l /system/etc/security/cacerts
-rw-r--r-- root root 4767 2012-09-22 11:57 00673b5b.0
-rw-r--r-- root root 4573 2012-09-22 11:57 03e16f6c.0
-rw-r--r-- root root 5292 2012-09-22 11:57 08aef7bb.0
......
Run Code Online (Sandbox Code Playgroud)
这是我的代码片段..
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "https://www.google.com:443");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); // default
curl_easy_setopt(curl, CURLOPT_CAPATH, "/system/etc/security/cacerts");
curl_easy_perform(curl);
Run Code Online (Sandbox Code Playgroud)
Curl始终返回错误:
== Info: SSL certificate problem: unable to get local issuer certificate
== Info: Closing connection 0
curl_easy_perform() failed: Peer certificate cannot be authenticated with given CA certificates
Run Code Online (Sandbox Code Playgroud)
它的工作,如果我请从CA包文件CA-bundle.crt http://curl.haxx.se/docs/caextract.html和curl_easy_setopt(curl, CURLOPT_CAINFO, "path:/ca-bundle.crt").
这是我的问题:有没有办法通过从/system/etc/security/cacerts手动下载CA捆绑文件并指定CURLOPT_CAINFO?来读取证书来使SSL对等验证工作?
CURL的示例实现使用TLS1.2,openSSL 1.01p,curl版本7.40.0,带验证对等的cacert.pem包,验证主机名选项显示在https://github.com/vyshas/CURL-Android-with-verify -peer-
以上链接的重要部分如下所示:
public native void setDir(String caCertDir);
setDir(saveCertPemFile());
private String saveCertPemFile()
{
Context context=getApplicationContext();
String assetFileName="cacert.pem";
if(context==null || !FileExistInAssets(assetFileName,context))
{
Log.i("TestActivity", "Context is null or asset file doesnt exist");
return null;
}
//destination path is data/data/packagename
String destPath=getApplicationContext().getApplicationInfo().dataDir;
String CertFilePath =destPath + "/" +assetFileName;
File file = new File(CertFilePath);
if(file.exists())
{
//delete file
file.delete();
}
//copy to internal storage
if(CopyAssets(context,assetFileName,CertFilePath)==1) return CertFilePath;
return CertFilePath=null;
}
private int CopyAssets(Context context,String assetFileName, String toPath)
{
AssetManager assetManager = context.getAssets();
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(assetFileName);
new File(toPath).createNewFile();
out = new FileOutputStream(toPath);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1)
{
out.write(buffer, 0, read);
}
in.close();
in = null;
out.flush();
out.close();
out = null;
return 1;
} catch(Exception e) {
Log.e("tag", "CopyAssets"+e.getMessage());
}
return 0;
}
private boolean FileExistInAssets(String fileName,Context context)
{
try {
return Arrays.asList(context.getResources().getAssets().list("")).contains(fileName);
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("tag", "FileExistInAssets"+e.getMessage());
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
JNIEXPORT void JNICALL Java_com_example_androidtest_TestActivity_setDir(JNIEnv*env,jobject obj,jstring caCertDir){if(!caCertDir)return;
JNIEXPORT void JNICALL Java_com_example_androidtest_TestActivity_setDir(JNIEnv* env, jobject obj, jstring caCertDir)
{
if(!caCertDir) return;
const char* caCertDir_c = env->GetStringUTFChars(caCertDir, NULL);
if (!caCertDir_c) return ;
const jsize len = env->GetStringUTFLength(caCertDir);
LOGI( "CaCertDir: %s", caCertDir_c );
std::string caCert(caCertDir_c,len);
caCertPtr=caCert;
LOGI( "CaCertDirptr in std string: %s", caCertPtr.c_str());
env->ReleaseStringUTFChars(caCertDir, caCertDir_c);
}
Run Code Online (Sandbox Code Playgroud)
}
CURL* curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
/* curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, TRUE);*/
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curlCallback);
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, downloadObject);
curl_easy_setopt(curl,CURLOPT_CAINFO,caCertPtr.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
curl_version_info_data * vinfo = curl_version_info( CURLVERSION_NOW );
if( vinfo->features & CURL_VERSION_SSL )
// SSL support enabled
LOGI("SSL support enabled");
else
{// No SSL
LOGI("NO SSL");
}
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK){
LOGI("CURL failed with error code %d", res);
}
LOGI("CURL download is OK, result:%d", res);
curl_easy_cleanup(curl);
return res == CURLE_OK;
Run Code Online (Sandbox Code Playgroud)
编辑:我之前的答案是错误的。
CURLOPT_CAPATH应指向使用c_hash工具为 OpenSSL 准备的目录。我不知道Android提供的格式是否相同。
我发现这个关于如何将新证书导入最近的 Android 的描述,它似乎表明该目录中的文件格式与 c_hash 所做的格式略有不同......
| 归档时间: |
|
| 查看次数: |
4441 次 |
| 最近记录: |