hermetik
hermetik

Reputation: 115

libsodium crypto_box_seal_open failing

I am using the following function to create a sealed box using libsodium:

void encrypt_message(char *msg, char *enc_msg, int db_id)
{
    unsigned char pk[crypto_box_PUBLICKEYBYTES] = { '\0' };
    char key[BUFLEN] = { '\0' };

    db_man_get_contacts_public_key(db_id, key);

    sodium_hex2bin(pk, crypto_box_publickeybytes(), key, sizeof(key), 
                    NULL, NULL, NULL);

    crypto_box_seal(enc_msg, msg, sizeof(msg), pk);
}

After which, I convert the binary encrypted message to hex, for storage on disk, utilizing the following libsodium function

sodium_bin2hex(hex_cipher_text, sizeof(hex_cipher_text),
                       cipher_text, sizeof(cipher_text));

The hex_cipher_text is then stored in a SQLite3 database. When I retrieve the message for decryption, the call to libsodium fails with an error code of 1. My decryption function is as follows:

void decrypt_message(message *msg)
{
    unsigned char pk[crypto_box_SECRETKEYBYTES] = { '\0' };
    unsigned char pubkey[crypto_box_PUBLICKEYBYTES] = { '\0' };
    char key[BUFLEN] = { '\0' };
    unsigned char tmp[BUFLEN] = { '\0' };
    int dbg = 0;

    db_man_get_my_private_key(key);
    sodium_hex2bin(pk, crypto_box_secretkeybytes(), key, sizeof(key), NULL, NULL, NULL);

    memset(key, '\0', BUFLEN);

    db_man_get_my_public_key(key);
    sodium_hex2bin(pubkey, crypto_box_publickeybytes(), key, sizeof(key), 
                    NULL, NULL, NULL);

    sodium_hex2bin(tmp, sizeof(tmp), msg->enc_body, sizeof(msg- >enc_body), 
                NULL, NULL, NULL);

    if ((dbg = crypto_box_seal_open(msg->dec_body, tmp, sizeof(tmp), pubkey, pk) != 0))
    {
        fprintf(stderr, "Decryption failed!\nError code: %d\n\n", dbg);   
    }
}

Any advice would be greatly appreciated.

Updated

Following the advice of Frank Denis and DamV I have modified the previous encryption and decryption functions as follows; note the change from the sizeof() function call to the appropriate strlen() function call.


void encrypt_message(char *msg, char *enc_msg, int db_id)
{
    unsigned char pk[crypto_box_PUBLICKEYBYTES] = { '\0' };
    char key[BUFLEN] = { '\0' };

    db_man_get_contacts_public_key(db_id, key);

    sodium_hex2bin(pk, crypto_box_publickeybytes(), key, strlen(key), 
                    NULL, NULL, NULL);

    crypto_box_seal(enc_msg, msg, USR_MSG_MAX_LENGTH, pk);

}

void decrypt_message(message *msg)
{
    unsigned char pk[crypto_box_SECRETKEYBYTES] = { '\0' };
    unsigned char pubkey[crypto_box_PUBLICKEYBYTES] = { '\0' };
    char key[BUFLEN] = { '\0' };
    unsigned char tmp[BUFLEN] = { '\0' };
    int dbg = 0;

    db_man_get_my_private_key(key);
    sodium_hex2bin(pk, crypto_box_secretkeybytes(), key, strlen(key), 
                    NULL, NULL, NULL);

    memset(key, '\0', BUFLEN);

    db_man_get_my_public_key(key);
    sodium_hex2bin(pubkey, crypto_box_publickeybytes(), key, 
                    strlen(key), NULL, NULL, NULL);

    sodium_hex2bin(tmp, sizeof(tmp), msg->enc_body, strlen(msg->enc_body), 
                    NULL, NULL, NULL);

    if ((dbg = crypto_box_seal_open(msg->dec_body, tmp, 
        USR_MSG_MAX_LENGTH + crypto_box_SEALBYTES, pubkey, pk) != 0))
        {
            fprintf(stderr, "Decryption failed!\nError code: %d\n\n", dbg);

        }
}

Upvotes: 0

Views: 494

Answers (2)

Frank Denis
Frank Denis

Reputation: 1501

sizeof <pointer> returns a constant, the size of the pointer itself.

In your code sizeof(msg) will always return 4 or 8, no matter what the message size is.

sizeof(msg->enc_body) probably doesn't do what you want either.

If you are new to the C language, I'd recommend forgetting the sizeof keyword.

You rarely need it, and it's the main source of confusion, bugs and vulnerabilities in applications written by people new to the language.

The only thing you need to remember is that sizeof (<type>) or sizeof value always returns a constant.

Upvotes: 1

DamV
DamV

Reputation: 35

When I retrieve the message for decryption, the call to libsodium fails with an error code of 1

You mean it returns -1, right ?

I wonder if the issue can be with the size of the array which contains binary values. I mean if the size of the data stored in hexadecimal form is smaller than the buf you allocated to store it, you will loose the information of which part of the buf has actually been written to.

I am especially concerned about enc_body -> tmp. If the size of the binary data is smaller than BUFLEN, you will give to crypto_box_seal_open a buffer size bigger than the one you want to give. It will cause an issue with decryption, no ?

In practice I think you must recover the size of the data after calling hex2bin (it probably outputs it), then pass it to crypto_box_seal_open instead of sizeof(tmp) (aka BUFLEN).

Upvotes: 1

Related Questions