Home > Net >  C OpenSSL RSA encryption ignores non printable characters
C OpenSSL RSA encryption ignores non printable characters

Time:07-05

C ignores non printable bytes when trying to encode a byte array. The encoded result only contains the printable characters.

eg.: bytearray {0x41, 0x42, 0x43, 0x00, 0x01, 0x02, 0x03} would encrypt, and when decrypted (in c or c#), resulting bytes are {0x41, 0x42, 0x43}

It appears that 0x00 triggers EOF, and it ignores the rest of the array.

(note that keys in the code are for testing purposes)

#define _CRT_SECURE_NO_WARNINGS
#define OPENSSL_API_COMPAT 0x00908000L
#include <string>
#include <iostream>
#include <fstream>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <openssl/applink.c>
#include <openssl/pkcs7.h>


const char* private_key_filepath = "E:\\private_key.pem";
const char* public_key_filepath = "E:\\public_key.pem";
const char* filepathSha1 = "E:\\encrypted_SHA_1.bin";
const char* filepathSha256 = "E:\\encrypted_SHA256.bin";
const char* filepathSha512 = "E:\\encrypted_SHA512.bin";

RSA * createRSAWithFilename(const char * filename, bool isPublicKey)
{
    FILE * fp = fopen(filename, "r");

    if (fp == NULL)
    {
        printf("Unable to open file %s \n", filename);
        return NULL;
    }
    RSA *rsa = RSA_new();

    if (isPublicKey)
    {
        rsa = PEM_read_RSA_PUBKEY(fp, &rsa, NULL, NULL);
    }
    else
    {
        rsa = PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL);
    }

    fclose(fp);
    return rsa;
}

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

    return rsa;
}

int public_encrypt(unsigned char * data, int data_len, unsigned char * key, unsigned char *encrypted)
{
    //RSA * rsa = createRSAWithFilename(public_key_filepath, true);
    //https://groups.google.com/g/mailing.openssl.users/c/iv3lgFenxno
    RSA* rsa = createRSA(key, true);
    int result = RSA_public_encrypt(data_len, data, encrypted, rsa, RSA_PKCS1_OAEP_PADDING);
    return result;
}

int private_decrypt(unsigned char * enc_data, int data_len, unsigned char * key, unsigned char *decrypted)
{
    //RSA * rsa = createRSAWithFilename(private_key_filepath, false);
    RSA* rsa = createRSA(key, false);
    int  result = RSA_private_decrypt(data_len, enc_data, decrypted, rsa, RSA_PKCS1_OAEP_PADDING);
    return result;
}

void printLastError(const char *msg)
{
    char err[120];
    ERR_load_crypto_strings();
    ERR_error_string(ERR_get_error(), err);
    printf("%s ERROR: %s\n", msg, err);
}

