Java android上的libcurl CURLE\u SSL\u CACERT\u坏文件错误
所以我尝试将libcurl与JNI一起使用,但它返回CURLE\u SSL\u CACERT\u BADFILE错误。这是我的密码 JNI端:Java android上的libcurl CURLE\u SSL\u CACERT\u坏文件错误,java,android,ssl,java-native-interface,libcurl,Java,Android,Ssl,Java Native Interface,Libcurl,所以我尝试将libcurl与JNI一起使用,但它返回CURLE\u SSL\u CACERT\u BADFILE错误。这是我的密码 JNI端: static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) { ((string*)userp)->append((char*)contents, size * nmemb); return size * nmemb; }
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
((string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
//jList is an array containing the certificate.
Java_packageName_MainActivity_Test(JNIEnv *env, jobject thiz, jobject jList)
{
vector<string> certificatesPinning;
// Convert jobject to jobjectArray
// retrieve the java.util.List interface class
jclass cList = env->FindClass("java/util/List");
// retrieve the toArray method and invoke it
jmethodID mToArray = env->GetMethodID(cList, "toArray", "()[Ljava/lang/Object;");
jobjectArray stringArray = (jobjectArray)env->CallObjectMethod(jList, mToArray);
// Add each certificate to the list
int stringCount = (env)->GetArrayLength(stringArray);
for (int i=0; i < stringCount; i++)
{
jstring certificateString = (jstring)(env)-> GetObjectArrayElement(stringArray, i);
const char *cert = (env)->GetStringUTFChars(certificateString, 0);
const jsize len = env->GetStringUTFLength(certificateString);
string certificatePinningObj(cert,len);
certificatesPinning.push_back(certificatePinningObj);
(env)->ReleaseStringUTFChars( certificateString, cert);
}
string readBuffer;
CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, "https://theapi.com");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);// Fill the response in the readBuffer
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 120); // 120 s connect timeout
curl_easy_setopt(curl, CURLOPT_ENCODING, GZIP);
curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"der");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER , 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST , 2L);
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
curl_easy_setopt(curl, CURLOPT_CAINFO,certificatesPinning[0].c_str());//buf
CURLcode res;
res = curl_easy_perform(curl);
if(!readBuffer.empty())
{
printf("success \n");
}
else
{
printf("error \n");
int a = (int)res;// this is 77 = CURLE_SSL_CACERT_BADFILE
}
}
// Define the function
native void Test(ArrayList<String> certificates);
// Prepare the certificate
ArrayList<String> certificatesPinning = new ArrayList<String>();
certificatesPinning.add(saveCertPemFile());
// Call the function
Test(certificatesPinning);
// Helpers
private String saveCertPemFile()
{
Context context=getApplicationContext();
String assetFileName="certificateName.der";
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;
}
静态大小写回调(void*contents、size\t size、size\t nmemb、void*userp)
{
((string*)userp)->追加((char*)内容,大小*nmemb);
返回大小*nmemb;
}
//jList是包含证书的数组。
Java_packageName_MainActivity_测试(JNIEnv*env、jobject thiz、jobject jList)
{
矢量认证;
//将jobject转换为jobjectArray
//检索java.util.List接口类
jclass cList=env->FindClass(“java/util/List”);
//检索toArray方法并调用它
jmethodID mToArray=env->GetMethodID(cList,“toArray”,“()[Ljava/lang/Object;”;
jobjectArray stringArray=(jobjectArray)env->CallObjectMethod(jList,mToArray);
//将每个证书添加到列表中
int stringCount=(env)->GetArrayLength(stringArray);
对于(int i=0;iGetObjectArrayElement(stringArray,i);
const char*cert=(env)->GetStringUTFChars(certificateString,0);
const jsize len=env->GetStringUTFLength(证书约束);
字符串证书(证书,len);
证书打印。推回(证书打印OBJ);
(环境)->发布StringUTFChars(证书约束,证书);
}
字符串读取缓冲区;
CURL*CURL=CURL_easy_init();
curl_easy_setopt(curl,CURLOPT_CUSTOMREQUEST,“POST”);
curl\u easy\u setopt(curl,CURLOPT\u URL,“https://theapi.com");
curl\u easy\u setopt(curl,CURLOPT\u WRITEFUNCTION,WriteCallback);//在readBuffer中填充响应
curl\u easy\u setopt(curl、CURLOPT\u WRITEDATA和readBuffer);
curl_easy_setopt(curl,CURLOPT_CONNECTTIMEOUT,120);//120秒连接超时
curl_easy_setopt(curl,CURLOPT_编码,GZIP);
curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,“der”);
curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,1);
curl_easy_setopt(curl,CURLOPT_SSL_VERIFYHOST,2L);
旋度设置(旋度、旋度、旋度、旋度);
curl_easy_setopt(curl,CURLOPT_CAINFO,certificatesPinning[0].c_str());//buf
卷曲编码;
res=旋度(curl)\u容易执行(curl);
如果(!readBuffer.empty())
{
printf(“成功”\n);
}
其他的
{
printf(“错误\n”);
int a=(int)res;//这是77=CURLE\u SSL\u CACERT\u BADFILE
}
}
JAVA端:
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
((string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
//jList is an array containing the certificate.
Java_packageName_MainActivity_Test(JNIEnv *env, jobject thiz, jobject jList)
{
vector<string> certificatesPinning;
// Convert jobject to jobjectArray
// retrieve the java.util.List interface class
jclass cList = env->FindClass("java/util/List");
// retrieve the toArray method and invoke it
jmethodID mToArray = env->GetMethodID(cList, "toArray", "()[Ljava/lang/Object;");
jobjectArray stringArray = (jobjectArray)env->CallObjectMethod(jList, mToArray);
// Add each certificate to the list
int stringCount = (env)->GetArrayLength(stringArray);
for (int i=0; i < stringCount; i++)
{
jstring certificateString = (jstring)(env)-> GetObjectArrayElement(stringArray, i);
const char *cert = (env)->GetStringUTFChars(certificateString, 0);
const jsize len = env->GetStringUTFLength(certificateString);
string certificatePinningObj(cert,len);
certificatesPinning.push_back(certificatePinningObj);
(env)->ReleaseStringUTFChars( certificateString, cert);
}
string readBuffer;
CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, "https://theapi.com");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);// Fill the response in the readBuffer
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 120); // 120 s connect timeout
curl_easy_setopt(curl, CURLOPT_ENCODING, GZIP);
curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"der");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER , 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST , 2L);
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
curl_easy_setopt(curl, CURLOPT_CAINFO,certificatesPinning[0].c_str());//buf
CURLcode res;
res = curl_easy_perform(curl);
if(!readBuffer.empty())
{
printf("success \n");
}
else
{
printf("error \n");
int a = (int)res;// this is 77 = CURLE_SSL_CACERT_BADFILE
}
}
// Define the function
native void Test(ArrayList<String> certificates);
// Prepare the certificate
ArrayList<String> certificatesPinning = new ArrayList<String>();
certificatesPinning.add(saveCertPemFile());
// Call the function
Test(certificatesPinning);
// Helpers
private String saveCertPemFile()
{
Context context=getApplicationContext();
String assetFileName="certificateName.der";
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;
}
//定义函数
原生孔隙测试(ArrayList证书);
//准备证书
ArrayList certificatesPinning=新的ArrayList();
certificatesPinning.add(saveCertPemFile());
//调用函数
测试(认证计划);
//助手
私有字符串saveCertPemFile()
{
Context=getApplicationContext();
字符串assetFileName=“certificateName.der”;
if(context==null | |!FileExistInAssets(assetFileName,context))
{
Log.i(“TestActivity”、“上下文为空或资产文件不存在”);
返回null;
}
//目标路径是data/data/packagename
字符串destPath=getApplicationContext().getApplicationInfo().dataDir;
字符串CertFilePath=destPath+“/”+assetFileName;
文件文件=新文件(CertFilePath);
if(file.exists())
{
//删除文件
delete();
}
//复制到内部存储器
if(CopyAssets(context,assetFileName,CertFilePath)==1)返回CertFilePath;
返回CertFilePath=null;
}
私有int-CopyAssets(上下文上下文、字符串assetFileName、字符串toPath)
{
AssetManager AssetManager=context.getAssets();
InputStream in=null;
OutputStream out=null;
试一试{
in=assetManager.open(assetFileName);
新建文件(toPath).createNewFile();
out=新文件输出流(toPath);
字节[]缓冲区=新字节[1024];
int-read;
while((read=in.read(buffer))!=-1)
{
输出。写入(缓冲区,0,读取);
}
in.close();
in=null;
out.flush();
out.close();
out=null;
返回1;
}捕获(例外e){
Log.e(“tag”、“CopyAssets”+e.getMessage());
}
返回0;
}
私有布尔FileExistInAssets(字符串文件名、上下文)
{
试一试{
返回Arrays.asList(context.getResources().getAssets().list(“”)。包含(文件名);
}捕获(IOE异常){
//TODO自动生成的捕捉块
Log.e(“tag”、“FileExistInAssets”+e.getMessage());
}
返回false;
}
“certificateName.der”是存储在资产文件夹中的证书
这是发送到jni的证书路径:
/data/data/packageName/certificateName.der
您还没有完全解释您在这里使用的是什么,但我猜您下面有一个针对OpenSSL构建的libcurl。然后,该选项应该是使用PEM格式标识CA证书捆绑包的文件名。该捆绑包是您受信任CA的所有证书 您的描述听起来像是您有一个DER文件,但是您不能将DER与OpenSSL一起用于CA证书捆绑包
获得一个像样的CA包的一个常见方法是下载Firefox中包含的文件。基于我的另一个问题,那么我如何能够从iPhone发送相同的文件而不是从Android?在两个平台中使用相同的代码?你的意思是?这不是这个问题,所以在这里回答这个问题会很奇怪,但这似乎也使用了e如果使用OpenSSL,则文件格式错误。