美文网首页程序员
Linux下RSA的lua实现

Linux下RSA的lua实现

作者: voxer | 来源:发表于2018-02-28 14:48 被阅读524次

    硬件里带的是MIPS的Linux,里面安装了Luajit, 需要实现RSA的功能。分2部分来尝试:

    • 在CentOS下使用lua实现
    • 在MIPS下使用lua实现

    0. 下载openssl

    我们这里实现的RSA基于openssl,所以先下载openssl.
    在CentOS下下载openssl:

    $git clone git://git.openssl.org/openssl.git
    

    1. 编译openssl

    CentOS是使用云服务,自带了openssl,执行查询版本命令

    $openssl version
    OpenSSL 1.0.2k-fips  26 Jan 2017
    

    先考虑CentOS上交叉编译mips对应的so文件,先在下载的openssl根目录下执行config生成Makefile文件。

    $./Configure linux-mips32 no-asm shared --prefix=/root/luatest/openssl
    

    linux-mips32是因为我这边硬件的mips系统是32位,你需要选择自己正确的平台,支持的平台名称可以用./Configure LIST来查询.
    另外prefix表示最后编译出来的so文件保存的目录

    这个Makefile文件并不能直接用,需要修改:
    找到 CROSS_COMPILE=改成CROSS_COMPILE= CROSS_COMPILE= /root/luatest/mips-gcc/bin/mips-linux-gnu-

    其中 /root/luatest/mips-gcc/就是我这里安装交叉编译环境的根目录,开发者需要替换成自己的目录。

    最后再执行make

    $make
    $make install
    

    make成功后会在/root/luatest/openssl生成相应的不少文件,我们暂时只需要lib下的libcrypto.so,libcrypto.so.1.1,libssl.so,libssl.so.1.1

    2. RSA加解密的C实现

    在网上能找到很多种RSA的C实现,我这里用的是以下简单实现(通过 OpenSSL 调用)

    /*******************************************************************************************
     *
     *  Copyright (C) Ravishanker Kusuma / ecofast.  All Rights Reserved.
     *
     *  File: rsautils.c 
     *  Date: 2017/12/01
     *  Desc: RSA Encryption & Decryption utils with OpenSSL in C
     *
     *  Thks: http://hayageek.com/rsa-encryption-decryption-openssl-c/
     *
     *  Compilation Command: gcc rsautils.c -fPIC -shared -lssl -lcrypto -o librsa.so
     *******************************************************************************************/
    
    #include <openssl/pem.h>
    #include <openssl/ssl.h>
    #include <openssl/rsa.h>
    #include <openssl/evp.h>
    #include <openssl/bio.h>
     
    const int padding = RSA_PKCS1_OAEP_PADDING;
     
    int public_encrypt(unsigned char* data, int data_len, unsigned char* key, unsigned char* encrypted)
    {
        int ret = -1;
        BIO* keybio = BIO_new_mem_buf(key, -1);
        if (keybio != NULL)
        {
            RSA* rsa = NULL;
            rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
            if (rsa != NULL)
            {
                ret = RSA_public_encrypt(data_len, data, encrypted, rsa, padding);
                RSA_free(rsa);
            }
            BIO_free_all(keybio);
        }
        return ret;
    }
    
    int private_decrypt(unsigned char* enc_data, int data_len, unsigned char* key, unsigned char* decrypted)
    {
        int ret = -1;
        BIO* keybio = BIO_new_mem_buf(key, -1);
        if (keybio != NULL)
        {
            RSA* rsa = NULL;
            rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);
            if (rsa != NULL)
            {
                ret = RSA_private_decrypt(data_len, enc_data, decrypted, rsa, padding);
                RSA_free(rsa);
            }
            BIO_free_all(keybio);
        }
        return ret;
    }
    

    3. 编译RSAUtils.c

    示例自带了编译命令gcc rsautils.c -fPIC -shared -lssl -lcrypto -o librsa.so,我们这里编译需要注意以下几个改动。

    • gcc 改成 /root/luatest/mips-gcc/bin/mips-linux-gnu-gcc,因为是交叉编译
    • 需要吧openssl的h文件加到INCLUDE的path里,其中XXXX是你的openssl相关h文件所在的目录
    $export C_INCLUDE_PATH=XXXX:$C_INCLUDE_PATH
    
    • 需要把libcrypto.so,libcrypto.so.1.1,libssl.so,libssl.so.1.1 拷贝到/root/luatest/mips-gcc/lib/gcc/mips-linux-gnu/4.7.2 这样执行-l参数的时候才能找到libsssl.solibcrypto.so
      最后执行后会生成librsa.so是我们需要的文件。

    4. 通过lua调用RASUtils.c定义的2个函数

    上一步生成的librsa.so最终是需要发布到硬件的mips linux下才能验证,在这之前,我们先在CentOS下验证以下lua调用的过程。
    所以还需要再生成一个so文件,这个是针对CentOS的。命令就是:

    $gcc rsautils.c -fPIC -shared -lssl3 -lcrypto -o librsa_centos.so
    

    其中-lssl3 -lcrypt 是根据CentOS现有安装的openssl在/user/lib64下的libssl3.solibcrypto.so来决定的

    继续新建2个lua文件rsautils.lua和rsatest.lua,完全是拷贝过来的。

    local ffi = require('ffi')
    local rsa = ffi.load('./librsa.so')
    local basexx = require('basexx')
    
    local _M = {}
    
    ffi.cdef[[
    int public_encrypt(unsigned char * data,int data_len,unsigned char * key, unsigned char *encrypted);
    int private_decrypt(unsigned char * enc_data,int data_len,unsigned char * key, unsigned char *decrypted);
    
    int private_encrypt(unsigned char * data,int data_len,unsigned char * key, unsigned char *encrypted);
    int public_decrypt(unsigned char * enc_data,int data_len,unsigned char * key, unsigned char *decrypted);
    ]]
    
    local RSA_PUBLIC_KEY = [[-----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3bTBJNQJjY6u7Y5b2eOWws0yW
    CGuWPm6MGOSVan65wCrJa5p3q3sodQUDVPotjsknjLlje9E1F7Bx94ZuqTwkvAr6
    ieLkgbbeqTCzeJ0AryUXiF3auxFSPdpBoD6nxtEeN8bZwfa/IYzdKyKlbhiQbUMN
    qWgmxiPVwupwAML7RQIDAQAB
    -----END PUBLIC KEY-----]]
    
    local RSA_PRIV_KEY = [[-----BEGIN RSA PRIVATE KEY-----
    MIICXAIBAAKBgQC3bTBJNQJjY6u7Y5b2eOWws0yWCGuWPm6MGOSVan65wCrJa5p3
    q3sodQUDVPotjsknjLlje9E1F7Bx94ZuqTwkvAr6ieLkgbbeqTCzeJ0AryUXiF3a
    uxFSPdpBoD6nxtEeN8bZwfa/IYzdKyKlbhiQbUMNqWgmxiPVwupwAML7RQIDAQAB
    AoGAc4NXvUKc1mqWY9Q75cwNGlJQEMwMtPlsNN4YVeBTHjdeuqoBBQwA62GGXqrN
    QpOBKl79ASGghob8n0j6aAY70PQqHSU4c06c7UlkeEvxJKlyUTO2UgnjjIHb2flR
    uW8y3xmjpXAfwe50eAVMNhCon7DBc+XMF/paSVwiG8V+GAECQQDvosVLImUkIXGf
    I2AJ2iSOUF8W1UZ5Ru68E8hJoVkNehk14RUFzTkwhoPHYDseZyEhSunFQbXCotlL
    Ar5+O+lBAkEAw/PJXvi3S557ihDjYjKnj/2XtIa1GwBJxOliVM4eVjfRX15OXPR2
    6shID4ZNWfkWN3fjVm4CnUS41+bzHNctBQJAGCeiF3a6FzA/0bixH40bjjTPwO9y
    kRrzSYX89F8NKOybyfCMO+95ykhk1B4BF4lxr3drpPSAq8Paf1MhfHvxgQJBAJUB
    0WNy5o+OWItJBGAr/Ne2E6KnvRhnQ7GFd8zdYJxXndNTt2tgSv2Gh6WmjzOYApjz
    heC3jy1gkN89NCn+RrECQBTvoqFHfyAlwOGC9ulcAcQDqj/EgCRVkVe1IsQZenAe
    rKCWlUaeIKeVkRz/wzb1zy9AVsPC7Zbnf4nrOxJ23mI=
    -----END RSA PRIVATE KEY-----]]
    
    function _M.rsa_encrypt(plainText)
        local c_str = ffi.new("char[?]", 1024 / 8)
        ffi.copy(c_str, plainText)
        local pub = ffi.new("char[?]", #RSA_PUBLIC_KEY)
        ffi.copy(pub, RSA_PUBLIC_KEY)
        local cipherText = ffi.new("char[?]", 2048)
        local cipherLen = rsa.public_encrypt(c_str, #plainText, pub, cipherText)
        if cipherLen == -1 then
            return -1, nil
        end    
        return cipherLen, basexx.to_base64(ffi.string(cipherText, cipherLen))
    end
    
    function _M.rsa_decrypt(cipherLen, b64cipherText)
        local c_str = ffi.new("char[?]", cipherLen + 1)
        ffi.copy(c_str, basexx.from_base64(b64cipherText))
        local pri = ffi.new("char[?]", #RSA_PRIV_KEY)
        ffi.copy(pri, RSA_PRIV_KEY)
        local plainText = ffi.new("char[?]", 2048)
        local plainLen = rsa.private_decrypt(c_str, cipherLen, pri, plainText)
        if plainLen == -1 then
            return nil
        end    
        return ffi.string(plainText, plainLen)
    end
    
    return _M
    
    local rsautils = require('rsautils')
    
    local src_str = "my name is ecofast小0胡!!"
    local cipherLen, cipher = rsautils.rsa_encrypt(src_str)
    if cipherLen ~= -1 then
        local plain = rsautils.rsa_decrypt(cipherLen, cipher)    
        print("src text:", plain)
            
        print("=========================")
        local txt2 = rsautils.rsa_decrypt(128, "aeMIl3wyPP/DIJLudq49k1YeK9o6QhrScyjy2JHcJ7CmFOpQAmbwLxOe/rWigSYeWbAMUw2MB1KTIsool9zEuOSaoiZtgjfpDvf5g/MZUjPAmDofKVutG9xJNonVoK6usHKVcR7wozq/tJ8h/CUWyKGHnLgkxvU3ObbhLPm/wwI=")    
        print("src text2:", txt2)    
    end
    

    另外还有一个'basexx.lua'用于base64函数的。
    最后在CentOS上运行可以成功:

    $luajit rsatest.lua
    src text:   my name is ecofast小0胡!!
    =========================
    src text2:  my name is ecofast小0胡!!
    

    最后附上相关示例demo所有源码,以供参考!

    相关文章

      网友评论

        本文标题:Linux下RSA的lua实现

        本文链接:https://www.haomeiwen.com/subject/gxcmxftx.html