Java android上的libcurl CURLE\u SSL\u CACERT\u坏文件错误

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; }

所以我尝试将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;
}


//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,则文件格式错误。