int main()
{
    OpenSSL_add_all_digests();
    OpenSSL_add_all_algorithms();
    //https://groups.google.com/g/mailing.openssl.users/c/iv3lgFenxno
    /* ------------------ PUBLIC KEY ---------------------*/
    std::string strPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAthNIG6T4geicFrTBFJkFYvuL7NEVBktXx/g9vORQb0TtiUfa5AzwIykKUfinsvFWxijUEJNxNnsuvTDQGX9ntqr4xKhXkeqSDdQa61rmN76s0OceYBM3ZxQfhvjAwk9HXs/Dnt7XsaH30/SWbhKS16WJPw9aZE2qfJ2JVO0ph89PEkujoCZpo0Q5RiZgbwwqYTghJvP/24Uz9VA/5Ee4thvrs5wyLuP3c3fpkrPZBN9oedcOk9gIs67G3J9ReVwVAdNdwApGLmXuVDD5YVA/A5dqWzrKY0fWw6L41QZRxkZYM8ZhTo4wOxYNqrPXxiAaMgGv6OQmsZKHhNbny5amJQIDAQAB";
    int nPublicKeyLen = strPublicKey.size();      //strPublicKey by base64 Encoded public key string
    for (int i = 64; i < nPublicKeyLen; i  = 64)
    {
        if (strPublicKey[i] != '\n')
        {
            strPublicKey.insert(i, "\n");
        }
        i  ;
    }

    strPublicKey.insert(0, "-----BEGIN PUBLIC KEY-----\n");
    strPublicKey.append("\n-----END PUBLIC KEY-----\n");
    char *chPublicKey = const_cast<char *>(strPublicKey.c_str());

    /* ------------------ PRIVATE KEY ---------------------*/
    std::string strPrivateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC2E0gbpPiB6JwWtMEUmQVi 4vs0RUGS1fH D285FBvRO2JR9rkDPAjKQpR Key8VbGKNQQk3E2ey69MNAZf2e2qvjEqFeR6pIN1BrrWuY3vqzQ5x5gEzdnFB G MDCT0dez8Oe3texoffT9JZuEpLXpYk/D1pkTap8nYlU7SmHz08SS6OgJmmjRDlGJmBvDCphOCEm8//bhTP1UD/kR7i2G uznDIu4/dzd mSs9kE32h51w6T2Aizrsbcn1F5XBUB013ACkYuZe5UMPlhUD8Dl2pbOspjR9bDovjVBlHGRlgzxmFOjjA7Fg2qs9fGIBoyAa/o5CaxkoeE1ufLlqYlAgMBAAECggEBALAG9C/FznvJ5x4Mop7HUe3gQ cwPKNZNASgew jrB/nA781OOpBl hmRRP60iauLLZnwp5D7bA Z3GBP69m/V4c7WUzW3Y20f2Mknn355r9PRa6WyOHcIi3a8ORusog219OflGaH 4cKP1B i1wx4a1A3tz3HAcpjbUF3GD2CLzKDBAYtsY2u6qxqv1qHw/0Ou3ZX5mzSaWpFCHD9IEhhtyWPN3nhis4rwTgTrMPIRcmec0NQbKK tT3aT6fOsz3bvGFJEIPbUSkZPAa 1yEjoH4H2 LETYSz5bpogMVEmw Kz Akswi2JD7 YWP YQd8xeo7Hi2X5H6/Bo7UTrSgECgYEA4PE1l79xJbrUSVgMsSzeodMJBEoDuyJCiVPblUM2TPFZtgEaciRdkGGOibK7NghcJZEa4mwFsw/LTCvIiRgJGSqiHXyft3p486KgzIXiWxMxcjUWdXIKxRS9B3bjN0aJkPaebilypputCDjlT776yOhwVTlM4w4USamJEAYnGHMCgYEAzzbm6BT1sYSZnNUIRtjFRSWuhqp28ewOpY8t8R8s/f /J1KBKXpyxMVo3kP9U4iQleZZy7kmbbsphRAo4EbAVFfSzRlosBI aC3eyV/2bM 2BhcFIbrqxhWogkpHcxreIFR3ZzZ8aoQyYuICGFVuYG1rqkN5vUx5KGzNuRKnWQcCgYEAgYqn4IJBuQbFJo/sj0RV2j/cm3m8eFKcmtWOSYFxjhIYJfawsjc7IuDr42To548c8g2EvAyVo69e1rkIPdt3seSZg/23RUTkzvpDPEWGPAjrmufzzSMmDKWKzveqlrSqmK9OQgbgng5dMbUCalCDwJwLxSjAnKoJCPr3kiDY9v0CgYA0yg/ZYD2Xk hug/cv1VmsXAUyWYsj5rd0hh12KDMWImlYYzR0lLVYW9JzjW6kMU5kYeLOe8TGf7/8HjnLqTqmQhl6FtcMxBkSAV2Yf9IPtnrw4jx0c2IMRMhBKRs6v8WHBv3EVaUsnbEYb uIt3r/JeEf50DEcQ8MtWtTkuT/UQKBgDWbR/tBuB3gAkH5SJUKJUMLY4/H0rHyX0OAx3gnuS2MlLxX Los03 slvhu5Mw//tWMIjE rVoJ80n2RIAvbI9YrRjZrYQvzOpmEFRRNtnhVo2maQxHoELE5zaJgr49IKzYIwrbrB9fezAd2a4qH JS3DdeVpKrFG5x9uzyyRYt";
    int nPrivateKeyLen = strPrivateKey.size();
    for (int i = 64; i < nPrivateKeyLen; i  = 64)
    {
        if (strPrivateKey[i] != '\n')
        {
            strPrivateKey.insert(i, "\n");
        }
        i  ;
    }
    strPrivateKey.insert(0, "-----BEGIN RSA PRIVATE KEY-----\n");
    strPrivateKey.append("\n-----END RSA PRIVATE KEY-----\n");
    char *chPrivateKey = const_cast<char *>(strPrivateKey.c_str());
    /* ------------------- [END] KEYS ----------------------*/

    char  encrypted[512] = {};
    unsigned char decrypted[512] = {};
    const char* plainText = "This is RSA test";
    //char plainText[]= {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
    SSL_CONF_CTX* ctx = SSL_CONF_CTX_new();
    SSL_CONF_cmd(ctx, "SignatureAlgorithms", "ECDSA SHA256:RSA SHA256:DSA SHA256");

    int encrypted_length = public_encrypt((unsigned char*)plainText, strlen(plainText), (unsigned char*)chPublicKey, (unsigned char*)encrypted);
    if (encrypted_length == -1)
    {
        printLastError("Public Encrypt failed ");
        exit(0);
    }
    printf("Encrypted length =%d\n", encrypted_length);

    /* Write to file */
    FILE* fp = fopen(filepathSha256, "wb");
    fwrite(encrypted, encrypted_length, 1, fp);
    fclose(fp);

    //https://stackoverflow.com/questions/59112701/sha512-c-program-using-the-openssl-library
    //https://stackoverflow.com/questions/2262386/generate-sha256-with-openssl-and-c
    //https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd_value_type.html

    //FILE* fp;
    //Get file size
    std::ifstream in_file(filepathSha256, std::ios::binary);
    in_file.seekg(0, std::ios::end);
    int file_size = in_file.tellg();
    printf("File length: %d\n", file_size);

    //read from the file and decrypt it.
    char fileContent[256] = {};
    fp = fopen(filepathSha256, "rb");
    RSA* rsa = createRSA((unsigned char*)chPrivateKey, false);
    fread(fileContent, file_size, 1, fp);

    int decrypted_length = private_decrypt((unsigned char*)fileContent, file_size, (unsigned char*)chPrivateKey, (unsigned char*)decrypted);
    if (decrypted_length == -1)
    {
        printLastError("Private Decrypt failed ");
        exit(0);
    }
    printf("Decrypted Text =%s\n", decrypted);
    printf("Decrypted Length =%d\n", decrypted_length);


    return 0;

}

