0%

openssl之RSA加解密

    OpenSSL不多介绍,RSA也不多介绍,这里就贴出公钥加密,私钥解密的分段加解密代码。

     特别说明的一点是RSA公钥和私钥的长度为1024,所以最对可以加密1024/8-11=117字节长度。代码如下:

#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/buffer.h>
#include <stdio.h>

const int PADDING = RSA_PKCS1_PADDING;
RSA *createRSA(unsigned char *key, int public_token)
{
    RSA *rsa = NULL;
    BIO *keybio;
    keybio = BIO_new_mem_buf(key, -1);
    if (keybio == NULL)
    {
        printf("Failed to create key BIO");
        return 0;
    }
    if (public_token)
    {
        rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
    }
    else
    {
        rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);
    }
    if (rsa == NULL)
    {
        printf("Failed to create RSA");
    }

    return rsa;
}

int public_key_encrypt(unsigned char *data, int data_len, unsigned char *key, unsigned char *encrypted)
{
    RSA *rsa = createRSA(key, 1);
    if (NULL == rsa)
    {
        return -1;
    }
    size_t res = RSA_size(rsa);
    int block_len = res - 11;

    int pos = 0;



    unsigned char* temp = (unsigned char*)malloc(res+1);
    if (temp == NULL) {
        return -1;
    }

    unsigned char* outData = (unsigned char*)malloc(res+1);
    if (outData == NULL) {
        return -1;
    }

    int totalSize = 0; 
    while (pos < data_len) {
        memset(temp, 0, res+1);
        int size = min(block_len, data_len - pos);
        memcpy(temp, data + pos, size);

        memset(outData, 0, res+1);
        int result = RSA_public_encrypt(strlen(temp), temp, outData, rsa, PADDING);
        printf("%s\n",temp);
        if (result >  0) {
            memcpy(encrypted + totalSize, outData, result);
            pos += block_len;

            totalSize += result;
        }
        else {

            free(temp);
            free(outData);
            return -1;
        }

    }

    free(temp);
    free(outData);
    return totalSize;
}

int private_key_decrypt(unsigned char *enc_data, int data_len, unsigned char *key, unsigned char *decrypted)
{
    RSA *rsa = createRSA(key, 0);
    if (NULL == rsa)
    {
        return -1;
    }
    size_t res = RSA_size(rsa);

    int pos = 0;
    int i = 0;
    int totalSize = 0;

    unsigned char* temp = (unsigned char*)malloc(res + 1);
    if (temp == NULL) {
        return -1;
    }

    unsigned char* outData = (unsigned char*)malloc(res + 1);
    if (outData == NULL) {
        return -1;
    }
    while (pos < data_len) {
        memset(temp, 0, res + 1);
        int size = min(res, data_len - pos);
        memcpy(temp, enc_data + pos, size);

        memset(outData, 0, res + 1);
        int result = RSA_private_decrypt(strlen(temp), temp, outData, rsa, PADDING);

        if (result > 0) {

            memcpy(decrypted + totalSize, outData, result);
            pos += res;

            totalSize += result;

            printf("%s\n", decrypted);
        }
        else {
            return -1;
        }



    }

    return totalSize;
}

void ras_test()
{
    unsigned char plainText[] = "[oh-my-zsh] For safety, we will not load completions from these directories until[oh-my-zsh] you fix their permissions and ownership and restart zsh.oh-my-zsh] See the above list for directories with group or other writability.";

    unsigned char publicKey[] = "-----BEGIN PUBLIC KEY-----\n"
        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrPgCMJW17JN2DW7tZFk/FB6pU\n"
        "pLvLOo6G/EuND8XZptffXbyiY2VscMRhP+kKVeaLO9HuEYR3Zl78x8oR6prytstc\n"
        "/MueersWDxh4iGSHsZXGxA41hXrXLRElrSTRc43ea18o0zMxZoVZiR2JFt7QcgM+\n"
        "T6eOrvj59MhXv9O46QIDAQAB\n"
        "-----END PUBLIC KEY-----\n";

    unsigned char privateKey[] = "-----BEGIN RSA PRIVATE KEY-----\n"
        "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKs+AIwlbXsk3YNb\n"
        "u1kWT8UHqlSku8s6job8S40Pxdmm199dvKJjZWxwxGE/6QpV5os70e4RhHdmXvzH\n"
        "yhHqmvK2y1z8y556uxYPGHiIZIexlcbEDjWFetctESWtJNFzjd5rXyjTMzFmhVmJ\n"
        "HYkW3tByAz5Pp46u+Pn0yFe/07jpAgMBAAECgYBj1YH8MtXhNVzveEuBZMCc3hsv\n"
        "vdq+YSU3DV/+nXN7sQmp77xJ8CjxT80t5VS38dy2z+lUImJYOhamyNPGHkC2y84V\n"
        "7i5+e6ScQve1gnwHqRKGBjtSCaYOqm9rTDECCTT1oMU26sfYznWlJqMrkJp1jWn7\n"
        "aAwr+3FcX2XhD74ZAQJBAN34Y6fmHLRPv21MsdgGqUjKgyFvJfLUmtFFgb6sLEWc\n"
        "k22J3BAFAcNCTLYHFZwMhL/nwaw9/7rIUJD+lcl6n3cCQQDFfrN14qKC3GJfoBZ8\n"
        "k9S6F7Ss514DDPzIuenbafhoUjZDVcjLw9EmYZQjpfsQ3WdNICUKRrDHZay1Pz+s\n"
        "YkKfAkB+OKfaquS5t/t/2LPsxuTuipIEqiKnMjSTOfYsidVnBEFlcZZc2awF76aV\n"
        "f/PO1+OJCO2910ebXBtMSCi++GbDAkEAmc7zNPwsVH4OnyquWJdJNSUBMSd/sCCN\n"
        "PkaMOrVtINHmMMq+dvMqEBoupRS/U4Ma0JYYQsiLJL+qof2AOWDNQQJAcquLGHLT\n"
        "eGDDLluHo+kkIGwZi4aK/fDoylZ0NCEtYyMtShQ3JmllST9kmb9NJX2gMsejsirc\n"
        "H6ObxqZPbka6UA==\n"
        "-----END RSA PRIVATE KEY-----\n";

    unsigned char encrypted_str[1024];
    unsigned char decrypted_str[1024];


    memset(encrypted_str, '\0', sizeof(encrypted_str));
    memset(decrypted_str, '\0', sizeof(decrypted_str));

    size_t len = strlen((const char *)plainText);
    printf("Original string length =%d\n\n", len);

    // 公钥加密
    int encrypted_length = public_key_encrypt(plainText, len, publicKey, encrypted_str);
    if (-1 == encrypted_length)
    {
        printf("Private Encrypt failed\n");
        exit(0);
    }
    encrypted_str[encrypted_length] = '\0';



    // 私钥解密
    int decrypted_length = private_key_decrypt(encrypted_str, encrypted_length, privateKey, decrypted_str);
    if (-1 == decrypted_length)
    {
        printf("Public Decrypt failed\n");
        exit(0);
    }

    printf("Decrypted Text =%s\n\n", decrypted_str);
    printf("Decrypted Length =%d\n", decrypted_length);
}

代码下载