Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use salsa20 (or ChaCha)?

Assume that we have a large file which can be read in chunks of 1024 bytes or so, how can I encrypt and decrypt each chunk using Salsa or Chacha 20?

Also, where would I specify the number of rounds (i.e. 8, 12, or 20)?

So far, I haven't been able to figure it out by looking at the eSTREAM test package :(

I've downloaded the following files via eSTREAM and the Salsa20 homepage:

  • chacha.c
  • ecrypt-config.h
  • ecrypt-machine.h
  • ecrypt-portable.h
  • ecrypt-sync.h

And I see the comments in encrypt-sync.h talk about calling functions in this order:

  • ECRYPT_keysetup();
  • ECRYPT_ivsetup();
  • ECRYPT_encrypt_bytes();

But I have absolutely no idea exactly what I'm supposed to be supplying as parameters to make this work...

Here's my best attempt so far, starting with one small string of plaintext (my C is rusty... it's possible I've made some basic mistake, though I can't see it):

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "ecrypt-sync.h"

#define CHUNKSIZE 1024

void getRandomBytes(u8 **str, u32 len);
void showData(u8 *data, u8 *header);

int main(int argc, char** argv)
{
    char plaintext[CHUNKSIZE] = "THIS IS A TEST";
    ECRYPT_ctx ctx;
    u8 *key, *IV, *ciphertext, *result;

    /*
    Don't use random values till we get it working with zeroes at least
    getRandomBytes(&key, ECRYPT_MAXKEYSIZE/8);
    getRandomBytes(&IV, ECRYPT_MAXIVSIZE/8);
    */

    key = (u8 *)calloc((size_t)ECRYPT_MAXKEYSIZE/8, sizeof(u8));
    IV = (u8 *)calloc((size_t)ECRYPT_MAXIVSIZE/8, sizeof(u8));

    printf("Encrypting [%s] using random %d bit key and %d bit IV:\n", plaintext, ECRYPT_MAXKEYSIZE, ECRYPT_MAXIVSIZE);

    ECRYPT_init();
    ECRYPT_keysetup(&ctx, key, ECRYPT_MAXKEYSIZE, ECRYPT_MAXIVSIZE);
    ECRYPT_ivsetup(&ctx, IV);

    ciphertext = (u8 *)calloc((size_t)CHUNKSIZE, sizeof(u8));

    ECRYPT_encrypt_bytes(&ctx, plaintext, ciphertext, CHUNKSIZE);

    //showData(ciphertext, "CIPHERTEXT");

    result = (u8 *)calloc((size_t)CHUNKSIZE, sizeof(u8));

    ECRYPT_decrypt_bytes(&ctx, ciphertext, result, CHUNKSIZE);
    printf("And now decrypting back: [%s]\n", result);

    return 0;
}

void showData(u8 *data, u8 *header) {
    printf("\n-----BEGIN %s-----\n%s\n-----END %s-----\n", header, data, header);

}

void getRandomBytes(u8 **str, u32 len) {
    int fd = open("/dev/random", O_RDONLY);
    char *ptr = malloc((size_t) + 1);

    read(fd, ptr, len);
    close(fd);

    ptr[len] = '\0';
    *str = ptr; 
}

Results are like:

Encrypting [THIS IS A TEST] using random 256 bit key and 64 bit IV: And now decrypting back: [(bunch of random characters)]

Where it should be:

And now decrypting back: [THIS IS A TEST]

Feel free to provide your solution in either C or C++

Thank you!

like image 676
davidkomer Avatar asked Sep 11 '25 18:09

davidkomer


1 Answers

If you are going to use Salsa20 in real code and you are asking questions like this, you probably want to use the NaCl library with nice friendly C++ wrappers.

See The NaCl website.

To answer your actual question: you need to set the IV up again for the decryption operation. The IV consists of your nonce and a block offset. The encrypt/decrypt functions increment the offset, giving your code a different IV for the encryption and decryption functions.

like image 119
janm Avatar answered Sep 14 '25 07:09

janm