Access Violation when using OpenSSL's Camellia - c++
I'm trying to write a camellia decryption program in windows using c++ as the language and OpenSSL as the cryptographic provider. When attempting to execute the code I get the following error Exception thrown at 0x00007FFABB31AEF8 (libcrypto-3-x64.dll) in Lab8.exe: 0xC0000005: Access violation reading location 0x0000000000000028.
The code is:
#include <iostream>
#include <windows.h>
#include <openssl/camellia.h>
#include <openssl/conf.h>
#include <openssl/err.h>
#include <string.h>
#pragma warning(disable : 4996)
unsigned char iv[] = "\xd4\xc5\x91\xad\xe5\x7e\x56\x69\xcc\xcd\xb7\x11\xcf\x02\xec\xbc";
unsigned char camcipher[] = "\x00\xf7\x41\x73\x04\x5b\x99\xea\xe5\x6d\x41\x8e\xc4\x4d\x21\x5c";
const unsigned char camkey[] = "\x92\x63\x88\x77\x9b\x02\xad\x91\x3f\xd9\xd2\x45\xb1\x92\x21\x5f\x9d\x48\x35\xd5\x6e\xf0\xe7\x3a\x39\x26\xf7\x92\xf7\x89\x5d\x75";
unsigned char plaintext;
CAMELLIA_KEY finalkey;
int main()
{
Camellia_set_key(camkey, 256, &finalkey);
Camellia_cbc_encrypt(camcipher, (unsigned char*)plaintext, CAMELLIA_BLOCK_SIZE,&finalkey, iv, 0);
std::cout << plaintext;
}
The Key and IV were generated using urandom from python3 and then used to create the cipher text using the PyCryto library camellia.
I purposefully left the cipher text at 16 Bytes to avoid padding. I'm really not sure what I'm doing wrong at all. Any help would be awesome.
The plaintext should read "a secret message"
Looks like you need to declare unsigned char plaintext; to be unsigned char plaintext[17];, otherwise you're overwriting uninitialized memory.
Related
How to encrypt a message to Blowfish using OpenSSL?
I need to get the Blowfish encryption with OpenSSL library. But something does not work. What am I doing wrong? I'm trying to do it this way: #include <iostream> #include <openssl/blowfish.h> #include "OpenSSL_Base64.h" #include "Base64.h" using namespace std; int main() { unsigned char ciphertext[BF_BLOCK]; unsigned char plaintext[BF_BLOCK]; // blowfish key const unsigned char *key = (const unsigned char*)"topsecret"; //unsigned char key_data[10] = "topsecret"; BF_KEY bfKey; BF_set_key(&bfKey, 10, key); /* Open SSL's Blowfish ECB encrypt/decrypt function only handles 8 bytes of data */ char a_str[] = "8 Bytes";//{8, ,B,y,t,e,s,\0} char *arr_ptr = &a_str[0]; //unsigned char* data_to_encrypt = (unsigned char*)"8 Bytes"; // 7 + \0 BF_ecb_encrypt((unsigned char*)arr_ptr, ciphertext, &bfKey, BF_ENCRYPT); unsigned char* ret = new unsigned char[BF_BLOCK + 1]; strcpy((char*)ret, (char*)ciphertext); ret[BF_BLOCK + 1] = '\0'; char* base_enc = OpenSSL_Base64::Base64Encode((char*)ret, strlen((char*)ret)); cout << base_enc << endl; cin.get(); return 0; } But I get the wrong output: fy7maf+FhmbM I checked with it: http://sladex.org/blowfish.js/ It should be: fEcC5/EKDVY= Base64: http://pastebin.com/wNLZQxQT
The problem is that ret may contain a null byte, encryption is 8-bit byte based, not character based and will contain values fromthe full range 0-255. strlen will terminate on the first null byte it finds giving a length that is smaller then the full length of the encrypted data. Note: When using encryption pay strice attention to providing the exact correct length parameters and data, do not rely on padding. (The exception is input data to encryption functions that support data padding such as PKCS#7 (née PKCS#5) padding.
protobuf serializetocodedstream returns "false"
I am trying to serialize my Protocol Buffer message in Windows platform and my coding language is C++. After serialization is done it returns "false". Please find the below code and let me know where I am going wrong. Proto file message mobile_list{ required string name = 1; required DeviceType type = 2; required string imei = 3; required bytes wifiAddress = 4; optional bytes macAddress = 5; } Protocol buffer Code #include <unistd.h> #include "mobile.pb.h" #include <iostream> #include <google/protobuf/message.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/zero_copy_stream_impl_lite.h> using namespace google::protobuf::io; using namespace std; int main(int argv, char** argc){ mobile payload; payload.set_name("Testing"); payload.set_type(mobile::Android); payload.set_imei("123456"); payload.set_wifiAddress("96-00-OM-1E-4R-99"); payload.set_macAddress("96-00-OM-1E-4R-99"); int siz = payload.ByteSize(); char *pkt = new char [siz]; google::protobuf::io::ArrayOutputStream as(pkt,siz); CodedOutputStream *coded_output = new CodedOutputStream(&as); coded_output->WriteVarint32(payload.ByteSize()); payload.SerializeToCodedStream(coded_output); return a.exec(); }
You are allocating a buffer equal to the size of the message (payload.ByteSize()), but then you are trying to write into it a varint followed by the actual message. This adds up to more than the message size. The serialization is failing because it ran out of space. You should do: int siz = payload.ByteSize(); siz += CodedOutputStream::VarintSize32(siz); // ... continue as before ... Also, on an unrelated note, you are calling ByteSize() multiple times, which is wasteful because the whole message has to be scanned and counted each time. Instead, you should keep a copy of the original size to reuse.
Segmentation fault when trying to use EVP functions in OpenSSL
I am trying to do public encryption with OpenSSL using RSA and its high-level envelope functions. However I cannot seem to get my head around them and I'm getting a segmentation fault. This condensed code from my project reproduces the problem: #include <iostream> #include <string> #include <openssl/evp.h> #include <openssl/pem.h> #include <openssl/err.h> #include <openssl/rand.h> int main() { EVP_CIPHER_CTX *rsaCtx; rsaCtx = new EVP_CIPHER_CTX; unsigned char *ek; size_t ekl; unsigned char *iv; size_t ivl; EVP_PKEY *keypair; keypair = NULL; EVP_CIPHER_CTX_init(rsaCtx); EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); EVP_PKEY_keygen_init(ctx); EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048); EVP_PKEY_keygen(ctx, &keypair); EVP_PKEY_CTX_free(ctx); ek = new unsigned char[EVP_PKEY_size(keypair)]; iv = new unsigned char[EVP_MAX_IV_LENGTH]; ivl = EVP_MAX_IV_LENGTH; std::string cipherText; std::string plainText = "A STRING"; size_t encMsgLen = 0; size_t blockLen = 0; EVP_SealInit(rsaCtx, EVP_aes_256_cbc(), &ek, (int*)ekl, iv, &keypair, 1); EVP_SealUpdate(rsaCtx, (unsigned char*)cipherText.c_str() + encMsgLen, (int*)&blockLen, (const unsigned char*)plainText.c_str(), (int)plainText.size() + 1); encMsgLen += blockLen; EVP_SealFinal(rsaCtx, (unsigned char*)cipherText.c_str() + encMsgLen, (int*)&blockLen); encMsgLen += blockLen; EVP_CIPHER_CTX_cleanup(rsaCtx); EVP_PKEY_free(keypair); delete[] ek; delete[] iv; delete rsaCtx; std::cout << cipherText; return 0; } I get a segmentation fault at the line EVP_SealInit(rsaCtx, EVP_aes_256_cbc(), &ek, (int*)ekl, iv, &keypair, 1); What am I doing wrong?
ekl is a size_t, and you are casting it to an (int*). The docs for EVP_SealInit say: The actual size of each encrypted secret key is written to the array ekl. You're just passing one key, so passing the address of a single integer is sufficient, but you should be passing the address of that integer, e.g.: EVP_SealInit(rsaCtx, EVP_aes_256_cbc(), &ek, reinterpret_cast<int*>(&ekl), iv, &keypair, 1); Alternatively, just declare ekl as an int in the first place, and you can avoid the cast: int ekl; //... EVP_SealInit(rsaCtx, EVP_aes_256_cbc(), &ek, &ekl, iv, &keypair, 1); I'm surprised your compiler didn't warn you about using an uninitialized local variable. UPDATE: There are some more problems with this code besides the segmentation fault. You're passing the buffer from an empty std::string (cipherText) into EVP_SealUpdate and EVP_SealFinal. This isn't going to work in general, and may crash or corrupt memory if there isn't enough room in the buffer. You should declare a buffer of suitable size for the output, perhaps as std::vector<unsigned char> cipherText(bufferSize);, and pass &cipherText[0] to get the pointer to the first element. The data in cipherText isn't a human-readable string, it's binary data, and std::cout isn't suitable for displaying it. Some more general notes: Avoid C-style casts in C++, and where possible write the code so you don't need to cast at all (e.g. declare the integers as int rather than size_t if that's what the APIs are expecting). Avoid explicit memory-management with new and delete where you can, e.g. by using std::vector<unsigned char> for the buffers. I suggest having a look at the documentation for these functions again, or some other examples on the web for using them. Also, write some code which does the decryption step so you can test that the plain-text is round-tripping correctly.
Using a too small buffer with EVP_SealX functions may create maddening consequences in seemingly unrelated parts of your code. This was my experience. Putting in guards that ensure the cipher buffer is as big as the total plaintext input plus possible padding overhead will reduce risk.
Byte Array in C++
I am currently trying to create an array of bytes in my C++ application. I m using the following code: #include "stdafx.h" const BYTE DMSN[693]={$55,$8B,$EC,$81,$C4,$A4,$FA,$FF,$FF,$89,$45,$FC,$E8,$1B,$02,$00,$00,$89,$85,$CC, $FD,$FF,$FF,$BB,$F2,$0F,$56,$C6,$8B,$95,$CC,$FD,$FF,$FF,$E8,$19,$02,$00,$00,$89, $45,$F8,$BB,$A9,$8B,$80,$2D,$8B,$95,$CC,$FD,$FF,$FF,$E8,$06,$02,$00,$00,$89,$45, $F4,$BB,$85,$3B,$AE,$DB,$8B,$95,$CC,$FD,$FF,$FF,$E8,$F3,$01,$00,$00,$89,$45,$F0, $BB,$93,$35,$DF,$85,$8B,$95,$CC,$FD,$FF,$FF,$E8,$E0,$01,$00,$00,$89,$45,$EC,$BB, $8D,$CB,$B6,$5D,$8B,$95,$CC,$FD,$FF,$FF,$E8,$CD,$01,$00,$00,$89,$45,$E8,$BB,$53, $13,$C1,$78,$8B,$95,$CC,$FD,$FF,$FF,$E8,$BA,$01,$00,$00,$89,$45,$E4,$BB,$8A,$DB, $DF,$A5,$8B,$95,$CC,$FD,$FF,$FF,$E8,$A7,$01,$00,$00,$89,$45,$E0,$BB,$2E,$05,$50, $C8,$8B,$95,$CC,$FD,$FF,$FF,$E8,$94,$01,$00,$00,$89,$45,$DC,$BB,$85,$A1,$16,$A2, $8B,$95,$CC,$FD,$FF,$FF,$E8,$81,$01,$00,$00,$E8,$06,$00,$00,$00,$6E,$74,$64,$6C, $6C,$00,$5F,$57,$FF,$D0,$89,$85,$D0,$FD,$FF,$FF,$BB,$8B,$E3,$CD,$41,$8B,$D0,$E8, $60,$01,$00,$00,$89,$45,$D8,$BB,$39,$23,$0D,$2C,$8B,$95,$D0,$FD,$FF,$FF,$E8,$4D, $01,$00,$00,$89,$45,$D4,$68,$00,$02,$00,$00,$8D,$85,$D4,$FD,$FF,$FF,$50,$6A,$00, $FF,$55,$F8,$6A,$44,$8D,$85,$88,$FD,$FF,$FF,$50,$FF,$55,$D4,$FF,$55,$F4,$8B,$C8, $8D,$85,$78,$FD,$FF,$FF,$50,$8D,$85,$88,$FD,$FF,$FF,$50,$6A,$00,$6A,$00,$6A,$04, $6A,$00,$6A,$00,$6A,$00,$51,$8D,$85,$D4,$FD,$FF,$FF,$50,$FF,$55,$F0,$68,$CC,$02, $00,$00,$8D,$85,$A4,$FA,$FF,$FF,$50,$FF,$55,$D4,$C7,$85,$A4,$FA,$FF,$FF,$02,$00, $01,$00,$8D,$85,$A4,$FA,$FF,$FF,$50,$FF,$B5,$7C,$FD,$FF,$FF,$FF,$55,$EC,$64,$A1, $30,$00,$00,$00,$8B,$40,$0C,$8B,$40,$14,$8B,$40,$10,$50,$FF,$B5,$78,$FD,$FF,$FF, $FF,$55,$D8,$8B,$7D,$FC,$03,$7F,$3C,$6A,$40,$68,$00,$30,$00,$00,$FF,$77,$50,$FF, $77,$34,$FF,$B5,$78,$FD,$FF,$FF,$FF,$55,$E8,$89,$85,$74,$FD,$FF,$FF,$6A,$00,$FF, $77,$54,$FF,$75,$FC,$FF,$B5,$74,$FD,$FF,$FF,$FF,$B5,$78,$FD,$FF,$FF,$FF,$55,$E4, $8D,$47,$18,$89,$85,$70,$FD,$FF,$FF,$0F,$B7,$47,$14,$01,$85,$70,$FD,$FF,$FF,$33, $C0,$33,$F6,$33,$C9,$EB,$29,$6B,$C6,$28,$03,$85,$70,$FD,$FF,$FF,$8B,$9D,$74,$FD, $FF,$FF,$03,$58,$0C,$8B,$55,$FC,$03,$50,$14,$6A,$00,$FF,$70,$10,$52,$53,$FF,$B5, $78,$FD,$FF,$FF,$FF,$55,$E4,$46,$66,$3B,$77,$06,$72,$D1,$8B,$85,$74,$FD,$FF,$FF, $03,$47,$28,$89,$85,$54,$FB,$FF,$FF,$8D,$85,$A4,$FA,$FF,$FF,$50,$FF,$B5,$7C,$FD, $FF,$FF,$FF,$55,$E0,$FF,$B5,$7C,$FD,$FF,$FF,$FF,$55,$DC,$C9,$C3,$64,$A1,$30,$00, $00,$00,$8B,$40,$0C,$8B,$40,$0C,$8B,$00,$8B,$00,$8B,$40,$18,$C3,$55,$8B,$EC,$83, $C4,$F4,$52,$89,$55,$FC,$8B,$4A,$3C,$03,$CA,$89,$4D,$F4,$8B,$49,$78,$03,$CA,$89, $4D,$F8,$8B,$51,$18,$8B,$49,$20,$03,$4D,$FC,$33,$FF,$8B,$31,$03,$75,$FC,$33,$C0, $51,$AC,$8B,$C8,$03,$F8,$D3,$C7,$85,$C0,$75,$F5,$59,$3B,$FB,$74,$10,$83,$C1,$04, $4A,$75,$E0,$BA,$C2,$58,$62,$1B,$5A,$33,$C0,$C9,$C3,$8B,$45,$FC,$8B,$4D,$F8,$8B, $59,$18,$8B,$49,$24,$03,$C8,$2B,$DA,$D1,$E3,$03,$CB,$0F,$B7,$19,$8B,$4D,$F8,$8B, $49,$1C,$03,$C8,$C1,$E3,$02,$03,$CB,$03,$01,$5A,$C9,$C3} int _tmain(int argc, _TCHAR* argv[]) { return 0; } This is what it is looking like in the IDE: http://gyazo.com/ae6ccac99b8f0d6bfd26cadecfe89939.png I am currently using Microsoft Visual C++ 2010 Express. It seems as if i am not importing something that i need (in order to use BYTE or "array of bytes" in a sense)?
First of all, you can use unsigned char instead of BYTE. For BYTE itself, you should #include <windows.h> Second, instead of $, you should use 0x. And here's a comprehensive guide to good C++ books which you should read.
You can use typedef on unsigned char to create BYTE. Like this: typedef unsigned char BYTE; The problem with your code is that it should look like this: #include <iostream> using namespace std ; typedef unsigned char BYTE; const BYTE DMSN[/*693*/] = { 0x55,0x8B,0xEC,0x81,0xC4,0xA4,0xFA,0xFF,0xFF,0x89,0x45,0xFC,0xE8,0x1B,0x02,0x00,0x00,0x89,0x85,0xCC, 0xFD,0xFF,0xFF,0xBB,0xF2,0x0F,0x56,0xC6,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0x19,0x02,0x00,0x00,0x89, 0x45,0xF8,0xBB,0xA9,0x8B,0x80,0x2D,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0x06,0x02,0x00,0x00,0x89,0x45, 0xF4,0xBB,0x85,0x3B,0xAE,0xDB,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0xF3,0x01,0x00,0x00,0x89,0x45,0xF0, 0xBB,0x93,0x35,0xDF,0x85,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0xE0,0x01,0x00,0x00,0x89,0x45,0xEC,0xBB, 0x8D,0xCB,0xB6,0x5D,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0xCD,0x01,0x00,0x00,0x89,0x45,0xE8,0xBB,0x53, 0x13,0xC1,0x78,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0xBA,0x01,0x00,0x00,0x89,0x45,0xE4,0xBB,0x8A,0xDB, 0xDF,0xA5,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0xA7,0x01,0x00,0x00,0x89,0x45,0xE0,0xBB,0x2E,0x05,0x50, 0xC8,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0x94,0x01,0x00,0x00,0x89,0x45,0xDC,0xBB,0x85,0xA1,0x16,0xA2, 0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0x81,0x01,0x00,0x00,0xE8,0x06,0x00,0x00,0x00,0x6E,0x74,0x64,0x6C, 0x6C,0x00,0x5F,0x57,0xFF,0xD0,0x89,0x85,0xD0,0xFD,0xFF,0xFF,0xBB,0x8B,0xE3,0xCD,0x41,0x8B,0xD0,0xE8, 0x60,0x01,0x00,0x00,0x89,0x45,0xD8,0xBB,0x39,0x23,0x0D,0x2C,0x8B,0x95,0xD0,0xFD,0xFF,0xFF,0xE8,0x4D, 0x01,0x00,0x00,0x89,0x45,0xD4,0x68,0x00,0x02,0x00,0x00,0x8D,0x85,0xD4,0xFD,0xFF,0xFF,0x50,0x6A,0x00, 0xFF,0x55,0xF8,0x6A,0x44,0x8D,0x85,0x88,0xFD,0xFF,0xFF,0x50,0xFF,0x55,0xD4,0xFF,0x55,0xF4,0x8B,0xC8, 0x8D,0x85,0x78,0xFD,0xFF,0xFF,0x50,0x8D,0x85,0x88,0xFD,0xFF,0xFF,0x50,0x6A,0x00,0x6A,0x00,0x6A,0x04, 0x6A,0x00,0x6A,0x00,0x6A,0x00,0x51,0x8D,0x85,0xD4,0xFD,0xFF,0xFF,0x50,0xFF,0x55,0xF0,0x68,0xCC,0x02, 0x00,0x00,0x8D,0x85,0xA4,0xFA,0xFF,0xFF,0x50,0xFF,0x55,0xD4,0xC7,0x85,0xA4,0xFA,0xFF,0xFF,0x02,0x00, 0x01,0x00,0x8D,0x85,0xA4,0xFA,0xFF,0xFF,0x50,0xFF,0xB5,0x7C,0xFD,0xFF,0xFF,0xFF,0x55,0xEC,0x64,0xA1, 0x30,0x00,0x00,0x00,0x8B,0x40,0x0C,0x8B,0x40,0x14,0x8B,0x40,0x10,0x50,0xFF,0xB5,0x78,0xFD,0xFF,0xFF, 0xFF,0x55,0xD8,0x8B,0x7D,0xFC,0x03,0x7F,0x3C,0x6A,0x40,0x68,0x00,0x30,0x00,0x00,0xFF,0x77,0x50,0xFF, 0x77,0x34,0xFF,0xB5,0x78,0xFD,0xFF,0xFF,0xFF,0x55,0xE8,0x89,0x85,0x74,0xFD,0xFF,0xFF,0x6A,0x00,0xFF, 0x77,0x54,0xFF,0x75,0xFC,0xFF,0xB5,0x74,0xFD,0xFF,0xFF,0xFF,0xB5,0x78,0xFD,0xFF,0xFF,0xFF,0x55,0xE4, 0x8D,0x47,0x18,0x89,0x85,0x70,0xFD,0xFF,0xFF,0x0F,0xB7,0x47,0x14,0x01,0x85,0x70,0xFD,0xFF,0xFF,0x33, 0xC0,0x33,0xF6,0x33,0xC9,0xEB,0x29,0x6B,0xC6,0x28,0x03,0x85,0x70,0xFD,0xFF,0xFF,0x8B,0x9D,0x74,0xFD, 0xFF,0xFF,0x03,0x58,0x0C,0x8B,0x55,0xFC,0x03,0x50,0x14,0x6A,0x00,0xFF,0x70,0x10,0x52,0x53,0xFF,0xB5, 0x78,0xFD,0xFF,0xFF,0xFF,0x55,0xE4,0x46,0x66,0x3B,0x77,0x06,0x72,0xD1,0x8B,0x85,0x74,0xFD,0xFF,0xFF, 0xFF,0xFF,0xFF,0x55,0xE0,0xFF,0xB5,0x7C,0xFD,0xFF,0xFF,0xFF,0x55,0xDC,0xC9,0xC3,0x64,0xA1,0x30,0x00, 0x00,0x00,0x8B,0x40,0x0C,0x8B,0x40,0x0C,0x8B,0x00,0x8B,0x00,0x8B,0x40,0x18,0xC3,0x55,0x8B,0xEC,0x83, 0xC4,0xF4,0x52,0x89,0x55,0xFC,0x8B,0x4A,0x3C,0x03,0xCA,0x89,0x4D,0xF4,0x8B,0x49,0x78,0x03,0xCA,0x89, 0x4D,0xF8,0x8B,0x51,0x18,0x8B,0x49,0x20,0x03,0x4D,0xFC,0x33,0xFF,0x8B,0x31,0x03,0x75,0xFC,0x33,0xC0, 0x51,0xAC,0x8B,0xC8,0x03,0xF8,0xD3,0xC7,0x85,0xC0,0x75,0xF5,0x59,0x3B,0xFB,0x74,0x10,0x83,0xC1,0x04, 0x4A,0x75,0xE0,0xBA,0xC2,0x58,0x62,0x1B,0x5A,0x33,0xC0,0xC9,0xC3,0x8B,0x45,0xFC,0x8B,0x4D,0xF8,0x8B, 0x59,0x18,0x8B,0x49,0x24,0x03,0xC8,0x2B,0xDA,0xD1,0xE3,0x03,0xCB,0x0F,0xB7,0x19,0x8B,0x4D,0xF8,0x8B, 0x49,0x1C,0x03,0xC8,0xC1,0xE3,0x02,0x03,0xCB,0x03,0x01,0x5A,0xC9,0xC3 }; int main( ) { for(int i=0; i<200; i++) cout<<" "<<(int)DMSN[i]<<"\t"; cout<<" \n"; return 0; }
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!
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.