diff options
| -rw-r--r-- | lib/lib2.c | 230 | ||||
| -rw-r--r-- | lib/lib2.h | 17 | ||||
| -rw-r--r-- | set2/Makefile | 8 | ||||
| -rw-r--r-- | set2/task11.c | 61 | ||||
| -rw-r--r-- | set2/task13.c | 53 |
5 files changed, 304 insertions, 65 deletions
@@ -2,7 +2,7 @@ #include "lib.h" /** - * appends PKCS#7 padding to string. devide string in blocks of size blocksize + * appends PKCS#7 padding to string. devide string in blocks of size blocksize_bytes * and append to last block so that it is also of blocksize length */ @@ -105,23 +105,237 @@ int aes_cbc(char *in, int length_in, char *out, unsigned char *string_key, char } int aes_ecb(char *in, int length_in, char *out, unsigned char *string_key, - int blocksize, int encrypt) + int blocksize_bytes, int encrypt) { AES_KEY key; - int number_blocks = length_in / blocksize; + int number_blocks = length_in / blocksize_bytes; int i; if(encrypt) - AES_set_encrypt_key(string_key, blocksize, &key); + AES_set_encrypt_key(string_key, blocksize_bytes*8, &key); else - AES_set_decrypt_key(string_key, blocksize, &key); - + AES_set_decrypt_key(string_key, blocksize_bytes*8, &key); + for(i=0;i<number_blocks;i++) { if(encrypt) { - AES_encrypt(&in[i*blocksize], &out[i*blocksize],&key); + AES_encrypt(&in[i*blocksize_bytes], &out[i*blocksize_bytes],&key); } else { - AES_decrypt(&in[i*blocksize], &out[i*blocksize],&key); + AES_decrypt(&in[i*blocksize_bytes], &out[i*blocksize_bytes],&key); + } + } +} + + + +int random_number_between(int min, int max) +{ + return (rand() % (max-min) + min); +} + + +int generate_random_bytes(char *buf, int length_key_bytes) +{ + int i; + for(i=0;i<length_key_bytes;i++) { + buf[i] = (char) random_number_between(0,255); + } + +} + +char *encrypt_with_random_bytes(char *toencrypt, int length, int ecb) +{ + int toappend_before = random_number_between(5,10); + int toappend_after= random_number_between(5,10); + + char random_bytes[11]; + char key[17]; + // blocksize is 16 so allocate engouh + char *result = malloc(length+toappend_before+toappend_after+17); + char *ciphertext = malloc(length+toappend_before+toappend_after+17); + + generate_random_bytes(random_bytes, toappend_before); + + memcpy(result, random_bytes, toappend_before); + memcpy(&result[toappend_before], toencrypt, length); + + generate_random_bytes(random_bytes, toappend_after); + + memcpy(&result[length+toappend_before+toappend_after], random_bytes, toappend_after); + + generate_random_bytes(key, 16); + + + if(ecb) + aes_ecb(result, (length+toappend_before+toappend_after), ciphertext, key, 16, 1); + else { + char iv[16]; + memset(iv, 0, 16); + aes_cbc(result, (length+toappend_before+toappend_after), ciphertext, key, iv, 1); + } + + free(result); + return ciphertext; +} + + +int detect_blocksize_ecb(char *text, int length_text, char *key) +{ + int MAX_BLOCK_SIZE = 50; + int i,j; + + int breaking = 0; + char *encrypt_string = malloc(MAX_BLOCK_SIZE + length_text+17); + char *encrypted = malloc(MAX_BLOCK_SIZE + length_text+17); + char last_first_block[MAX_BLOCK_SIZE]; + memset(last_first_block, 0, MAX_BLOCK_SIZE); + + for(i=1;i<MAX_BLOCK_SIZE;i++) { + memset(encrypt_string, 'A', i); + memcpy(&encrypt_string[i+1], text, length_text); + // enrypt this and break if the first block did not change + aes_ecb(encrypt_string, length_text, encrypted, key, 16, 1); + for(j=0;j<i;j++) { + if (last_first_block[j] != encrypted[j]) { + break; + } } + memcpy(last_first_block,encrypted,i); + if(j+1==i && i!=1) + break; } + + free(encrypt_string); + free(encrypted); + + return i-1; +} +/** + * cracks one AES-ECB block + */ +int crack_aes_ecb(char *text, int length_text, char *plaintext, char *key, int blocksize) +{ + char *to_encrypt_block = malloc(length_text + 17); + char **ciphertexts= malloc(sizeof(char*)*blocksize); + char *cipher_block = malloc(blocksize+1); + char *prefix = malloc(blocksize+1); + int i,j; + + for(i=0;i<blocksize;i++) { + ciphertexts[i] = malloc(length_text + 17); + memcpy(&to_encrypt_block[i],text, length_text); + // fill it with our controlled input + memset(to_encrypt_block, 0x54, i); + // encrypt the block + aes_ecb(to_encrypt_block, blocksize, ciphertexts[i], key, 16, 1); + } + // we have all ciphertexts now to crack the whole plaintext + // let's go! + + memset(plaintext, 0, length_text); + // for every block + for(i=1;i<2;i++) { + for(j=blocksize-1;j>=0;j--) { + if(i==0) + memset(prefix, 0x54, blocksize); + else + memcpy(prefix, &text[((i-1)*blocksize)+blocksize-j], blocksize); + memcpy(&prefix[j], &text[i*blocksize], blocksize-j); + printf("prefix:%s\nendprefix\n", prefix); + memcpy(cipher_block, &(ciphertexts[j][i*blocksize]), blocksize); + plaintext[i*blocksize+blocksize-1-j] = create_dictionary_and_match(prefix, cipher_block, key, blocksize); + } + printf("plaintext so far: %s\n", plaintext); + } + +} + +char create_dictionary_and_match(char *prefix, char *match, char *key, int blocksize_bytes) +{ + char *dict_string = malloc(blocksize_bytes); + char *cipher_block = malloc(blocksize_bytes); + char *hex_tmp= malloc(blocksize_bytes*2); + int i; + hex_binary_to_string(match, hex_tmp, blocksize_bytes); + //printf("%s\n", hex_tmp); + memcpy(dict_string, prefix, blocksize_bytes); + for(i=0;i<255;i++) { + dict_string[blocksize_bytes-1] = (char) i; + printf("%s\n", dict_string); + aes_ecb(dict_string, blocksize_bytes, cipher_block, key, blocksize_bytes, 1); + hex_binary_to_string(cipher_block, hex_tmp, blocksize_bytes); + // printf("%s\n", hex_tmp); + if(memcmp(cipher_block, match, blocksize_bytes) == 0) { + //printf("found charatcer: %i\n", i); + return (char) i; + } + } +} + +struct key_value_pair *parse_key_value(char *string, int length_string) +{ + char *str1, *str2, *tmp, *tmp2; + struct key_value_pair *pair = malloc(sizeof(struct key_value_pair)); + char *saveptr1; + char *saveptr2; + + for(str1 = string; ; str1 = NULL) { + tmp2 = strtok_r(str1, "&", &saveptr1); + if (tmp2 == NULL) + break; + + for(str2 = tmp2; ; str2 = NULL) { + tmp = strtok_r(str2, "=", &saveptr2); + if (tmp == NULL) + break; + + if(str2 == NULL) { + pair->value = malloc(strlen(tmp)); + strcpy(pair->value, tmp); + } else { + pair->key = malloc(strlen(tmp)); + strcpy(pair->key, tmp); + } + } + printf("found pair: %s, %s\n", pair->key, pair->value); + } + return pair; +} + +char *__profile_for(char *email) +{ + char *ret; + char *before = "email="; + char *after = "&uid=10&role=user"; + + if(strchr(email, '=') || strchr(email, '&')) + return NULL; + + ret = malloc(strlen(email) + strlen(before) + strlen(after)+1); + strncpy(ret, before, strlen(before)); + strncat(ret, email, strlen(email)); + strncat(ret, after, strlen(after)); + + printf("%s\n", ret); + return ret; + +} + +char *profile_for(char *email) +{ + char *unencrpyted_profile_string = __profile_for(email); + char *ret = malloc(strlen(unencrpyted_profile_string)); + + aes_ecb(unencrpyted_profile_string , strlen(unencrpyted_profile_string), + ret, key, 16, 1); + + return ret; +} + +void send_user(char *encrypted_user, int length) +{ + char *unencrypted_user = malloc(length); + aes_ecb(encrypted_user, length, unencrypted_user , key, 16, 0); + printf("Got user: %s\n", unencrypted_user); + parse_key_value(unencrypted_user, strlen(unencrypted_user)); } @@ -6,10 +6,25 @@ #include <stdlib.h> #include <openssl/aes.h> +struct key_value_pair { + char *key; + char *value; +}; + +char key[17]; + char *pkcs7_padding(char *string, int length_string, int blocksize); int aes_cbc(char *in, int length_in, char *out, unsigned char *string_key, char *init_vector, int encrypt); int valid_pkcs7_padding(const char *in, int length_in, char *unpadded, int blocksize); int aes_ecb(char *in, int length_in, char *out, unsigned char *string_key, int blocksize, int encrypt); - +int generate_random_bytes(char *buf, int length_key_bytes); +int random_number_between(int min, int max); +char *encrypt_with_random_bytes(char *toencrypt, int length, int ecb); +char create_dictionary_and_match(char *prefix, char *match, char *key, int blocksize_bytes); +int detect_blocksize_ecb(char*,int,char*); +int crack_aes_ecb(char *text, int length_text, char *plaintext_block, char *key, int blocksize); +struct key_value_pair *parse_key_value(char *string, int length_string); +char *profile_for(char *email); +void send_user(char *encrypted_user, int length); #endif diff --git a/set2/Makefile b/set2/Makefile index 9c5f43e..a2d66d4 100644 --- a/set2/Makefile +++ b/set2/Makefile @@ -3,7 +3,7 @@ CC=gcc CFLAGS := -g $(CFLAGS) CLIBS=`pkg-config --cflags --libs libcrypto` -all: task9 task10 task15 +all: task9 task10 task11 task12 task13 task15 task9: $(CC) $(CFLAGS) task9.c $(LIB) $(CLIBS) -o task9 @@ -11,7 +11,11 @@ task10: $(CC) $(CFLAGS) task10.c $(LIB) $(CLIBS) -o task10 task11: $(CC) $(CFLAGS) task11.c $(LIB) $(CLIBS) -o task11 +task12: + $(CC) $(CFLAGS) task12.c $(LIB) $(CLIBS) -o task12 +task13: + $(CC) $(CFLAGS) task13.c $(LIB) $(CLIBS) -o task13 task15: $(CC) $(CFLAGS) task15.c $(LIB) $(CLIBS) -o task15 clean: - rm task9 task10 task15 + rm task9 task10 task11 task12 task13 task15 diff --git a/set2/task11.c b/set2/task11.c index 60483e0..e344a60 100644 --- a/set2/task11.c +++ b/set2/task11.c @@ -1,83 +1,36 @@ #include "../lib/lib2.h" #include "../lib/lib.h" -int random_number_between(int min, int max) -{ - return (rand() % (max-min) + min); -} - - -int generate_random_bytes(char *buf, int length_key_bytes) -{ - int random_number; - int i; - for(i=0;i<length_key_bytes;i++) { - buf[i] = (char) random_number_between(0,255); - } - -} - -char *encrypt_with_random_bytes(char *toencrypt, int length, int ecb) -{ - int toappend_before = random_number_between(5,10); - int toappend_after= random_number_between(5,10); - - char random_bytes[10]; - char key[16]; - - char *result = malloc(length+toappend_before+toappend_after+1); - char *ciphertext = malloc(length+toappend_before+toappend_after+1); - - generate_random_bytes(random_bytes, toappend_before); - - memcpy(result, random_bytes, toappend_before); - memcpy(&result[toappend_before], toencrypt, length); - - generate_random_bytes(random_bytes, toappend_after); - - memcpy(&result[length+toappend_before], random_bytes, toappend_after); - - generate_random_bytes(key, 16); - - - if(ecb) - aes_ecb(result, (length+toappend_before+toappend_after), ciphertext, key, 128, 1); - else { - char iv[16]; - memset(iv, 0, 16); - aes_cbc(result, (length+toappend_before+toappend_after), ciphertext, key, iv, 1); - } - - return ciphertext; -} int main(int argc, char **argv) { - // set seed + // srand(1); int i; // encrypt ecb mode char *cleartext = "Ok, dann mach ich mal einen richtigen Satz. Vielleicht ist das ECB mit so vielen gleichen Bloecken total ueberfordert. Oder der Satz muss einfach laenger sein. Man brauch also wirklich wohl erstmal ein bisschen Text, bevor man ECB erkennen kann"; char *ciphertext; char *ciphertext_cbc; - char iv[16]; + char iv[17]; memset(iv, 0, 16); - ciphertext = encrypt_with_random_bytes(cleartext, strlen(cleartext), 1); ciphertext_cbc = encrypt_with_random_bytes(cleartext, strlen(cleartext), 0); - //aes_ecb(cleartext, strlen(cleartext), ciphertext, "BUMMS", 128, 1); - //aes_cbc(cleartext, strlen(cleartext), ciphertext_cbc, "BUMMS", iv, 1); +// aes_ecb(cleartext, strlen(cleartext), ciphertext, "BUMMS", 128, 1); +// aes_cbc(cleartext, strlen(cleartext), ciphertext_cbc, "BUMMS", iv, 1); if(string_is_ecb_encrypted(ciphertext_cbc, strlen(cleartext), 16)) printf("Das ist wohl ECB (ist es aber nicht!)\n"); if(string_is_ecb_encrypted(ciphertext, strlen(cleartext), 16)) printf("Das ist wohl ECB (richtig)\n"); + /* for(i=0;i<strlen(cleartext);i++) printf("%c", ciphertext_cbc[i]); */ + free(ciphertext); + free(ciphertext_cbc); return 0; } diff --git a/set2/task13.c b/set2/task13.c new file mode 100644 index 0000000..3b4a7ef --- /dev/null +++ b/set2/task13.c @@ -0,0 +1,53 @@ +#include "../lib/lib2.h" +#include "../lib/lib.h" + + +/** + * One can request profiles by calling the function profile_for. + * This function ensures, that all created profiles are user profiles + * Since the profiles are encrypted and only the other side knows the + * key one cannot change the profile normally. + * + * But by making to special requst and combine them one can get a profile + * with the role admin (since it is encrypted with ECB mode) + * + * First Request: + * Create a profile such that one blocks ends with role= + * Create profile for bobi@test.com results in: + * email=bobi@test.com&uid=10&role=user + * Encrypted this results in three blocks + * The first encrypted block ist: + * email=bobi@test. + * The sencond is: + * com&uid=10&role= + * The third is not interesting for us + * + * Second Request: + * Create a profile such that a block start with admin. Combine it with + * the block which ends with role= concat them an we are admin! + * Create profile for bobi@test.admin + * First block is agian: + * email?bpbo@test. + * Second block is: + * admin&uid=10&rol + * + * When using a strict paser he maybe would not accept the string + * because of the second role=user + * + */ + +int main(int argc, char **argv) +{ + // initialize key + generate_random_bytes(key, 16); + + char *encrypted_user1 = profile_for("bobi@test.com"); + char *encrypted_user2 = profile_for("bobi@test.admin"); + char admin_user[50]; + // create new user from the two above + memcpy(admin_user, encrypted_user1, 32); + memcpy(&admin_user[32], &encrypted_user2[16], 16); + + // send new user to server + send_user(admin_user, 48); +} |
