V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wiket
V2EX  ›  C

Android JNI 实现基于 openssl 的 RSA 私钥加密后密文长度问题

  •  
  •   wiket · 2017-08-02 11:22:23 +08:00 · 2261 次点击
    这是一个创建于 2681 天前的主题,其中的信息可能已经有所发展或是发生改变。

    openssl 版本 1.1.0f

    /**
     * 公钥加密
     * @param data
     * @param type 0 为默认,1 为使用的 key1 密钥对,2 为使用的 key2 密钥对
     * @return
     */
    std::string MyRSA::encryptRSA(const std::string& data, int *lenreturn, int type) {
    
        int ret, flen;
        BIO *bio = NULL;
        RSA *r = NULL;
        if(type == 2){
            bio = BIO_new_mem_buf((void *)PUBLICKEY_KEY2, -1);
        }else if(type == 1){
            bio = BIO_new_mem_buf((void *)PUBLICKEY_KEY1, -1);
        }else{
            bio = BIO_new_mem_buf((void *)PUBLICKEY, -1);
        }
    
        if (bio == NULL)       //从字符串读取 RSA 公钥
        {
            LOGE("BIO_new_mem_buf failed!\n");
        }
    
        r = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
    
        flen = RSA_size(r);
        lenreturn = &flen;
    
        LOGE("wiket test RSA encryptRSA:RSA_size %d", flen);
    
        static std::string text;
        text.clear();
    
        char *dst = NULL;
    
    
        dst = (char *) malloc(flen+1);
    
        memset(dst, 0, flen + 1);
        
        //RSA_PKCS1_PADDING 最大加密长度 为 128 -11
        //RSA_NO_PADDING 最大加密长度为  128
        ret = RSA_public_encrypt(flen - 11, 
        (unsigned char*)data.c_str(), 
        (unsigned char*)dst, r, RSA_PKCS1_PADDING);
        
        LOGE("wiket test RSA encryptRSA:after encryptChar_size %d", strlen(dst));
        text.assign(dst);
        LOGE("wiket test RSA encryptRSA:after encryptStr_size %d", text.length());
    
        RSA_free(r);
        BIO_free_all(bio);
    
        free(dst);
    
        CRYPTO_cleanup_all_ex_data(); //清除管理 CRYPTO_EX_DATA 的全局 hash 表中的数据,避免内存泄漏
    
        return  text;
    
    }
    

    然而通过上述函数加密得到的密文长度非固定 128 位
    请问大神们,如果需要最终得到的密文( dst )长度固定为 128 该如何实现?

    6 条回复    2017-08-08 10:22:39 +08:00
    RLib
        1
    RLib  
       2017-08-02 16:57:56 +08:00
    RSA1024 的话, 密文的长度就是固定的 RSA_size(r) = 128 bytes, 你这里对密文不要直接当成文本计算长度, 可以考虑 hexencode 或者 base64
    wiket
        2
    wiket  
    OP
       2017-08-02 17:32:46 +08:00
    @RLib 通过对密文进行 hexencode 和 base64encode 之后,很大的概率得到的 string 长度会不固定,这样子传给第三方无法进行 decode 后再进行解密了。
    仅仅密文长度是 128 的时候,经过 base64encode 或者 hexencode,给到第三方就能够解密
    gnaggnoyil
        3
    gnaggnoyil  
       2017-08-03 01:19:26 +08:00
    我不知道你是用什么观测方式得到结论密文长度不是 128 位的.但是如果你是通过在函数外部查看*lenreturn 的值来观测的话,我很明确地告诉你,你并没有观测到密文的长度——对 dangling pointer 解引用是未定义行为.
    wiket
        4
    wiket  
    OP
       2017-08-03 13:28:44 +08:00
    @gnaggnoyil 我是通过 strlen(dst)获取的长度
    按照我的理解,既然密钥是 128 位的,那么不考虑明文长度超长的情况下,应该每次通过 RSA_public_encrypt ()得到的密文长度应该是一致的呀。
    是否是我的代码里面的变量使用方式不对?
    请问有什么方式能保证我得到的 dst 或者 text 的长度是 128 位的吗?
    RLib
        5
    RLib  
       2017-08-03 14:50:57 +08:00
    @wiket 跟你说了对密文不要直接当成文本计算长度, strlen(dst)遇到\0 就结束了, 没有规定密文不能含有\0, 这是 bytes 不是 string, 另外 hexencode 是常规做法, 得到 256 长度文本
    wiket
        6
    wiket  
    OP
       2017-08-08 10:22:39 +08:00
    @RLib 找到问题所在了。

    ···
    text.assign(dst);
    ···
    替换为
    ···
    text.assign(dst,128);
    ···
    即可
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3170 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 12:57 · PVG 20:57 · LAX 04:57 · JFK 07:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.