From a96729198fa1ce02da3ef83695c0e77c320a707d Mon Sep 17 00:00:00 2001 From: antoine Date: Wed, 20 Jan 2016 20:25:02 +0100 Subject: [PATCH] passage en objet fini mais segfault --- .idea/.name | 1 + .idea/aes.iml | 12 ++ .idea/encodings.xml | 6 + .idea/misc.xml | 14 ++ .idea/modules.xml | 8 ++ .idea/vcs.xml | 6 + .idea/workspace.xml | 320 ++++++++++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 8 ++ aes.cpp | 285 ++++++++------------------------------- aes.cpp.save | 256 +++++++++++++++++++++++++++++++++++ aes.hpp | 143 ++++++++++++++++++++ crypt.hpp | 75 +++++++++++ crypto.ex | Bin 34704 -> 62216 bytes decrypt.hpp | 71 ++++++++++ makefile | 2 + 15 files changed, 978 insertions(+), 229 deletions(-) create mode 100644 .idea/.name create mode 100644 .idea/aes.iml create mode 100644 .idea/encodings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 CMakeLists.txt create mode 100644 aes.cpp.save create mode 100644 crypt.hpp create mode 100644 decrypt.hpp diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..e9ff9a0 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +aes \ No newline at end of file diff --git a/.idea/aes.iml b/.idea/aes.iml new file mode 100644 index 0000000..921849b --- /dev/null +++ b/.idea/aes.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..97626ba --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..3eb495b --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..1de4e38 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..391076c --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + C/C++ + + + + + Unused codeC/C++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1453148077173 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7232844 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.3) +project(aes) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -ggdb -lcrypto") +include_directories("/usr/include/openssl/") + +set(SOURCE_FILES aes.cpp) +add_executable(crypto.ex ${SOURCE_FILES}) \ No newline at end of file diff --git a/aes.cpp b/aes.cpp index 289f636..84f49d8 100644 --- a/aes.cpp +++ b/aes.cpp @@ -1,256 +1,83 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define FAILURE -1 -#define SUCCESS 0 - -#define AES_KEYLEN 256 -#define AES_ROUNDS 6 - - -int aesDecrypt(EVP_CIPHER_CTX* aesDecryptCtx, unsigned char* aesKey, unsigned char* aesIV, unsigned char *encMsg, size_t encMsgLen, unsigned char **decMsg) { - size_t decLen = 0; - size_t blockLen = 0; - - *decMsg = (unsigned char*)malloc(encMsgLen); - if(*decMsg == NULL) return FAILURE; - - if(!EVP_DecryptInit_ex(aesDecryptCtx, EVP_aes_256_cbc(), NULL, aesKey, aesIV)) { - return FAILURE; - } - - if(!EVP_DecryptUpdate(aesDecryptCtx, (unsigned char*)*decMsg, (int*)&blockLen, encMsg, (int)encMsgLen)) { - return FAILURE; - } - decLen += blockLen; - - if(!EVP_DecryptFinal_ex(aesDecryptCtx, (unsigned char*)*decMsg + decLen, (int*)&blockLen)) { - return FAILURE; - } - decLen += blockLen; - - EVP_CIPHER_CTX_cleanup(aesDecryptCtx); - - return (int)decLen; -} - -int aesEncrypt(EVP_CIPHER_CTX* aesEncryptCtx, unsigned char* aesKey, unsigned char* aesIV, const unsigned char *msg, size_t msgLen, unsigned char **encMsg) { - size_t blockLen = 0; - size_t encMsgLen = 0; - - *encMsg = (unsigned char*)malloc(msgLen + AES_BLOCK_SIZE); - if(encMsg == NULL) return FAILURE; - - if(!EVP_EncryptInit_ex(aesEncryptCtx, EVP_aes_256_cbc(), NULL, aesKey, aesIV)) { - return FAILURE; - } - - if(!EVP_EncryptUpdate(aesEncryptCtx, *encMsg, (int*)&blockLen, (unsigned char*)msg, msgLen)) { - return FAILURE; - } - encMsgLen += blockLen; - - if(!EVP_EncryptFinal_ex(aesEncryptCtx, *encMsg + encMsgLen, (int*)&blockLen)) { - return FAILURE; - } - - EVP_CIPHER_CTX_cleanup(aesEncryptCtx); - - return encMsgLen + blockLen; -} - -void clear_all(EVP_CIPHER_CTX* aesEncryptCtx, EVP_CIPHER_CTX* aesDecryptCtx, unsigned char* aesKey, unsigned char* aesIV) { - EVP_CIPHER_CTX_cleanup(aesEncryptCtx); - EVP_CIPHER_CTX_cleanup(aesDecryptCtx); - - free(aesEncryptCtx); - free(aesDecryptCtx); - - free(aesIV); - free(aesKey); -} - -void init_all(EVP_CIPHER_CTX* aesEncryptCtx, EVP_CIPHER_CTX* aesDecryptCtx, unsigned char* aesKey, unsigned char* aesIV) { - EVP_CIPHER_CTX_init(aesEncryptCtx); - EVP_CIPHER_CTX_init(aesDecryptCtx); - - unsigned char *aesPass = (unsigned char*)malloc(AES_KEYLEN/8); - unsigned char *aesSalt = (unsigned char*)malloc(8); - - if(aesKey == NULL || aesIV == NULL || aesPass == NULL || aesSalt == NULL) { - exit(FAILURE); - } - - #define USE_PBKDF - #ifdef USE_PBKDF - std::cerr << "utilisation de USE_PBKDF" << std::endl; - // Get some random data to use as the AES pass and salt - if(RAND_bytes(aesPass, AES_KEYLEN/8) == 0) { - exit(FAILURE); - } - - if(RAND_bytes(aesSalt, 8) == 0) { - exit(FAILURE); - } - - if(EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha256(), aesSalt, aesPass, AES_KEYLEN/8, AES_ROUNDS, aesKey, aesIV) == 0) { - exit(FAILURE); - } - #else - if(RAND_bytes(aesKey, AES_KEYLEN/8) == 0) { - exit(FAILURE); - } - - if(RAND_bytes(aesIV, AES_KEYLEN/8) == 0) { - exit(FAILURE); - } - #endif - - free(aesPass); - free(aesSalt); -} - -void writeFile(char *filename, unsigned char *file, size_t fileLength) { - FILE *fd = fopen(filename, "wb"); - if(fd == NULL) { - fprintf(stderr, "Failed to open file: %s\n", strerror(errno)); - exit(1); - } - - size_t bytesWritten = fwrite(file, 1, fileLength, fd); - - if(bytesWritten != fileLength) { - fprintf(stderr, "Failed to write file\n"); - exit(1); - } - - fclose(fd); -} - -int readFile(char *filename, unsigned char **file) { - FILE *fd = fopen(filename, "rb"); - if(fd == NULL) { - fprintf(stderr, "Failed to open file: %s\n", strerror(errno)); - exit(1); - } - - // Determine size of the file - fseek(fd, 0, SEEK_END); - size_t fileLength = ftell(fd); - fseek(fd, 0, SEEK_SET); - - // Allocate space for the file - *file = (unsigned char*)malloc(fileLength); - if(*file == NULL) { - fprintf(stderr, "Failed to allocate memory\n"); - exit(1); - } - - // Read the file into the buffer - size_t bytesRead = fread(*file, 1, fileLength, fd); - - if(bytesRead != fileLength) { - fprintf(stderr, "Error reading file\n"); - exit(1); - } - - fclose(fd); - - return fileLength; -} +#include "aes.hpp" +#include "crypt.hpp" +#include "decrypt.hpp" int main(int argc, char* argv[]) { if(argc != 2) { - fprintf(stderr, "No file argument supplied.\n"); + std::cerr << "No file argument supplied.\n"; return 1; } - EVP_CIPHER_CTX* aesEncryptCtx = (EVP_CIPHER_CTX*)malloc(sizeof(EVP_CIPHER_CTX)); - EVP_CIPHER_CTX* aesDecryptCtx = (EVP_CIPHER_CTX*)malloc(sizeof(EVP_CIPHER_CTX)); - if(aesDecryptCtx == NULL || aesEncryptCtx == NULL) { - return FAILURE; - } - - unsigned char* aesKey = (unsigned char*)malloc(AES_KEYLEN/8); - unsigned char* aesIV = (unsigned char*)malloc(AES_KEYLEN/8); - - init_all(aesEncryptCtx, aesDecryptCtx, aesKey, aesIV); - //*************************************************** char* filename = argv[1]; + aes O = crypt(filename); + // Read the file to encrypt unsigned char *file; - size_t fileLength = readFile(filename, &file); + // readFile fait l'aloccation mémoire !!! pensé au free + size_t fileLength = O.readFile(&file); printf("%d bytes to be encrypted\n", (int)fileLength); - + // Encrypt the file unsigned char *encryptedFile; int encryptedFileLength; - if((encryptedFileLength = aesEncrypt(aesEncryptCtx, aesKey, aesIV, (const unsigned char*)file, fileLength, &encryptedFile)) == -1) { - fprintf(stderr, "Encryption failed\n"); - return 1; - } - printf("%d bytes encrypted\n", encryptedFileLength); - - // Append .enc to the filename - char *encryptedFilename = (char*)malloc(strlen(filename) + 5); - if(encryptedFilename == NULL) { - fprintf(stderr, "Failed to allocate memory\n"); - return 1; - } - sprintf(encryptedFilename, "%s.enc", filename); - - // Write the encrypted file to its own file - writeFile(encryptedFilename, encryptedFile, encryptedFileLength); - std::cerr << "aesKey : "; - for (int i = 0; i < 32; i++) { - std::cerr << std::hex << aesKey[i]; - } - std::cerr << std::endl; + crypt temp = static_cast(O); + + // if((encryptedFileLength = (temp).aesEncrypt((const unsigned char*)file, fileLength, &encryptedFile) ) == -1) { + // fprintf(stderr, "Encryption failed\n"); + // return 1; + // } + // printf("%d bytes encrypted\n", encryptedFileLength); - printf("Encrypted message written to \"%s\"\n", encryptedFilename); + // // Append .enc to the filename + // char *encryptedFilename = (char*)malloc(strlen(filename) + 5); + // if(encryptedFilename == NULL) { + // fprintf(stderr, "Failed to allocate memory\n"); + // return 1; + // } + // sprintf(encryptedFilename, "%s.enc", filename); + + // // Write the encrypted file to its own file + // writeFile(encryptedFilename, encryptedFile, encryptedFileLength); + + // std::cerr << "aesKey : "; + // for (int i = 0; i < 32; i++) { + // std::cerr << std::hex << aesKey[i]; + // } + // std::cerr << std::endl; + + // printf("Encrypted message written to \"%s\"\n", encryptedFilename); free(file); - //*************************************************** + // //*************************************************** - fileLength = readFile(encryptedFilename, &file); + // fileLength = readFile(encryptedFilename, &file); - // Decrypt the encrypted file - unsigned char *decryptedFile; - int decryptedFileLength; - if((decryptedFileLength = aesDecrypt(aesDecryptCtx, aesKey, aesIV, file, fileLength, &decryptedFile)) == -1) { - fprintf(stderr, "Decryption failed\n"); - return 1; - } - printf("%d bytes decrypted\n", (int)decryptedFileLength); + // // Decrypt the encrypted file + // unsigned char *decryptedFile; + // int decryptedFileLength; + // if((decryptedFileLength = aesDecrypt(aesDecryptCtx, aesKey, aesIV, file, fileLength, &decryptedFile)) == -1) { + // fprintf(stderr, "Decryption failed\n"); + // return 1; + // } + // printf("%d bytes decrypted\n", (int)decryptedFileLength); - // Append .dec to the filename - char *decryptedFilename = (char*)malloc(strlen(filename) + 5); - if(decryptedFilename == NULL) { - fprintf(stderr, "Failed to allocate memory\n"); - return 1; - } - sprintf(decryptedFilename, "%s.dec", filename); + // // Append .dec to the filename + // char *decryptedFilename = (char*)malloc(strlen(filename) + 5); + // if(decryptedFilename == NULL) { + // fprintf(stderr, "Failed to allocate memory\n"); + // return 1; + // } + // sprintf(decryptedFilename, "%s.dec", filename); - // Write the decrypted file to its own file - writeFile(decryptedFilename, decryptedFile, decryptedFileLength); - printf("Decrypted file written to \"%s\"\n", decryptedFilename); + // // Write the decrypted file to its own file + // writeFile(decryptedFilename, decryptedFile, decryptedFileLength); + // printf("Decrypted file written to \"%s\"\n", decryptedFilename); - free(decryptedFile); - free(file); + // free(decryptedFile); + // free(file); - - //*************************************************** - clear_all(aesEncryptCtx, aesDecryptCtx, aesKey, aesIV); return 0; } \ No newline at end of file diff --git a/aes.cpp.save b/aes.cpp.save new file mode 100644 index 0000000..c6952e9 --- /dev/null +++ b/aes.cpp.save @@ -0,0 +1,256 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define FAILURE -1 +#define SUCCESS 0 + +#define AES_KEYLEN 256 +#define AES_ROUNDS 6 + + +int aesDecrypt(EVP_CIPHER_CTX* aesDecryptCtx, unsigned char* aesKey, unsigned char* aesIV, unsigned char *encMsg, size_t encMsgLen, unsigned char **decMsg) { + size_t decLen = 0; + size_t blockLen = 0; + + *decMsg = (unsigned char*)malloc(encMsgLen); + if(*decMsg == NULL) return FAILURE; + + if(!EVP_DecryptInit_ex(aesDecryptCtx, EVP_aes_256_cbc(), NULL, aesKey, aesIV)) { + return FAILURE; + } + + if(!EVP_DecryptUpdate(aesDecryptCtx, (unsigned char*)*decMsg, (int*)&blockLen, encMsg, (int)encMsgLen)) { + return FAILURE; + } + decLen += blockLen; + + if(!EVP_DecryptFinal_ex(aesDecryptCtx, (unsigned char*)*decMsg + decLen, (int*)&blockLen)) { + return FAILURE; + } + decLen += blockLen; + + EVP_CIPHER_CTX_cleanup(aesDecryptCtx); + + return (int)decLen; +} + +int aesEncrypt(EVP_CIPHER_CTX* aesEncryptCtx, unsigned char* aesKey, unsigned char* aesIV, const unsigned char *msg, size_t msgLen, unsigned char **encMsg) { + size_t blockLen = 0; + size_t encMsgLen = 0; + + *encMsg = (unsigned char*)malloc(msgLen + AES_BLOCK_SIZE); + if(encMsg == NULL) return FAILURE; + + if(!EVP_EncryptInit_ex(aesEncryptCtx, EVP_aes_256_cbc(), NULL, aesKey, aesIV)) { + return FAILURE; + } + + if(!EVP_EncryptUpdate(aesEncryptCtx, *encMsg, (int*)&blockLen, (unsigned char*)msg, msgLen)) { + return FAILURE; + } + encMsgLen += blockLen; + + if(!EVP_EncryptFinal_ex(aesEncryptCtx, *encMsg + encMsgLen, (int*)&blockLen)) { + return FAILURE; + } + + EVP_CIPHER_CTX_cleanup(aesEncryptCtx); + + return encMsgLen + blockLen; +} + +void clear_all(EVP_CIPHER_CTX* aesEncryptCtx, EVP_CIPHER_CTX* aesDecryptCtx, unsigned char* aesKey, unsigned char* aesIV) { + EVP_CIPHER_CTX_cleanup(aesEncryptCtx); + EVP_CIPHER_CTX_cleanup(aesDecryptCtx); + + free(aesEncryptCtx); + free(aesDecryptCtx); + + free(aesIV); + free(aesKey); +} + +void init_all(EVP_CIPHER_CTX* aesEncryptCtx, EVP_CIPHER_CTX* aesDecryptCtx, unsigned char* aesKey, unsigned char* aesIV) { + EVP_CIPHER_CTX_init(aesEncryptCtx); + EVP_CIPHER_CTX_init(aesDecryptCtx); + + unsigned char *aesPass = (unsigned char*)malloc(AES_KEYLEN/8); + unsigned char *aesSalt = (unsigned char*)malloc(8); + + if(aesKey == NULL || aesIV == NULL || aesPass == NULL || aesSalt == NULL) { + exit(FAILURE); + } + + #define USE_PBKDF + #ifdef USE_PBKDF + std::cerr << "utilisation de USE_PBKDF" << std::endl; + // Get some random data to use as the AES pass and salt + if(RAND_bytes(aesPass, AES_KEYLEN/8) == 0) { + exit(FAILURE); + } + + if(RAND_bytes(aesSalt, 8) == 0) { + exit(FAILURE); + } + + if(EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha256(), aesSalt, aesPass, AES_KEYLEN/8, AES_ROUNDS, aesKey, aesIV) == 0) { + exit(FAILURE); + } + #else + if(RAND_bytes(aesKey, AES_KEYLEN/8) == 0) { + exit(FAILURE); + } + + if(RAND_bytes(aesIV, AES_KEYLEN/8) == 0) { + exit(FAILURE); + } + #endif + + free(aesPass); + free(aesSalt); +} + +void writeFile(char *filename, unsigned char *file, size_t fileLength) { + FILE *fd = fopen(filename, "wb"); + if(fd == NULL) { + fprintf(stderr, "Failed to open file: %s\n", strerror(errno)); + exit(1); + } + + size_t bytesWritten = fwrite(file, 1, fileLength, fd); + + if(bytesWritten != fileLength) { + fprintf(stderr, "Failed to write file\n"); + exit(1); + } + + fclose(fd); +} + +int readFile(char *filename, unsigned char **file) { + FILE *fd = fopen(filename, "rb"); + if(fd == NULL) { + fprintf(stderr, "Failed to open file: %s\n", strerror(errno)); + exit(1); + } + + // Determine size of the file + fseek(fd, 0, SEEK_END); + size_t fileLength = ftell(fd); + fseek(fd, 0, SEEK_SET); + + // Allocate space for the file + *file = (unsigned char*)malloc(fileLength); + if(*file == NULL) { + fprintf(stderr, "Failed to allocate memory\n"); + exit(1); + } + + // Read the file into the buffer + size_t bytesRead = fread(*file, 1, fileLength, fd); + + if(bytesRead != fileLength) { + fprintf(stderr, "Error reading file\n"); + exit(1); + } + + fclose(fd); + + return fileLength; +} + +int main(int argc, char* argv[]) { + if(argc != 2) { + fprintf(stderr, "No file argument supplied.\n"); + return 1; + } + + EVP_CIPHER_CTX* aesEncryptCtx = (EVP_CIPHER_CTX*)malloc(sizeof(EVP_CIPHER_CTX)); + EVP_CIPHER_CTX* aesDecryptCtx = (EVP_CIPHER_CTX*)malloc(sizeof(EVP_CIPHER_CTX)); + if(aesDecryptCtx == NULL || aesEncryptCtx == NULL) { + return FAILURE; + } + + unsigned char* aesKey = (unsigned char*)malloc(AES_KEYLEN/8); + unsigned char* aesIV = (unsigned char*)malloc(AES_KEYLEN/8); + + init_all(aesEncryptCtx, aesDecryptCtx, aesKey, aesIV); + + //*************************************************** + char* filename = argv[1]; + + // Read the file to encrypt + unsigned char *file; + size_t fileLength = readFile(filename, &file); + printf("%d bytes to be encrypted\n", (int)fileLength); + + // Encrypt the file + unsigned char *encryptedFile; + int encryptedFileLength; + if((encryptedFileLength = aesEncrypt(aesEncryptCtx, aesKey, aesIV, (const unsigned char*)file, fileLength, &encryptedFile)) == -1) { + fprintf(stderr, "Encryption failed\n"); + return 1; + } + printf("%d bytes encrypted\n", encryptedFileLength); + + // Append .enc to the filename + char *encryptedFilename = (char*)malloc(strlen(filename) + 5); + if(encryptedFilename == NULL) { + fprintf(stderr, "Failed to allocate memory\n"); + return 1; + } + sprintf(encryptedFilename, "%s.enc", filename); + + // Write the encrypted file to its own file + writeFile(encryptedFilename, encryptedFile, encryptedFileLength); + + std::cerr << "aesKey : "; + for (int i = 0; i < 32; i++) { + std::cerr << std::hex << aesKey[i]; + } + std::cerr << std::endl; + + printf("Encrypted message written to \"%s\"\n", encryptedFilename); + + free(file); + //*************************************************** + + fileLength = readFile(encryptedFilename, &file); + + // Decrypt the encrypted file + unsigned char *decryptedFile; + int decryptedFileLength; + if((decryptedFileLength = aesDecrypt(aesDecryptCtx, aesKey, aesIV, file, fileLength, &decryptedFile)) == -1) { + fprintf(stderr, "Decryption failed\n"); + return 1; + } + printf("%d bytes decrypted\n", (int)decryptedFileLength); + + // Append .dec to the filename + char *decryptedFilename = (char*)malloc(strlen(filename) + 5); + if(decryptedFilename == NULL) { + fprintf(stderr, "Failed to allocate memory\n"); + return 1; + } + sprintf(decryptedFilename, "%s.dec", filename); + + // Write the decrypted file to its own file + writeFile(decryptedFilename, decryptedFile, decryptedFileLength); + printf("Decrypted file written to \"%s\"\n", decryptedFilename); + + free(decryptedFile); + free(file); + + + //*************************************************** + clear_all(aesEncryptCtx, aesDecryptCtx, aesKey, aesIV); + return 0; +} \ No newline at end of file diff --git a/aes.hpp b/aes.hpp index e69de29..7bb6ffd 100644 --- a/aes.hpp +++ b/aes.hpp @@ -0,0 +1,143 @@ +#ifndef _AES +#define _AES + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define FAILURE -1 +#define SUCCESS 0 + +#define AES_KEYLEN 256 +#define AES_ROUNDS 6 + +class aes { +protected: + unsigned char* aesKey; + unsigned char* aesIV; +private: + std::string filename; + +public: + aes(std::string _filename); + aes(const aes& _e); + void init_all(); + void writeFile(unsigned char *file, size_t fileLength); + int readFile(unsigned char **file); + void clear_all(); + ~aes(); +}; + +aes::aes(std::string _filename) { + filename = _filename; + aesKey = (unsigned char*)malloc(AES_KEYLEN/8); + aesIV = (unsigned char*)malloc(AES_KEYLEN/8); +} + +aes::aes(const aes& _e) : filename(_e.filename) { + std::cerr << "salut\n"; +} + +void aes::init_all() { + + unsigned char *aesPass = (unsigned char*)malloc(AES_KEYLEN/8); + unsigned char *aesSalt = (unsigned char*)malloc(8); + + if(aesKey == NULL || aesIV == NULL || aesPass == NULL || aesSalt == NULL) { + exit(FAILURE); + } + + #define USE_PBKDF + #ifdef USE_PBKDF + std::cerr << "utilisation de USE_PBKDF" << std::endl; + // Get some random data to use as the AES pass and salt + if(RAND_bytes(aesPass, AES_KEYLEN/8) == 0) { + exit(FAILURE); + } + + if(RAND_bytes(aesSalt, 8) == 0) { + exit(FAILURE); + } + + if(EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha256(), aesSalt, aesPass, AES_KEYLEN/8, AES_ROUNDS, aesKey, aesIV) == 0) { + exit(FAILURE); + } + #else + if(RAND_bytes(aesKey, AES_KEYLEN/8) == 0) { + exit(FAILURE); + } + + if(RAND_bytes(aesIV, AES_KEYLEN/8) == 0) { + exit(FAILURE); + } + #endif + + free(aesPass); + free(aesSalt); +} + +// peut être déporté le buffer lut avec methode pour travaillé dessus +int aes::readFile(unsigned char **file) { + FILE *fd = fopen(filename.c_str(), "rb"); + if(fd == NULL) { + fprintf(stderr, "Failed to open file: %s\n", strerror(errno)); + exit(1); + } + + // Determine size of the file + fseek(fd, 0, SEEK_END); + size_t fileLength = ftell(fd); + fseek(fd, 0, SEEK_SET); + + // Allocate space for the file + *file = (unsigned char*)malloc(fileLength); + if(*file == NULL) { + fprintf(stderr, "Failed to allocate memory\n"); + exit(1); + } + + // Read the file into the buffer + size_t bytesRead = fread(*file, 1, fileLength, fd); + + if(bytesRead != fileLength) { + fprintf(stderr, "Error reading file\n"); + exit(1); + } + + fclose(fd); + + return fileLength; +} + +void aes::writeFile(unsigned char *file, size_t fileLength) { + FILE *fd = fopen(filename.c_str(), "wb"); + if(fd == NULL) { + fprintf(stderr, "Failed to open file: %s\n", strerror(errno)); + exit(1); + } + + size_t bytesWritten = fwrite(file, 1, fileLength, fd); + + if(bytesWritten != fileLength) { + fprintf(stderr, "Failed to write file\n"); + exit(1); + } + + fclose(fd); +} + +void aes::clear_all() { + free(aesIV); + free(aesKey); +} + +aes::~aes() {} + +#endif \ No newline at end of file diff --git a/crypt.hpp b/crypt.hpp new file mode 100644 index 0000000..1c4f123 --- /dev/null +++ b/crypt.hpp @@ -0,0 +1,75 @@ +#ifndef _CRYPT +#define _CRYPT + +#include "aes.hpp" + +class crypt : public aes { +private: + EVP_CIPHER_CTX* aesEncryptCtx; + +public: + crypt(std::string filename); + crypt(const aes& a); + void init_all(); + int aesEncrypt(const unsigned char *msg, size_t msgLen, unsigned char **encMsg); + ~crypt(); +}; + +crypt::crypt(std::string filename) : aes(filename) { + aesEncryptCtx = (EVP_CIPHER_CTX*)malloc(sizeof(EVP_CIPHER_CTX)); + if(aesEncryptCtx == NULL) { + exit(FAILURE); + } + init_all(); +} + +crypt::crypt(const aes& _a) : aes(_a) { + aesEncryptCtx = (EVP_CIPHER_CTX*)malloc(sizeof(EVP_CIPHER_CTX)); + if(aesEncryptCtx == NULL) { + exit(FAILURE); + } + int res = EVP_CIPHER_CTX_copy(aesEncryptCtx, static_cast(_a).aesEncryptCtx); + if(!res) + exit(FAILURE); + + // *aesEncryptCtx = (*(static_cast(_a)).aesEncryptCtx); +} + +void crypt::init_all() { + aes::init_all(); + EVP_CIPHER_CTX_init(aesEncryptCtx); +} + +int crypt::aesEncrypt(const unsigned char *msg, size_t msgLen, unsigned char **encMsg) { + size_t blockLen = 0; + size_t encMsgLen = 0; + + *encMsg = (unsigned char*)malloc(msgLen + AES_BLOCK_SIZE); + if(encMsg == NULL) return FAILURE; + + if(!EVP_EncryptInit_ex(aesEncryptCtx, EVP_aes_256_cbc(), NULL, aes::aesKey, aes::aesIV)) { + return FAILURE; + } + + if(!EVP_EncryptUpdate(aesEncryptCtx, *encMsg, (int*)&blockLen, (unsigned char*)msg, msgLen)) { + return FAILURE; + } + encMsgLen += blockLen; + + if(!EVP_EncryptFinal_ex(aesEncryptCtx, *encMsg + encMsgLen, (int*)&blockLen)) { + return FAILURE; + } + + EVP_CIPHER_CTX_cleanup(aesEncryptCtx); + + return encMsgLen + blockLen; +} + + +crypt::~crypt() { + aes::clear_all(); + EVP_CIPHER_CTX_cleanup(aesEncryptCtx); + free(aesEncryptCtx); +} + +#endif \ No newline at end of file diff --git a/crypto.ex b/crypto.ex index 8c1725c00cff5c413e15f96f9b6e60e7fa0bf7db..082483d472149a9d49c4e08990eff8e4f8130951 100755 GIT binary patch literal 62216 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 E0P3g`xBvhE literal 34704 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.aesDecryptCtx); +} + +void decrypt::init_all() { + aes::init_all(); + EVP_CIPHER_CTX_init(aesDecryptCtx); +} + +int decrypt::aesDecrypt(unsigned char *encMsg, size_t encMsgLen, unsigned char **decMsg) { + size_t decLen = 0; + size_t blockLen = 0; + + *decMsg = (unsigned char*)malloc(encMsgLen); + if(*decMsg == NULL) return FAILURE; + + if(!EVP_DecryptInit_ex(aesDecryptCtx, EVP_aes_256_cbc(), NULL, aes::aesKey, aes::aesIV)) { + return FAILURE; + } + + if(!EVP_DecryptUpdate(aesDecryptCtx, (unsigned char*)*decMsg, (int*)&blockLen, encMsg, (int)encMsgLen)) { + return FAILURE; + } + decLen += blockLen; + + if(!EVP_DecryptFinal_ex(aesDecryptCtx, (unsigned char*)*decMsg + decLen, (int*)&blockLen)) { + return FAILURE; + } + decLen += blockLen; + + EVP_CIPHER_CTX_cleanup(aesDecryptCtx); + + return (int)decLen; +} + +decrypt::~decrypt() { + aes::clear_all(); + EVP_CIPHER_CTX_cleanup(aesDecryptCtx); + free(aesDecryptCtx); +} + +#endif \ No newline at end of file diff --git a/makefile b/makefile index d2e7722..1775626 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,7 @@ main: @g++ -Wall -Wextra -ggdb -o crypto.ex aes.cpp -lcrypto + +run: @./crypto.ex file.txt clean: