0

I always lose part of the last , here's my code and even when it uses scrypt, that part just works fine, I've tested the hashing with even more than 500 bytes.

So I produce a 32 bytes hash (for AES256) a 16 bytes iv and a 16 bytes salt, and of course the length of my encrypted text which would be saved in the beggining in this order.

1......... 16.. 16.. 16*x
[length][salt][iv][encrypted data]

The length of the decrypted string is ok, but the problem is that long data doesn't decrypt totally, shorter data works totally well.

You can totally skip the scrypt part that is here, since it's been tested a lot and I don't think the error is there anyway since I see partial data.

#include <string.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/bio.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include "libscrypt.h"

#define VK_SCRYPT_N 16384
#define VK_SCRYPT_r 8
#define VK_SCRYPT_p 1

#define VK_SCRYPT_HASH_LEN 32
#define VK_SCRYPT_SALT_LEN 16
#define VK_SCRYPT_LEN 48

int scryptencrypt(uint8_t* plaintext,size_t plaintext_l,uint8_t* password,size_t password_l,uint8_t* cipher){
    int saltRet;
    int hashRet;

    uint8_t saltbuf[VK_SCRYPT_SALT_LEN];
    saltRet = libscrypt_salt_gen(saltbuf,VK_SCRYPT_SALT_LEN);

    if (saltRet == -1) {
        return 1;
    } else {

        uint8_t hashbuf[VK_SCRYPT_HASH_LEN];
        int hashRet = libscrypt_scrypt(password,password_l,saltbuf,
                VK_SCRYPT_SALT_LEN,VK_SCRYPT_N, VK_SCRYPT_r, VK_SCRYPT_p, hashbuf, VK_SCRYPT_HASH_LEN);

        if (hashRet != 0) {
            return 1;
        } else {

            unsigned char iv[AES_BLOCK_SIZE];
            int rand_st = RAND_bytes(iv, AES_BLOCK_SIZE);
            if (rand_st <= 0){
                return 1;
            }

            const size_t result_len = ((plaintext_l + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;

            unsigned char encrypted[result_len];
            memset(encrypted, 0, sizeof(encrypted));

            AES_KEY key;
            if(AES_set_encrypt_key((unsigned char*) &hashbuf, 256, &key) >= 0){

                memcpy(cipher, &plaintext_l,1);
                memcpy(cipher + 1, &saltbuf, VK_SCRYPT_SALT_LEN);
                memcpy(cipher + 1 + VK_SCRYPT_SALT_LEN, &iv, AES_BLOCK_SIZE);

                AES_cbc_encrypt(plaintext,encrypted,plaintext_l, (const AES_KEY *) &key, iv, AES_ENCRYPT);
                memcpy(cipher + 1 + VK_SCRYPT_SALT_LEN + AES_BLOCK_SIZE, &encrypted, result_len);

                return 0;
            } else {
                return 1;
            }
        }
    }
}

int scryptdecrypt(uint8_t* cipher,size_t cipher_l,uint8_t* password,size_t password_l,uint8_t* plaintext){

    uint8_t saltbuf[VK_SCRYPT_SALT_LEN];
    uint8_t hashbuf[VK_SCRYPT_HASH_LEN];
    unsigned char iv[AES_BLOCK_SIZE];

    uint8_t length = 0;
    memcpy(&length,cipher,1);
    memcpy(saltbuf,cipher + 1,VK_SCRYPT_SALT_LEN);
    memcpy(iv,cipher + 1 + VK_SCRYPT_SALT_LEN,AES_BLOCK_SIZE);

    int hashRet = libscrypt_scrypt(password,password_l,(uint8_t*)saltbuf,
            VK_SCRYPT_SALT_LEN,VK_SCRYPT_N, VK_SCRYPT_r, VK_SCRYPT_p, hashbuf, VK_SCRYPT_HASH_LEN););

    if (hashRet != 0) {
        return 1;
    } else {
        AES_KEY key;
        if (AES_set_decrypt_key((unsigned char*) &hashbuf, 256, &key) >= 0){

            AES_cbc_encrypt(cipher + 1 + VK_SCRYPT_SALT_LEN + AES_BLOCK_SIZE, plaintext, length,
                &key, iv, AES_DECRYPT);
            return 0;
        } else {
            return 1;
        }
    }
}

int getScryptEncryptedSize(unsigned int decryptedsize) {


return 1 + VK_SCRYPT_SALT_LEN + AES_BLOCK_SIZE + (((decryptedsize + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE);
}

int main(){
    uint8_t encrypted[getScryptEncryptedSize(320)];
    uint8_t decrypted[320];

    scryptencrypt("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",320,"password",8,encrypted);
    hex_print(encrypted,getScryptEncryptedSize(320));
    scryptdecrypt(encrypted,getScryptEncryptedSize(320),"password",8,decrypted);
    hex_print(decrypted,320);
}
Onza
  • 1,710
  • 4
  • 18
  • 31
  • sorry I forgot to add the hex_print function, anyway, it just prints hex. – Onza Jun 23 '15 at 02:30
  • 1
    You need to be careful using the raw OpenSSL encryption/decryption functions, and the general view is that the "EVP" functions should be used instead. I know of one bug in `AES_cbc_encrypt` that may be contributing to your issue. See my answer here: http://stackoverflow.com/a/19893028/381588 – Iridium Jun 23 '15 at 07:59
  • @Iridium in your answer you recommend to make the data to encrypt a multiple of 16, which I already do here, well I'll check EVP then :( – Onza Jun 23 '15 at 12:40
  • @Iridium apparently must be that bug you mention, I use EVP even with the same variables and it works like charm. – Onza Jun 23 '15 at 15:10

0 Answers0