Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Chris M. Thomasson 6/4/2018
- Experimental HMAC Cipher
- C version with hardcoded secret key
- Using the following HMAC lib:
- https://github.com/ogay/hmac
- Here is some info on my cipher:
- http://funwithfractals.atspace.cc/ct_cipher
- ________________________________________________________*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- #include <string.h>
- #include <time.h>
- #include "hmac_sha2.h"
- #define HMAC_SZ 32
- // Uncomment PYTHON_TEST_VECTOR to sync with the Python 3 test vector
- // Python code: https://pastebin.com/raw/NAnsBJAZ
- // plaintext 9 bytes at: "Plaintext"
- // ciphertext bytes:
- // 723f811f5eb43df4e0dd50cc2016ff8f14f53137143135f31c99eb0030da44cbc6ace1d9be236858de
- //#define PYTHON_TEST_VECTOR
- struct ct_secret_key
- {
- unsigned char* hmac_key;
- size_t hmac_key_sz;
- char* hmac_algo;
- size_t rand_n;
- };
- struct ct_buf
- {
- unsigned char* p;
- size_t sz;
- };
- void ct_hex_printf(
- FILE* fout,
- unsigned char* buf,
- size_t buf_sz
- ) {
- for (size_t i = 0; i < buf_sz; i++)
- {
- fprintf(fout, "%02x", buf[i]);
- }
- }
- unsigned char*
- ct_reverse(
- unsigned char* P,
- size_t P_sz
- ) {
- for (size_t i = 0; i < P_sz / 2; ++i)
- {
- size_t r = P_sz - i - 1;
- unsigned char t = P[i];
- P[i] = P[r];
- P[r] = t;
- }
- return P;
- }
- size_t
- ct_file_get_size(
- FILE* file
- ) {
- size_t file_sz = 0;
- for (file_sz = 0; fgetc(file) != EOF; ++file_sz);
- rewind(file);
- return file_sz;
- }
- // return value ct_buf.p needs to be freed!
- struct ct_buf
- ct_file_copy(
- FILE* file
- ) {
- size_t file_sz = ct_file_get_size(file);
- struct ct_buf buf = { calloc(1, file_sz), file_sz };
- assert(buf.p);
- if (buf.p)
- {
- for (size_t i = 0; i < file_sz; ++i)
- {
- int byte = fgetc(file);
- assert(byte != EOF);
- buf.p[i] = byte;
- }
- }
- return buf;
- }
- // return value ct_buf.p needs to be freed!
- struct ct_buf
- ct_prepend_from_file(
- struct ct_secret_key const* const SK,
- const char* fname
- ) {
- FILE* file = fopen(fname, "rb");
- assert(file);
- size_t file_sz = ct_file_get_size(file) + SK->rand_n;
- struct ct_buf buf = { calloc(1, file_sz), file_sz };
- if (buf.p)
- {
- // Prepend the random bytes.
- // These should be drawn from a TRNG!!!
- srand((unsigned int)time(NULL));
- #if defined (PYTHON_TEST_VECTOR)
- for (size_t i = 0; i < SK->rand_n; ++i)
- {
- buf.p[i] = (unsigned char)i;
- }
- #else
- for (size_t i = 0; i < SK->rand_n; ++i)
- {
- buf.p[i] = rand() % 256;
- }
- #endif
- // Append the original plaintext
- for (size_t i = SK->rand_n; i < file_sz; ++i)
- {
- int byte = fgetc(file);
- assert(byte != EOF);
- buf.p[i] = byte;
- }
- }
- fclose(file);
- return buf;
- }
- struct ct_buf
- ct_load_from_file(
- const char* fname
- ) {
- FILE* file = fopen(fname, "rb");
- assert(file);
- size_t file_sz = ct_file_get_size(file);
- struct ct_buf buf = { calloc(1, file_sz), file_sz };
- if (buf.p)
- {
- // Append the original plaintext
- for (size_t i = 0; i < file_sz; ++i)
- {
- int byte = fgetc(file);
- assert(byte != EOF);
- buf.p[i] = byte;
- }
- }
- fclose(file);
- return buf;
- }
- void ct_hmac_sha256_digest(
- hmac_sha256_ctx* ctx,
- unsigned char* digest
- ) {
- hmac_sha256_ctx ctx_copy = *ctx;
- hmac_sha256_final(&ctx_copy, digest, HMAC_SZ);
- }
- unsigned char*
- ct_crypt_round(
- struct ct_secret_key* SK,
- unsigned char* P,
- size_t P_sz,
- int M
- ) {
- hmac_sha256_ctx H;
- hmac_sha256_init(&H, SK->hmac_key, SK->hmac_key_sz);
- ct_reverse(SK->hmac_key, SK->hmac_key_sz);
- hmac_sha256_update(&H, SK->hmac_key, SK->hmac_key_sz);
- ct_reverse(SK->hmac_key, SK->hmac_key_sz);
- unsigned char D[256] = { 0 };
- size_t P_I = 0;
- unsigned long di = 0;
- while (P_I < P_sz)
- {
- ct_hmac_sha256_digest(&H, D);
- printf("\nD[%lu]:", di);
- ct_hex_printf(stdout, D, HMAC_SZ);
- printf("\n");
- size_t D_I = 0;
- ++di;
- while (P_I < P_sz && D_I < HMAC_SZ)
- {
- unsigned char P_byte = P[P_I];
- unsigned char C_byte = P_byte ^ D[D_I];
- P[P_I] = C_byte;
- if (M == 0)
- {
- unsigned char update[2] = {
- P_byte, C_byte
- };
- hmac_sha256_update(&H, update, 2);
- }
- else
- {
- unsigned char update[2] = {
- C_byte, P_byte
- };
- hmac_sha256_update(&H, update, 2);
- }
- ++P_I;
- ++D_I;
- }
- }
- return P;
- }
- unsigned char*
- ct_crypt(
- struct ct_secret_key* SK,
- unsigned char* P,
- size_t P_sz,
- int M
- ) {
- printf("Crypt Round 0:\n________________________\n");
- unsigned char* C = ct_crypt_round(SK, P, P_sz, M);
- unsigned char* C_1 = ct_reverse(C, P_sz);
- printf("\n\nCrypt Round 1:\n________________________\n");
- C = ct_crypt_round(SK, C_1, P_sz, M);
- return C;
- }
- int
- ct_ciphertext_to_file(
- FILE* fout,
- struct ct_buf const* buf
- ) {
- for (size_t i = 0; i < buf->sz; ++i)
- {
- int status = fputc((int)buf->p[i], fout);
- if (status == EOF)
- {
- assert(status != EOF);
- return 0;
- }
- }
- return 1;
- }
- int
- ct_plaintext_to_file(
- FILE* fout,
- struct ct_secret_key* SK,
- struct ct_buf const* buf
- ) {
- assert(SK->rand_n <= buf->sz);
- for (size_t i = SK->rand_n; i < buf->sz; ++i)
- {
- int status = fputc((int)buf->p[i], fout);
- if (status == EOF)
- {
- assert(status != EOF);
- return 0;
- }
- }
- return 1;
- }
- int
- ct_encrypt(
- struct ct_secret_key* SK,
- char const* fname_in,
- char const* fname_out
- ) {
- int status = 0;
- // Prepend the random bytes to the file...
- struct ct_buf buf = ct_prepend_from_file(SK, fname_in);
- if (buf.p)
- {
- unsigned char* C = ct_crypt(SK, buf.p, buf.sz, 0);
- printf("\n\n\nCiphertext:");
- ct_hex_printf(stdout, C, buf.sz);
- printf("\n\n\n");
- // Write encrypted buffer to out file
- {
- FILE* fout = fopen(fname_out, "wb");
- assert(fout);
- status = ct_ciphertext_to_file(fout, &buf);
- fclose(fout);
- }
- free(buf.p);
- }
- return status;
- }
- int
- ct_decrypt(
- struct ct_secret_key* SK,
- char const* fname_in,
- char const* fname_out
- ) {
- int status = 0;
- // Load the file...
- struct ct_buf buf = ct_load_from_file(fname_in);
- if (buf.p)
- {
- unsigned char* C = ct_crypt(SK, buf.p, buf.sz, 1);
- printf("\n\n\nPlaintext:");
- ct_hex_printf(stdout, C, buf.sz);
- printf("\n\n\n");
- // Write decrypted buffer to out file
- {
- FILE* fout = fopen(fname_out, "wb");
- assert(fout);
- status = ct_plaintext_to_file(fout, SK, &buf);
- fclose(fout);
- }
- free(buf.p);
- }
- return status;
- }
- void ct_help(void)
- {
- printf(
- "\n\n\n"
- "Usage: program in_file out_file mode_flag\n\n"
- "mode_flag -e is encrypt where the in_file gets encrypted as out_file\n\n"
- "mode_flag -d is decrypt where the in_file gets decrypted as out_file\n\n"
- "Example:\n\n"
- "program plaintext ciphertext -e\n"
- "program ciphertext plaintext_decrypt -d\n\n"
- );
- }
- int main(int argc, char *argv[])
- {
- if (argc != 4)
- {
- printf("argument count incorrect!\n");
- ct_help();
- return EXIT_FAILURE;
- }
- {
- int mode = 0;
- if (strcmp(argv[3], "-e") == 0)
- {
- mode = 0;
- }
- else if (strcmp(argv[3], "-d") == 0)
- {
- mode = 1;
- }
- else
- {
- printf("argument encrypt/decrypt incorrect!\n");
- ct_help();
- return EXIT_FAILURE;
- }
- unsigned char hmac_key[] = "Password";
- struct ct_secret_key SK = {
- hmac_key,
- sizeof(hmac_key) - 1,
- "sha256",
- HMAC_SZ
- };
- if (mode == 0)
- {
- ct_encrypt(&SK, argv[1], argv[2]);
- }
- else
- {
- ct_decrypt(&SK, argv[1], argv[2]);
- }
- }
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment