//
// Created by MyPC on 2021/4/17.
//
#include <openssl/pem.h>
#include "rsaencode.h"
#include "include/openssl/nid.h"
#include "include/openssl/rsa.h"
#include "include/openssl/bn.h"
#include "include/openssl/bio.h"
#define LOG_TAG "WD_COLLECT"
#define LOGV(...)  __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__)
#include <android/log.h>
#include <mybase64.h>
char* myDecode( char *content, int size);
char* m_RSAPublicKey=(char*)"oq4FoqCv_kUJMz8qk4-dkrhvM-uNE-Fr5q4Foq4FvHCJ_4S8x4UvKkC6OMhuA5Pzk0mw6kmw_4K9hhnjOR_eOh6vZ5WsWrKmLhuXMauE_k1wq-nFK0hEUlTCMrSlZk-GcyWycHnMTk1MZHsVx-CCWRQ1huSwT57fhRnVxyrMAkPrM0EPAkFhc5FPLyUDAH1nc4SaOy7l6rUjTMkVW5nf6Qj0qeuW606yq-Fhxrhqo068GCJvc-rk6CWlkC_8xCTmh4gST98m_MkCAuunL-PEoCSoLh_0K5UWKHr8_M4Goq4FoqCrMHKdkuW8Er8hKHPJKD8o_hHFoq4FoK";
char* m_RSAPrivateKey="-----BEGIN RSA PRIVATE KEY-----\n"
                      "MIICXAIBAAKBgQDGPeXspW0p/3jfxg91F4fbXPVQWnJeE/ImIC8hxDaBx5gnh8LO\n"
                      "S2cGgKXBax0tTUmyvpTLuafVWaNaNFMZJWksixDm9cilKpKoYK8zWrCRvKO3Vode\n"
                      "fuYaXeifTIHxRylJVEf3wPkQaQE4EsEkwKEvFjot9MROec2GoSx/2Sok7wIDAQAB\n"
                      "AoGAVUDZWGPsBluvh8yNaTWtX1EizmOXO44oXO0KV+Mh7b4AWT+xLzaOH+XDYuLF\n"
                      "sW3De/Mp2lMFMmNSNMC729yS1anaawPhHu1NVjnXoNo/33TkUQ2ugAAeyO9p8ubx\n"
                      "ddSC4O7pKTY7y8MLm4tKFKdCsCvFGPq6K7E7KIuUNHhBKQECQQD+5evEmX/wKGBX\n"
                      "LsFcm6d7OfHQbbQh1ZUI+rz7YZLNNOlvsui22G0vYBkqaMRhtiudjl49geVth15x\n"
                      "UE8i9Py/AkEAxxlHgZZOAfz17sfHNj7T1NEez7bclnsvGCehyC9wqUDXe9o8K5Sq\n"
                      "gI51Y64MpesEyxkzxxJklZ86gpUyH+Jz0QJBAMIkZNqs/2Dvn9FHb0cV1w5oJ+HU\n"
                      "bKqIfqcEMwRUYPejIVlOLyl01lSLIR/IBCtYEQhD80ttsE0oGaq8vEmnxwkCQFxL\n"
                      "1r83G1CGoMehqzL1ayPUEbF+9sF3t3w+Gxx/CX4cxgfvQkd9spDH+ZlM/SYJTf6M\n"
                      "31jgqOpHl0sjuMnZI5ECQGNKd1Ozd7S65gPKjM9GP5nyXWHPcvIQQGBrUVRjuaeH\n"
                      "9/Edlnwh82mIYSjFYUt0PAyl2fo89OLWFWcvvI4cB1A=\n"
                      "-----END RSA PRIVATE KEY-----";
//这个函数 可以删除  只用于测试 生成公钥和私钥
void testWriteRSA2PEM()
{
    //生成密钥对
    RSA *r = RSA_new();
    int bits = 1024;
    BIGNUM *e = BN_new();
    BN_set_word(e, 65537);
    RSA_generate_key_ex(r, bits, e, NULL);


    BIO *out;
    out = BIO_new_file("/data/data/com.reyun.sdktestdemo/privateKey.pem","wb+");
    //这里生成的私钥没有加密，可选加密
    int ret = PEM_write_bio_RSAPrivateKey(out, r, NULL, NULL, 0, NULL, NULL);
    printf("writepri:%d\n",ret);
    BIO_flush(out);
    BIO_free(out);

    out = BIO_new_file("/data/data/com.reyun.sdktestdemo/publicKey.pem","wb+");
    ret = PEM_write_bio_RSAPublicKey(out, r);
    printf("writepub:%d\n",ret);
    BIO_flush(out);
    BIO_free(out);

    BN_free(e);
    RSA_free(r);

}
RSA * initPublicKey(char* publicKeyPath){
    RSA *pubkey = RSA_new();
    BIO *pubio;
    //获取公钥
    char* publicKey= myDecode(m_RSAPublicKey,strlen(m_RSAPublicKey));
    LOGV("测试代码->公钥解密后：%s",publicKey);
    pubio = BIO_new_mem_buf(publicKey,strlen(m_RSAPublicKey));
    free(publicKey);
//    pubio = BIO_new_file(publicKeyPath, "rb");
    if(pubio==NULL){
        RSA_free(pubkey);
        return NULL;
    }
    pubkey = PEM_read_bio_RSAPublicKey(pubio, &pubkey, NULL, NULL);
    BIO_free(pubio);
    return pubkey;
}

RSA * initPrivateKey(char* privateKeyPath){
    RSA *prikey = RSA_new();
    BIO *priio;
    //获取私钥
    priio = BIO_new_mem_buf(m_RSAPrivateKey, strlen(m_RSAPrivateKey));
//    priio = BIO_new_file(privateKeyPath, "rb");
    if(priio==NULL){
        RSA_free(prikey);
        return NULL;
    }
    prikey = PEM_read_bio_RSAPrivateKey(priio, &prikey, NULL, NULL);
    BIO_free(priio);
    return prikey;
}

int RSADecoder(RSA *pubkey,RSA *prikey,char* src,int src_Size,char*des,int* des_Size){
    if(pubkey== NULL||src== NULL||src_Size>128||des_Size== NULL){
        return 0;
    }
    //初始化变量
    unsigned char plain[128]= {0};
    unsigned char cipper[128]={0};
    size_t outl=128;
    memcpy(plain,src,src_Size);
    //打印源字符串的16进制
//    unsigned char temp[500]={0};
    LOGV("测试代码->RSA加密前：%s\n", plain);
    //进行加密
    outl=RSA_public_encrypt(strlen((char*)plain),plain,cipper,pubkey,RSA_PKCS1_PADDING);
    //打印密文字符串的16进制
    if(*des_Size<=outl*2||outl<128){
        return 0;
    }
    memcpy(des,cipper,outl);
    *des_Size=outl;
    //----------------------------------------
    //进行解密的测试代码
    char temp[500]={0};
    for(int i=0;i<outl;++i){
        char temp2[0x10]={0};
        sprintf(temp2,"%02x",cipper[i]);
        strcat((char *)(temp), (char *)(temp2));
    }
    LOGV("测试代码->加密后的二进制字符串: %s",temp);
    size_t outl2=0;
    unsigned char newplain[128]={0};
    outl2=RSA_private_decrypt(outl,cipper,newplain,prikey,RSA_PKCS1_PADDING);
    LOGV("测试代码->RSA加密后,重新私钥解密：%s", newplain);
    RSA_free(prikey);
    //------------------------------------------


    RSA_free(pubkey);
    return 1;
}



void rsa_Encoder_Base64(char *src,int src_len,char**out){
    if(src==NULL||src_len<=0||src_len>=128){
        return;
    }
    //读取文件获取公钥
    RSA *pubkey =initPublicKey("");
    if(pubkey==NULL){
        return;
    }
    RSA *prikey =initPrivateKey("");
    if(prikey==NULL){
        return;
    }
    //进行加密
    char result[500]={0};
    int outSize=sizeof(result);
    int flag= RSADecoder(pubkey,prikey,src,src_len,result,&outSize);
    if(flag>0){
        //------------BASE64 加密
        //计算加密后的长度
        int num=(outSize/3)*4;
        num=num + outSize % 3 ;
        //开始加密
        char *encode= (char*)(calloc(1,num+1));
        Base64Encode(result,outSize,encode);
        LOGV("测试代码->对RSA获取的密文进行Base64加密: %s ",encode);
        //传出结果
        *out=encode;

        //-----------------测试代码
        char *decode= (char*)(calloc(1,num+1));
        Base64Decode(encode,strlen(encode),decode);

        char temp[500]={0};
        for(int i=0;i<outSize;++i){
            char temp2[0x10]={0};
            sprintf(temp2,"%02x",decode[i]);
            strcat((char *)(temp), (char *)(temp2));
        }
        LOGV("测试代码->Base64解密->加密后的二进制字符串1: %s",temp);
        free(decode);
    }else{
        LOGV("加密失败");
    }
}

char* myDecode( char *content, int size){
    unsigned char table[]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,4,0,0,0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x36,0,0,0,0x39,0,0,0,0x26,0,0,0,0x1F,0,0,0,0x34,0,0,0,0x16,0,0,0,0x19,0,0,0,0x3C,0,0,0,1,0,0,0,0x33,0,0,0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1E,0,0,0,0x3E,0,0,0,0x35,0,0,0,0x32,0,0,0,8,0,0,0,0x2D,0,0,0,0xA,0,0,0,0x24,0,0,0,0x3A,0,0,0,9,0,0,0,0x10,0,0,0,0x1A,0,0,0,0x13,0,0,0,3,0,0,0,0xE,0,0,0,0x31,0,0,0,0,0,0,0,0x17,0,0,0,0x29,0,0,0,0xC,0,0,0,0x1D,0,0,0,0x2B,0,0,0,0xD,0,0,0,0x27,0,0,0,0x2E,0,0,0,0x18,0,0,0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x11,0,0,0,0xFF,0xFF,0xFF,0xFF,7,0,0,0,0x2A,0,0,0,0x1C,0,0,0,0x20,0,0,0,0x23,0,0,0,0x30,0,0,0,0x3D,0,0,0,0x15,0,0,0,0x3F,0,0,0,0x28,0,0,0,0x14,0,0,0,0x37,0,0,0,0x38,0,0,0,0x21,0,0,0,0xB,0,0,0,0x3B,0,0,0,0x12,0,0,0,5,0,0,0,0x2C,0,0,0,0xF,0,0,0,0x25,0,0,0,2,0,0,0,0x2F,0,0,0,0x1B,0,0,0,6,0,0,0,0x22,0,0,0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x41,0x41,0x41,0x41,0x42,0x33,0x4E,0x7A,0x61,0x43,0x31,0x79,0x63,0x32,0x45,0x41,0x41,0x41,0x41,0x44,0x41,0x51,0x41,0x42,0x41,0x41,0x41,0x42,0x41,0x51,0x44,0x48,0x53,0x47,0x49,0x70,0x41,0x32,0x78,0x66,0x54,0x4C,0x4A,0x4C,0x63,0x62,0x6B,0x74,0x43,0x33,0x47,0x70,0x78,0x37,0x73,0x6D,0x69,0x34,0x71,0x76,0x7A,0x75,0x6F,0x32,0x39,0x50,0x78,0x42,0x44,0x45,0x71,0x69,0x37,0x47,0x71,0x65,0x6B,0x37,0x63,0x6D,0x33,0x67};
    char* encode_str=content;
    char* bytes1=content;
    int num11=size%4;
    int num12=0;
    if(num11>0){
        num12=1;
    }
    int str_Size=(size/4+num12)*3+1;
    char*resultbyte=(char*)calloc(1,str_Size);
    memset(resultbyte,0,str_Size);
    int i=0;
    for ( i=0;i<size/4;++i){
        unsigned char byte_1=(unsigned char)bytes1[0+i*4];
        unsigned char  byte_2=(unsigned char)bytes1[1+i*4];
        unsigned char  byte_3=(unsigned char)bytes1[2+i*4];
        unsigned char  byte_4=(unsigned char)bytes1[3+i*4];
        int num= byte_1<<2;
        int num2=table[num];
        int R0=0;
        int R1=num2<<2;
        int R2=0xDC&R1;
        int R3=0X20;
        int R4=0x20&(~R1);
        R4=R4|R2;
        R2=table[byte_2<<2]/16;
        int R6=((0X3&R2)|0X20)^R4;
        resultbyte[0+i*3]=(char)R6;
        R1=table[byte_2<<2]*16;
        R3=(R1)&0xE0;
        R6=(0X19&(~R1))|R3;
        R3=table[byte_3<<2]/4;
        R0=0X6&R3;
        R3=~R3;
        R2=(((0X10|R3)&0X19)|R0)^R6;
        resultbyte[1+i*3]=(char)R2;
        R1=table[byte_3<<2]<<6;
        R2=table[byte_4<<2];
        R2=R2^R1;
        R0=R0&R1;
        R0=R0|R2;
        resultbyte[2+i*3]=(char)R0;
    }
    if(num12>0){
        int byte_1=-2;
        int byte_2=-2;
        int byte_3=-2;
        switch (num11){
            case 3:{
                byte_3=bytes1[size-1];
                byte_2=bytes1[size-2];
                byte_1=bytes1[size-3];
                break;
            }
            case 2:{
                byte_2=bytes1[size-1];
                byte_1=bytes1[size-2];
                break;
            }
            default:{

                return 0;
            }
        }
        int num= byte_1<<2;
        int num2=table[num];
        int R0=0;
        int R1=num2<<2;
        int R2=0xDC&R1;
        int R3=0X20;
        int R4=0x20&(~R1);
        R4=R4|R2;
        R2=table[byte_2<<2]/16;
        int R6=((0X3&R2)|0X20)^R4;
        resultbyte[0+(i)*3]=(char)R6;
        if(byte_3>-2){
            R1=table[byte_2<<2]*16;
            R3=(R1)&0xE0;
            R6=(0X19&(~R1))|R3;
            R3=table[byte_3<<2]/4;
            R0=0X6&R3;
            R3=~R3;
            R2=(((0X10|R3)&0X19)|R0)^R6;
            resultbyte[1+(i)*3]=(char)R2;
        }
    }



    return resultbyte;

}




