• 非对称加密、解密原理及openssl中的RSA示例代码


    一、【原理简介】非对称加密

    非对称加密,也被称为公钥加密,其中使用一对相关的密钥:一个公钥和一个私钥。公钥用于加密数据,私钥用于解密数据。公钥可以公开分享,而私钥必须保密。

    1. 密钥生成:

      • 当一个用户或设备希望使用非对称加密时,要生成一对密钥:一个公钥和一个私钥。这两个密钥是数学上相关的,但从公钥中计算出私钥在计算上是不可行的。
    2. 加密过程:

      • 发送方使用接收方的公钥对消息进行加密。只有持有与那个公钥相对应的私钥的人(在这种情况下是接收方)才能解密这个消息。
    3. 解密过程:

      • 接收方使用其私钥对接收到的加密消息进行解密,以恢复原始消息。
    4. 安全性:

      • 即使攻击者知道公钥并且他们拦截了加密的消息,但由于他们没有私钥,所以他们不能解密那个消息。这提供了保密性。
      • 由于私钥不是公开的,因此无法用它来伪造加密的消息。
    5. 数字签名:

      • 除了保密性外,非对称加密还可以用于数字签名。发送方使用其私钥对消息的哈希进行加密,产生一个数字签名。
      • 接收方可以使用发送方的公钥来验证签名,确保消息是从发送方发出的,并且没有被修改。
    6. 主要算法:

      • RSA、ElGamal、ECC(椭圆曲线加密)是非对称加密的主要算法。
    7. 性能问题:

      • 与对称加密相比,非对称加密通常计算上更加昂贵,所以它在处理大量数据时可能不太实用。在实际场景中,经常使用非对称加密来交换一个对称密钥(如AES密钥),然后使用对称加密来加密实际的数据。
    8. 公钥基础设施(PKI):

      • PKI是一个结合硬件、软件、策略和标准,以实现公钥加密和数字签名服务的体系结构。它包括证书颁发机构(CA),负责颁发和验证数字证书。

    总结:非对称加密使用一对密钥来确保数据的安全性和完整性。公钥用于加密,而私钥用于解密或签名。


    二、【代码】生成秘钥对文件 和 读取秘钥对加密、加密

    • example 1 生成秘钥对
    #include 
    #include 
    #include 
    
    /* compile : gcc createRSA_KeyPair.c -I./include -L./lib -lcrypto -Wl,-rpath=./lib  */
    int main() {
        int ret = 0;
        RSA *r = NULL;
        BIGNUM *bne = NULL;
        int bits = 2048;
        unsigned long e = RSA_F4;
    
        // 1. 生成 RSA 密钥对
        bne = BN_new();
        ret = BN_set_word(bne, e);
        if(ret != 1) {
            goto free_all;
        }
    
        r = RSA_new();
        ret = RSA_generate_key_ex(r, bits, bne, NULL);
        if(ret != 1) {
            goto free_all;
        }
    
        // 2. 保存私钥到 PEM 文件
        FILE *fp = fopen("private_key.pem", "wb");
        if(fp == NULL) {
            perror("Unable to open private key file for writing");
            goto free_all;
        }
        PEM_write_RSAPrivateKey(fp, r, NULL, NULL, 0, NULL, NULL);
        fclose(fp);
    
        // 3. 保存公钥到 PEM 文件
        fp = fopen("public_key.pem", "wb");
        if(fp == NULL) {
            perror("Unable to open public key file for writing");
            goto free_all;
        }
        PEM_write_RSA_PUBKEY(fp, r);
        fclose(fp);
    
    free_all:
        RSA_free(r);
        BN_free(bne);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • example 2 使用秘钥对加密、解密
    #include 
    #include 
    #include 
    
    /* compile : gcc keyFromFile.c -I./include -L./lib -lcrypto -Wl,-rpath=./lib  */
    int main() {
        // 加载公钥
        FILE* pubKeyFile = fopen("public_key.pem", "rb");
        RSA* rsaPublicKey = PEM_read_RSA_PUBKEY(pubKeyFile, NULL, NULL, NULL);
        fclose(pubKeyFile);
    
        // 加载私钥
        FILE* privKeyFile = fopen("private_key.pem", "rb");
        RSA* rsaPrivateKey = PEM_read_RSAPrivateKey(privKeyFile, NULL, NULL, NULL);
        fclose(privKeyFile);
    
        const char* plainText = "Hello, OpenSSL!";
        char encrypted[4098] = {};
        char decrypted[4098] = {};
    
        // 使用公钥加密
        int encryptedLength = RSA_public_encrypt(strlen(plainText), (unsigned char*)plainText,
                                                 (unsigned char*)encrypted, rsaPublicKey, RSA_PKCS1_OAEP_PADDING);
        if (encryptedLength == -1) {
            printf("Public Encrypt failed \n");
            return 0;
        }
    
        // 使用私钥解密
        int decryptedLength = RSA_private_decrypt(encryptedLength, (unsigned char*)encrypted,
                                                  (unsigned char*)decrypted, rsaPrivateKey, RSA_PKCS1_OAEP_PADDING);
        if (decryptedLength == -1) {
            printf("Private Decrypt failed \n");
            return 0;
        }
        decrypted[decryptedLength] = '\0';
    
        printf("Original: %s\n", plainText);
        printf("Decrypted: %s\n", decrypted);
    
        RSA_free(rsaPublicKey);
        RSA_free(rsaPrivateKey);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    三、【代码】代码内生成秘钥对并加密解密

    • c风格
    #include 
    #include 
    #include 
    #include 
    
    /* compile : gcc RSA.c -I./include -L./lib -lcrypto -Wl,-rpath=./lib */
    int main() {
        // 1. create key
        int ret = 0;
        RSA *rsa = NULL;
        BIGNUM *bne = NULL;
        int bits = 2048;
        unsigned long e = RSA_F4;
        bne = BN_new();
        ret = BN_set_word(bne, e);
        if(ret != 1) {
            goto free_all;
        }
    
        rsa = RSA_new();
        ret = RSA_generate_key_ex(rsa, bits, bne, NULL);
        if(ret != 1) {
            goto free_all;
        }
    
        // 2. encrypto
        const char* plainText = "Hello, OpenSSL!";
        char encrypted[4098] = {};
        int encryptedLength = RSA_public_encrypt(strlen(plainText) + 1, (unsigned char*)plainText,
                                                 (unsigned char*)encrypted, rsa, RSA_PKCS1_OAEP_PADDING);
        if(encryptedLength == -1) {
            printf("Public Encrypt failed \n");
            goto free_all;
        }
    
        // 3. decrypto
        char decrypted[4098] = {};
        int decryptedLength = RSA_private_decrypt(encryptedLength, (unsigned char*)encrypted,
                                                  (unsigned char*)decrypted, rsa, RSA_PKCS1_OAEP_PADDING);
        if(decryptedLength == -1) {
            printf("Private Decrypt failed \n");
            goto free_all;
        }
        decrypted[decryptedLength] = '\0';
    
        printf("Original: %s\n", plainText);
        printf("Decrypted: %s\n", decrypted);
    
    free_all:
        RSA_free(rsa);
        BN_free(bne);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • C++风格
    #include 
    #include 
    #include 
    
    extern "C"{
    #include 
    #include 
    }
    
    class RSAWrapper {
    public:
        RSAWrapper() {
            rsa = RSA_new();
            bne = BN_new();
            BN_set_word(bne, RSA_F4);
            RSA_generate_key_ex(rsa, 2048, bne, nullptr);
        }
    
        ~RSAWrapper() {
            RSA_free(rsa);
            BN_free(bne);
        }
    
        std::vector<unsigned char> encrypt(const std::string &plainText) {
            std::vector<unsigned char> encrypted(RSA_size(rsa));
            int encryptLength = RSA_public_encrypt(plainText.size(),
                                                   reinterpret_cast<const unsigned char*>(plainText.c_str()),
                                                   encrypted.data(),
                                                   rsa,
                                                   RSA_PKCS1_OAEP_PADDING);
            if (encryptLength == -1) {
                throw std::runtime_error("Error during encryption");
            }
            return encrypted;
        }
    
        std::string decrypt(const std::vector<unsigned char> &cipherText) {
            std::vector<unsigned char> decrypted(RSA_size(rsa));
            int decryptLength = RSA_private_decrypt(cipherText.size(),
                                                    cipherText.data(),
                                                    decrypted.data(),
                                                    rsa,
                                                    RSA_PKCS1_OAEP_PADDING);
            if (decryptLength == -1) {
                throw std::runtime_error("Error during decryption");
            }
            return std::string(reinterpret_cast<char*>(decrypted.data()));
        }
    
    private:
        RSA *rsa;
        BIGNUM *bne;
    };
    
    
    /* compile : g++ -std=c++11  RSA.cpp -I./include -L./lib -lcrypto -Wl,-rpath=./lib */
    int main() {
        try {
            RSAWrapper rsaWrapper;
            std::string plainText = "Hello, OpenSSL C++!";
            auto encrypted = rsaWrapper.encrypt(plainText);
            auto decrypted = rsaWrapper.decrypt(encrypted);
    
            std::cout << "Original Text: " << plainText << std::endl;
            std::cout << "Decrypted Text: " << decrypted << std::endl;
    
        } catch (const std::exception &e) {
            std::cerr << "Error: " << e.what() << std::endl;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
  • 相关阅读:
    zabbix基础环境部署
    Vue3学习——标签的ref属性
    25分钟详细解说c++搜索算法
    CSS常用函数补充(var、clac、blur、gradient)
    10:STM32------I2C通信
    mac输密码麻烦?一位数密码来了!
    华钜同创:亚马逊开店有哪些注意事项
    vue项目中定制化音频展示,wavesurfer.js基本使用
    Ansible中的角色使用
    Security的内容
  • 原文地址:https://blog.csdn.net/weixin_44328568/article/details/132888983