summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/lib3.c78
-rw-r--r--lib/lib3.h6
-rw-r--r--set3/task24.c48
3 files changed, 132 insertions, 0 deletions
diff --git a/lib/lib3.c b/lib/lib3.c
index e976fd1..150c6ea 100644
--- a/lib/lib3.c
+++ b/lib/lib3.c
@@ -203,3 +203,81 @@ int unshift_left_xor(int number, int shifts, unsigned int mask)
return restore;
}
+
+int mt_19937_stream_cipher(char *in, int length_in, char *out, int seed)
+{
+ struct mt_19937_state mt_state;
+ char keystream;
+ int i, tmp;
+
+ mt_19937_seed(seed, &mt_state);
+
+ for(i=0;i<length_in;i++) {
+ tmp = mt_19937(&mt_state);
+ keystream = tmp & 0xFF;
+ out[i] = in[i] ^ keystream;
+ }
+}
+
+int mt_19937_stream_cipher_oracle(char *in, int length_in, char *out)
+{
+ int prefix_length = random_number_between(0,50);
+ // only 16 bit seed, 0 would not be a good seed, since the keystream
+ // would allways be 0
+ int seed = random_number_between(1,65536);
+ char *plaintext_full = malloc(length_in + prefix_length);
+
+ printf("use seed: %i\n", seed);
+ // generate random number of random bytes
+ generate_random_bytes(plaintext_full, prefix_length);
+ memcpy(&plaintext_full[prefix_length], in, length_in);
+
+ mt_19937_stream_cipher(plaintext_full, (length_in+prefix_length),
+ out, seed);
+
+ return (length_in + prefix_length);
+}
+
+
+int crack_mt_19937_stream_cipher_16_bit_seed(char *ciphertext, int length_ciphertext,
+ char *plaintext, char *match)
+{
+ int i;
+ int seed;
+ int match_len = strlen(match);
+ for(seed=1;seed<65536;seed++) {
+ mt_19937_stream_cipher(ciphertext, length_ciphertext, plaintext, seed);
+ for(i=1;i<match_len;i++) {
+ if(plaintext[length_ciphertext-i] != match[match_len-i]) {
+ break;
+ }
+ else if (i == (match_len-1))
+ goto out;
+ }
+ }
+out:
+ printf("found seed: %i\n", seed);
+}
+
+unsigned int mt_19937_password_token()
+{
+ int seed = time(NULL);
+ struct mt_19937_state mt_state;
+ printf("password token seed: %i\n", seed);
+ mt_19937_seed(seed, &mt_state);
+
+ return mt_19937(&mt_state);
+}
+
+int mt_19937_password_token_time_based(unsigned int password_token, int time_window)
+{
+ int start_time = time(NULL);
+ struct mt_19937_state mt_state;
+ int seed;
+ for(seed=start_time-(time_window*60);seed<start_time+(time_window*60);seed++) {
+ mt_19937_seed(seed, &mt_state);
+ if(password_token == mt_19937(&mt_state))
+ return 1;
+ }
+ return 0;
+}
diff --git a/lib/lib3.h b/lib/lib3.h
index b37021d..2c65b97 100644
--- a/lib/lib3.h
+++ b/lib/lib3.h
@@ -33,4 +33,10 @@ unsigned int mt_19937_timestamp_orcale(struct mt_19937_state *mt_state);
void mt_19937_brute_force_timestamp();
int unshift_left_xor(int number, int shifts, unsigned int mask);
int unshift_right_xor(int number, int shifts);
+int mt_19937_stream_cipher(char *in, int length_in, char *out, int seed);
+int mt_19937_stream_cipher_oracle(char *in, int length_in, char *out);
+int crack_mt_19937_stream_cipher_16_bit_seed(char *ciphertext, int length_ciphertext,
+ char *plaintext, char *match);
+unsigned int mt_19937_password_token();
+int mt_19937_password_token_time_based(unsigned int password_token, int time_window);
#endif
diff --git a/set3/task24.c b/set3/task24.c
new file mode 100644
index 0000000..e355d08
--- /dev/null
+++ b/set3/task24.c
@@ -0,0 +1,48 @@
+#include "../lib/lib.h"
+#include "../lib/lib2.h"
+#include "../lib/lib3.h"
+#include <time.h>
+
+/**
+ * One should not restore the internal state of the MT. Given 624 bytes of
+ * input this would be straight forward.
+ * Instead one should restore more or less the first state (the seed from
+ * which this states arrived). To restore a previous state of the MT is
+ * possible. You have to go so far back, how long your ciphertext is and
+ * how much states you would need to encrpyt it.
+ *
+ * Since it is a 16 bit seed, one can also brute force it with 2^16
+ * possible values...within seconds! exhautive search Yeah!
+ * Theoritcal we only need 2^(16/2) values because of birthday paradox
+ *
+ **/
+
+int main()
+{
+ srand(time(NULL));
+ // try to decrypt
+ char plaintext[] = "Hallo du da wie geht es dir Knallkopp";
+ char *ciphertext = malloc(strlen(plaintext));
+
+ int length_ciphertext = mt_19937_stream_cipher_oracle(plaintext,
+ strlen(plaintext), ciphertext);
+
+ char *restore_pl = malloc(length_ciphertext);
+ char *hex_ciphertext = malloc(length_ciphertext*2+1);
+ hex_binary_to_string(ciphertext, hex_ciphertext, length_ciphertext);
+ printf("ciphertext: %s\n", hex_ciphertext);
+ //mt_19937_stream_cipher(ciphertext, length_ciphertext
+ // decrypt it
+ crack_mt_19937_stream_cipher_16_bit_seed(ciphertext, length_ciphertext,
+ restore_pl, plaintext);
+
+ printf("plaintext: %s\n", restore_pl);
+
+ // crack a MT time based password token
+ // well do it agian with brute force
+ unsigned int password_token = mt_19937_password_token();
+ int is_time_based = mt_19937_password_token_time_based(password_token, 1000);
+
+ printf("password token is time based %i\n", is_time_based);
+
+}