CodePudding user response:

Here is your program in godbolt: https://godbolt.org/z/E6T1x8jT8

Notice:

Decrypted Text =ABC
Decrypted Length =7

This is because I changed:

int encrypted_length = public_encrypt((unsigned char*)plainText, strlen(plainText), (unsigned char*)chPublicKey, (unsigned char*)encrypted);

to:

int encrypted_length = public_encrypt((unsigned char*)plainText, 7, (unsigned char*)chPublicKey, (unsigned char*)encrypted);

In other words, strlen on {0x41, 0x42, 0x43, 0x00, 0x01, 0x02, 0x03} will return 3, with the result that you only encrypt the first three characters of the input.

CodePudding user response:

When trying to encode {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F} The result is:

14 6D BC C9 C0 AA B8 74 32 A2 1C E0 72 73 50 8E 2B 68 12 B9 42 1C C3 62 F8 80 63 BE A3 75 0E F2 F4 73 42 30 72 89 68 6F C3 B9 CC 7B A6 8F DB A6 70 1A 88 C7 C7 38 32 E5 34 F6 7B F0 76 23 0A D0 E6 90 C9 F8 48 C7 49 05 34 C0 54 D0 2B 4F DA D2 15 C7 82 BD 4B 71 80 C7 C8 39 F6 D7 58 33 FA 70 72 B5 12 B1 6F CF 38 63 7A 84 2C 43 4B 29 DA CD 77 B7 DD 98 3A 43 E1 FE 9F 74 8A 5B 55 71 8C C1 89 7E 09 6C 06 33 64 2A 85 FF D8 66 1B 30 58 6C CD B9 70 54 12 9C 98 9D D9 35 3E BB EC 08 FA B1 FD B8 7A 1E 64 0C A0 36 4D 83 5F D0 EB 51 06 F9 DA C2 0E 7D B2 1E BC 78 3B 81 E4 E3 DB 41 3D 6A 1F 56 0E C8 46 EC 3A 69 2E 1E DB E2 66 09 F3 7C A8 A3 B4 51 9B 6E 9F 65 64 CE D1 21 8F 9D A7 54 3B 81 7D 71 4E E6 8C 04 9D D9 CA 9B 8D 83 AD AC 13 27 9E 54 04 62 0B DE D7 F7 0F FA 07 D9 DA 52

However, the decoded bytes are empty, due to 0x00 at the beginning.

  • Related