from sage.crypto.util import ascii_integer
from sage.crypto.block_cipher.sdes import SimplifiedDES
bin = BinaryStrings();
sigma = 0;
def encrypt(m, k):
ct = [];
iv = ZZ.random_element(256);
n = 0;
for a in m:
if n==0:
pt = bin.encoding(chr(int(str(bin.encoding(a)), 2)^^iv));
else:
pt = bin.encoding(chr(int(str(bin.encoding(a)), 2)^^int(ct[n-1],2)));
c = sdes.encrypt(list(pt), k);
ct.append(''.join(str(i) for i in c));
n = n + 1;
return [format(iv, '08b')] + ct;
def decrypt(ct, k):
pt = '';
n = 0;
iv = int(str(ct[0]), 2);
for c in ct[1:]:
p = sdes.decrypt(list(bin(c)), k);
if n==0:
p = chr(int(''.join(str(i) for i in p), 2) ^^ iv);
else:
p = chr(int(''.join(str(i) for i in p), 2) ^^ int(ct[n], 2));
pt += p;
n = n + 1;
return pt;
def subverted_encrypt(bk, k, m):
global sigma;
ct = [];
if sigma == 0:
c = sdes.encrypt(k[:8], bk);
fake_iv = ''.join(str(i) for i in c);
iv = int(fake_iv, 2);
else:
iv = ZZ.random_element(256);
sigma = sigma + 1;
n = 0;
for a in m:
if n==0:
pt = bin.encoding(chr(int(str(bin.encoding(a)), 2)^^iv));
else:
pt = bin.encoding(chr(int(str(bin.encoding(a)), 2)^^int(ct[n-1],2)));
c = sdes.encrypt(list(pt), k);
ct.append(''.join(str(i) for i in c));
n = n + 1;
return [format(iv, '08b')] + ct;
def subverted_decrypt(bk, ct):
pt = [];
iv = int(str(ct[0]), 2);
k = sdes.decrypt(list(bin.encoding(chr(iv))), bk);
key = [];
for i in range(4):
k_cand = [];
k_cand.append(int(i/2));
k_cand.append(int(i%2));
key.append(k + k_cand);
pt.append(decrypt(ct, k + k_cand));
return [pt, key];
sdes = SimplifiedDES();
k = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1];
m = 'Top Secret';
print "Message = ", m;
bk = [1, 1, 1, 1, 1, 0, 0, 0, 0, 0];
ct = subverted_encrypt(bk, k, m);
print "Fake IV = ", ct[0];
print "Ciphertext = ", ct[1:];
pt, key = subverted_decrypt(bk, ct);
print "Possible Plaintexts = ", pt;
print "Possible Keys = ", key;
found = 0;
ck = [];
for i in range(len(key)):
for t in pt[i]:
ascii = int(str(bin.encoding(t)), 2)
if ascii >= 32 and ascii <= 126:
found = 1;
ck = key[i];
continue;
else:
found = 0;
ck = [];
break;
if found == 1:
break;
if len(ck) > 0:
print "Correct Key = ", ck;
m = "NSA secret";
print "Next Message = ", m;
ct = subverted_encrypt(bk, k, m);
print "IV = ", ct[0];
print "Ciphertext = ", ct[1:];
pt = decrypt(ct, ck);
print "Plaintext = ", pt;
else:
print "Cannot find key"
Message = Top Secret
Fake IV = 00100011
Ciphertext = ['00111001', '11011010', '11101000', '01111111', '10100000', '00000001', '10100110', '10110011', '01111100', '11001101']
Possible Plaintexts = ['\x9d\xa6\xbc\xec7\xa9o\xdb\t\xb8', '<\xa2u\xc8\xfe`\x0e\xba\xa8u', 'P\xce\xb9A2\x04nVA\xb9', 'Top Secret']
Possible Keys = [[0, 0, 0, 0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 1, 1, 1, 0, 1], [0, 0, 0, 0, 0, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]]
Correct Key = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
Next Message = NSA secret
IV = 00100101
Ciphertext = ['01001111', '00100011', '10100110', '01111101', '11100011', '01111101', '00110100', '01101011', '11100011', '10000111']
Plaintext = NSA secret