1.2b julia done

This commit is contained in:
Kaushik Narayan R 2024-02-12 00:33:05 -07:00
parent 8b7829025e
commit 48f130fe73
17 changed files with 1185 additions and 26 deletions

View File

@ -1,7 +1,6 @@
a - caesar
left shift:
ROPORTIONATELYQUIDSMEDALLIONMICHELOBSICEBOXWEAKFISHSCUSTOMSINDOCTRINATEINQUIRERSANCTIFIEDCHAFFSEISMOLOGYSPERCALESCHISHOLMSBRAGGERSSTUMBLEDTWERKINGUROLOGISTSPROSPECTUSESBUNSENPRISSIESTINQUIRINGBRANCHES
(right shift gave:)
NKLKNPEKJWPAHUMQEZOIAZWHHEKJIEYDAHKXOEYAXKTSAWGBEODOYQOPKIOEJZKYPNEJWPAEJMQENANOWJYPEBEAZYDWBBOAEOIKHKCUOLANYWHAOYDEODKHIOXNWCCANOOPQIXHAZPSANGEJCQNKHKCEOPOLNKOLAYPQOAOXQJOAJLNEOOEAOPEJMQENEJCXNWJYDAO
which is not english text, also sha512 sum doesn't match
@ -10,8 +9,13 @@ a - julia
(the thing has a space at the end lol)
mile Vinay and Joseph Gaussinthough not with the speed and ease of a typewriter keyboard. Rather it was the assimilation of encipherment into the overall communication process. Vernam created what came to be called "on-line encipherment" (because it was done directly on the open telegraph circuit) to distinguish it from the old, separate, off-line encipherment. He freed a fundamental process in cryptography from the shackles of time and error. He eliminated a human beingthe cipher clerkfrom the chain of communication. His great contribution was to bring to cryptography the automation that had benefited mankind so much in so many fields of endeavor. These values were immediately recognized, and Ver-nam's idea quickly kicked up a flurry of activity. He put it down on paper in a sketch dated December 17. A.T. & T. notified the Navy, with which it had worked closely in a communications demonstration the previous year, and on February 18, 1918, Vernam, Parker, Lyman F. Morehouse, equipment
b - caesar
simply bruteforce, only 26 possibilities
key shift 3, left shift gives:
EMASWALDSRINGSHIGHLANDSSNOOTIESTASCENDSETTERSFLARESTHINKINGSCARPINGSEDERSSWELLEDMERCILESSOVERSENSITIVEADVENTURERDIVANSYPSILANTISJOCASTAHEADRESTSDISSERTATIONSJOISTSBUSSSERAPUPPETRYSBUNTEDAMPHITHEATRESSTEREOSUNJUSTIFIEDZEPHYRUSSABDICATIONSHUSSERLPALMISTFERALMANNERLEONIDSDILLONSWHEREFORESFERTILIZEDDUCKBILLDUNNESSCORESHAIRCUTBOTTICELLIREPELGLIDESFELICESBRAINSTORMINGSCLEMENCYREDOINGMEDICAIDSBLUNDERBUSS
b - julia
gzip header includes filename. filename is 14 chars, key is 12 chars, so first and thirteenth character have same key byte, get rotation from that and then
(the thing has a space at the end lol, also intentional typos?)
All work and no play makes Jack a dull boy.All work and no play makes Jack a dull boy.All woRk and no play makes Jack a dull boy.All work and ho play maoes Jack a dull boy.All work and no plAy makes Jack a dull boy.Alk work and no plAy makes Jack a dull boy.All work and no play makes Jack a dull boy.All work and no pLay maksa Jack a dull boy.All work and no play makes Jack a dull boy.All

View File

@ -1,7 +1,7 @@
with open("3/withoutkey/ciphertext.txt", "r") as caesar_cipher_file:
caesar_cipher_content = caesar_cipher_file.read()
for key_shift in range(1,27): # both left and right, 13x2=26
for key_shift in range(1,14): # both left and right, 13x2=26
print("key shift", key_shift)
caesar_plaintext_content_left_shift = ""

View File

@ -0,0 +1,44 @@
# Read the top of streamy.py for usage, and see line 23 of this file
from aes import AESCipher
from Crypto.Util.number import bytes_to_long
from Crypto.Util.number import long_to_bytes
import textwrap
import fileinput
def wrap64(string):
return '\n'.join(textwrap.wrap(string,64))
bitsknownint = 0
for line in fileinput.input():
if len(line) > 10:
firstline = line
if (len(line) % 2 == 0):
firstline = '0' + line
continue
x, y = map(int, line.split())
hint = ((x - 1) << 7) | (y - 32)
tryabit = hint & 1
i = hint >> 1
# All you have to do is figure out what YYY and ZZZ should be...
if (YYY):
ZZZ
#while (len(bitsknown) < 256):
# i = 255 - len(bitsknown)
#for tryabit in ['0', '1']:
#hint = (i << 1) + int(tryabit)
#bitsknown = str(tryabit) + bitsknown
AESkey = long_to_bytes(bitsknownint, 32)
aes = AESCipher(AESkey)
print(firstline)
print(len(firstline))
eavesdroppedaes = bytes.fromhex(firstline)
#('088d72fda25863ae81a27ddc286ee8ffef55bdcd0eeee4487fa42cb9c012155e6c38a32d741c68aaa86fda4c9878cbb4')
print('Recovered plaintext is: {}'.format(aes.decrypt(eavesdroppedaes)[:400]))
printme = "{0:b}".format(bitsknownint)
while len(printme) < 256:
printme = '0' + printme
print(wrap64(printme))

Binary file not shown.

View File

@ -0,0 +1,409 @@
import string
import copy
# Modified for CSE 365 by reducing the number of rounds
# Create a plaintext.bin and key.bin to test...
# dd if=/dev/urandom of=key.bin bs=16 count=1
# dd if=/dev/urandom of-plaintext.bin bs=1024 count=1024
# python2 rijndael-fewerrounds.py
# md5sum *
#############################################################################
# Original code ported from the Java reference code by Bram Cohen, April 2001,
# with the following statement:
#
# this code is public domain, unless someone makes
# an intellectual property claim against the reference
# code, in which case it can be made public domain by
# deleting all the comments and renaming all the variables
#
class Rijndael(object):
"""
A pure python (slow) implementation of rijndael with a decent interface.
To do a key setup::
r = Rijndael(key, block_size = 16)
key must be a string of length 16, 24, or 32
blocksize must be 16, 24, or 32. Default is 16
To use::
ciphertext = r.encrypt(plaintext)
plaintext = r.decrypt(ciphertext)
If any strings are of the wrong length a ValueError is thrown
"""
@classmethod
def create(cls):
if hasattr(cls, "RIJNDAEL_CREATED"):
return
# [keysize][block_size]
#cls.num_rounds = {16: {16: 10, 24: 12, 32: 14}, 24: {16: 12, 24: 12, 32: 14}, 32: {16: 14, 24: 14, 32: 14}}
# Modified for CSE 365 to reduce rounds to 3
cls.num_rounds = {16: {16: 3, 24: 3, 32: 3}, 24: {16: 3, 24: 3, 32: 3}, 32: {16: 3, 24: 3, 32: 3}}
cls.shifts = [[[0, 0], [1, 3], [2, 2], [3, 1]],
[[0, 0], [1, 5], [2, 4], [3, 3]],
[[0, 0], [1, 7], [3, 5], [4, 4]]]
A = [[1, 1, 1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 0],
[0, 0, 0, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 1, 1, 1, 1],
[1, 1, 0, 0, 0, 1, 1, 1],
[1, 1, 1, 0, 0, 0, 1, 1],
[1, 1, 1, 1, 0, 0, 0, 1]]
# produce log and alog tables, needed for multiplying in the
# field GF(2^m) (generator = 3)
alog = [1]
for i in xrange(255):
j = (alog[-1] << 1) ^ alog[-1]
if j & 0x100 != 0:
j ^= 0x11B
alog.append(j)
log = [0] * 256
for i in xrange(1, 255):
log[alog[i]] = i
# multiply two elements of GF(2^m)
def mul(a, b):
if a == 0 or b == 0:
return 0
return alog[(log[a & 0xFF] + log[b & 0xFF]) % 255]
# substitution box based on F^{-1}(x)
box = [[0] * 8 for i in xrange(256)]
box[1][7] = 1
for i in xrange(2, 256):
j = alog[255 - log[i]]
for t in xrange(8):
box[i][t] = (j >> (7 - t)) & 0x01
B = [0, 1, 1, 0, 0, 0, 1, 1]
# affine transform: box[i] <- B + A*box[i]
cox = [[0] * 8 for i in xrange(256)]
for i in xrange(256):
for t in xrange(8):
cox[i][t] = B[t]
for j in xrange(8):
cox[i][t] ^= A[t][j] * box[i][j]
# cls.S-boxes and inverse cls.S-boxes
cls.S = [0] * 256
cls.Si = [0] * 256
for i in xrange(256):
cls.S[i] = cox[i][0] << 7
for t in xrange(1, 8):
cls.S[i] ^= cox[i][t] << (7-t)
cls.Si[cls.S[i] & 0xFF] = i
# T-boxes
G = [[2, 1, 1, 3],
[3, 2, 1, 1],
[1, 3, 2, 1],
[1, 1, 3, 2]]
AA = [[0] * 8 for i in xrange(4)]
for i in xrange(4):
for j in xrange(4):
AA[i][j] = G[i][j]
AA[i][i+4] = 1
for i in xrange(4):
pivot = AA[i][i]
if pivot == 0:
t = i + 1
while AA[t][i] == 0 and t < 4:
t += 1
assert t != 4, 'G matrix must be invertible'
for j in xrange(8):
AA[i][j], AA[t][j] = AA[t][j], AA[i][j]
pivot = AA[i][i]
for j in xrange(8):
if AA[i][j] != 0:
AA[i][j] = alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255]
for t in xrange(4):
if i != t:
for j in xrange(i+1, 8):
AA[t][j] ^= mul(AA[i][j], AA[t][i])
AA[t][i] = 0
iG = [[0] * 4 for i in xrange(4)]
for i in xrange(4):
for j in xrange(4):
iG[i][j] = AA[i][j + 4]
def mul4(a, bs):
if a == 0:
return 0
r = 0
for b in bs:
r <<= 8
if b != 0:
r = r | mul(a, b)
return r
cls.T1 = []
cls.T2 = []
cls.T3 = []
cls.T4 = []
cls.T5 = []
cls.T6 = []
cls.T7 = []
cls.T8 = []
cls.U1 = []
cls.U2 = []
cls.U3 = []
cls.U4 = []
for t in xrange(256):
s = cls.S[t]
cls.T1.append(mul4(s, G[0]))
cls.T2.append(mul4(s, G[1]))
cls.T3.append(mul4(s, G[2]))
cls.T4.append(mul4(s, G[3]))
s = cls.Si[t]
cls.T5.append(mul4(s, iG[0]))
cls.T6.append(mul4(s, iG[1]))
cls.T7.append(mul4(s, iG[2]))
cls.T8.append(mul4(s, iG[3]))
cls.U1.append(mul4(t, iG[0]))
cls.U2.append(mul4(t, iG[1]))
cls.U3.append(mul4(t, iG[2]))
cls.U4.append(mul4(t, iG[3]))
# round constants
cls.rcon = [1]
r = 1
for t in xrange(1, 30):
r = mul(2, r)
cls.rcon.append(r)
cls.RIJNDAEL_CREATED = True
def __init__(self, key, block_size = 16):
# create common meta-instance infrastructure
self.create()
if block_size != 16 and block_size != 24 and block_size != 32:
raise ValueError('Invalid block size: ' + str(block_size))
if len(key) != 16 and len(key) != 24 and len(key) != 32:
raise ValueError('Invalid key size: ' + str(len(key)))
self.block_size = block_size
ROUNDS = Rijndael.num_rounds[len(key)][block_size]
BC = block_size / 4
# encryption round keys
Ke = [[0] * BC for i in xrange(ROUNDS + 1)]
# decryption round keys
Kd = [[0] * BC for i in xrange(ROUNDS + 1)]
ROUND_KEY_COUNT = (ROUNDS + 1) * BC
KC = len(key) / 4
# copy user material bytes into temporary ints
tk = []
for i in xrange(0, KC):
tk.append((ord(key[i * 4]) << 24) | (ord(key[i * 4 + 1]) << 16) |
(ord(key[i * 4 + 2]) << 8) | ord(key[i * 4 + 3]))
# copy values into round key arrays
t = 0
j = 0
while j < KC and t < ROUND_KEY_COUNT:
Ke[t / BC][t % BC] = tk[j]
Kd[ROUNDS - (t / BC)][t % BC] = tk[j]
j += 1
t += 1
tt = 0
rconpointer = 0
while t < ROUND_KEY_COUNT:
# extrapolate using phi (the round key evolution function)
tt = tk[KC - 1]
tk[0] ^= (Rijndael.S[(tt >> 16) & 0xFF] & 0xFF) << 24 ^ \
(Rijndael.S[(tt >> 8) & 0xFF] & 0xFF) << 16 ^ \
(Rijndael.S[ tt & 0xFF] & 0xFF) << 8 ^ \
(Rijndael.S[(tt >> 24) & 0xFF] & 0xFF) ^ \
(Rijndael.rcon[rconpointer] & 0xFF) << 24
rconpointer += 1
if KC != 8:
for i in xrange(1, KC):
tk[i] ^= tk[i-1]
else:
for i in xrange(1, KC / 2):
tk[i] ^= tk[i-1]
tt = tk[KC / 2 - 1]
tk[KC / 2] ^= (Rijndael.S[ tt & 0xFF] & 0xFF) ^ \
(Rijndael.S[(tt >> 8) & 0xFF] & 0xFF) << 8 ^ \
(Rijndael.S[(tt >> 16) & 0xFF] & 0xFF) << 16 ^ \
(Rijndael.S[(tt >> 24) & 0xFF] & 0xFF) << 24
for i in xrange(KC / 2 + 1, KC):
tk[i] ^= tk[i-1]
# copy values into round key arrays
j = 0
while j < KC and t < ROUND_KEY_COUNT:
Ke[t / BC][t % BC] = tk[j]
Kd[ROUNDS - (t / BC)][t % BC] = tk[j]
j += 1
t += 1
# inverse MixColumn where needed
for r in xrange(1, ROUNDS):
for j in xrange(BC):
tt = Kd[r][j]
Kd[r][j] = Rijndael.U1[(tt >> 24) & 0xFF] ^ \
Rijndael.U2[(tt >> 16) & 0xFF] ^ \
Rijndael.U3[(tt >> 8) & 0xFF] ^ \
Rijndael.U4[ tt & 0xFF]
self.Ke = Ke
self.Kd = Kd
def encrypt(self, plaintext):
if len(plaintext) != self.block_size:
raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(plaintext)))
Ke = self.Ke
BC = self.block_size / 4
ROUNDS = len(Ke) - 1
if BC == 4:
Rijndael.SC = 0
elif BC == 6:
Rijndael.SC = 1
else:
Rijndael.SC = 2
s1 = Rijndael.shifts[Rijndael.SC][1][0]
s2 = Rijndael.shifts[Rijndael.SC][2][0]
s3 = Rijndael.shifts[Rijndael.SC][3][0]
a = [0] * BC
# temporary work array
t = []
# plaintext to ints + key
for i in xrange(BC):
t.append((ord(plaintext[i * 4 ]) << 24 |
ord(plaintext[i * 4 + 1]) << 16 |
ord(plaintext[i * 4 + 2]) << 8 |
ord(plaintext[i * 4 + 3]) ) ^ Ke[0][i])
# apply round transforms
for r in xrange(1, ROUNDS):
for i in xrange(BC):
a[i] = (Rijndael.T1[(t[ i ] >> 24) & 0xFF] ^
Rijndael.T2[(t[(i + s1) % BC] >> 16) & 0xFF] ^
Rijndael.T3[(t[(i + s2) % BC] >> 8) & 0xFF] ^
Rijndael.T4[ t[(i + s3) % BC] & 0xFF] ) ^ Ke[r][i]
t = copy.copy(a)
# last round is special
result = []
for i in xrange(BC):
tt = Ke[ROUNDS][i]
result.append((Rijndael.S[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
result.append((Rijndael.S[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
result.append((Rijndael.S[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
result.append((Rijndael.S[ t[(i + s3) % BC] & 0xFF] ^ tt ) & 0xFF)
return string.join(map(chr, result), '')
def decrypt(self, ciphertext):
if len(ciphertext) != self.block_size:
raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(ciphertext)))
Kd = self.Kd
BC = self.block_size / 4
ROUNDS = len(Kd) - 1
if BC == 4:
Rijndael.SC = 0
elif BC == 6:
Rijndael.SC = 1
else:
Rijndael.SC = 2
s1 = Rijndael.shifts[Rijndael.SC][1][1]
s2 = Rijndael.shifts[Rijndael.SC][2][1]
s3 = Rijndael.shifts[Rijndael.SC][3][1]
a = [0] * BC
# temporary work array
t = [0] * BC
# ciphertext to ints + key
for i in xrange(BC):
t[i] = (ord(ciphertext[i * 4 ]) << 24 |
ord(ciphertext[i * 4 + 1]) << 16 |
ord(ciphertext[i * 4 + 2]) << 8 |
ord(ciphertext[i * 4 + 3]) ) ^ Kd[0][i]
# apply round transforms
for r in xrange(1, ROUNDS):
for i in xrange(BC):
a[i] = (Rijndael.T5[(t[ i ] >> 24) & 0xFF] ^
Rijndael.T6[(t[(i + s1) % BC] >> 16) & 0xFF] ^
Rijndael.T7[(t[(i + s2) % BC] >> 8) & 0xFF] ^
Rijndael.T8[ t[(i + s3) % BC] & 0xFF] ) ^ Kd[r][i]
t = copy.copy(a)
# last round is special
result = []
for i in xrange(BC):
tt = Kd[ROUNDS][i]
result.append((Rijndael.Si[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
result.append((Rijndael.Si[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
result.append((Rijndael.Si[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
result.append((Rijndael.Si[ t[(i + s3) % BC] & 0xFF] ^ tt ) & 0xFF)
return string.join(map(chr, result), '')
# @staticmethod
# def encrypt_block(key, block):
# return Rijndael(key, len(block)).encrypt(block)
# @staticmethod
# def decrypt_block(key, block):
# return Rijndael(key, len(block)).decrypt(block)
@staticmethod
def test():
def t(kl, bl):
b = 'b' * bl
r = Rijndael('a' * kl, bl)
x = r.encrypt(b)
assert x != b
assert r.decrypt(x) == b
t(16, 16)
t(16, 24)
t(16, 32)
t(24, 16)
t(24, 24)
t(24, 32)
t(32, 16)
t(32, 24)
t(32, 32)
# Rijndael
#############################################################################
key = open('key.bin', 'rb').read()
plaintext = open('plaintext.bin', 'rb').read()
while len(plaintext) % 16 != 0:
plaintext = plaintext + b'\0'
r = Rijndael(key, block_size = 16)
ciphertext = b''
for i in range(0, len(plaintext), 16):
c = bytes(r.encrypt(plaintext[i:i+16]))
ciphertext = ciphertext + c
f = open('ciphertext.bin', 'wb')
f.write(bytes(ciphertext))
f.close()
cipertext = open('ciphertext.bin', 'rb').read()
while len(ciphertext) % 16 != 0:
ciphertext = ciphertext + b'\0'
plaintext = b''
for i in range(0, len(ciphertext), 16):
p = r.decrypt(ciphertext[i:i+16])
plaintext = plaintext + p
f = open('plaintext-backatyou.bin', 'wb')
f.write(bytes(plaintext))
f.close()
print('Done.')

Binary file not shown.

View File

@ -0,0 +1,53 @@
cse468encrypt.py is used for caesar and julia ciphers for Homeworks 1.2 and
1.3.
The rest are sample files to try out how the RSA and AES encryptions work for
Homework 1.4. The recommended usage of this is to use your own loopback IP
(127.0.0.1) in two terminal windows (so you can see in I/O of the server and
client).
In addition, the serverPublicKey is the *actual* public key used in the lab, so
that's the one the attacker used in the actual attack.
File | Description |
-----------------+------------------------------------------------------------+
aes.py | Very basic classes for interfacing with AES and RSA |
rsa.py | methods |
-----------------+------------------------------------------------------------+
key.pub | A sample public key |
-----------------+------------------------------------------------------------+
key | A sample private key |
-----------------+------------------------------------------------------------+
sample_client.py | A client that encrypts the AES key and the word "True" and |
| sends it to the server |
-----------------+------------------------------------------------------------+
sample_server.py | A server that listens for messages from the client, |
| decrypts the client's message, capitalizes the plaintext, |
| and returns an encrypted version |
-----------------+------------------------------------------------------------+
serverPublicKey | The public key used by the true server for the lab |
-----------------+------------------------------------------------------------+
README.txt | This README |
-----------------+------------------------------------------------------------+
The python files should be run using python3, and you may need to install some
python packages depending on your environment, like:
pip3 install pycrypto
You can run the programs in the following way from the terminal:
$ python3 sample_server.py -p 10047 -kp key.pub -ks key
$ python3 sample_client.py -ip 127.0.0.1 -p 10047 -f key.pub
The first call stands up the server that listens on the specified port (10047
in this example). The -kp flag is the public key you'd like the server to use,
and -ks is the private key.
The second call kicks off a client on the loopback at the same port with -f
specifying the shared public key of the server.

View File

@ -0,0 +1,20 @@
from Crypto.Cipher import AES
class AESCipher:
def __init__(self, key):
self.key = key
def encrypt(self, raw):
cipher = AES.new(self.key, AES.MODE_ECB)
if len(raw) % 16 != 0:
raw += ' ' * (16 - (len(raw) % 16))
return cipher.encrypt(raw)
def decrypt(self, enc):
cipher = AES.new(self.key, AES.MODE_ECB)
overflow = len(enc) % 16
if overflow != 0:
enc += b' ' * (16 - overflow)
return cipher.decrypt(enc)

View File

@ -0,0 +1,132 @@
import argparse
import os
import time
import socket
import sys
from aes import AESCipher
from Crypto.PublicKey import RSA
from Crypto.Util.number import bytes_to_long
from Crypto.Util.number import long_to_bytes
import textwrap
def wrap64(string):
return '\n'.join(textwrap.wrap(string,64))
# Handle command-line arguments
parser = argparse.ArgumentParser()
parser.add_argument("-ip", "--ipaddress",
help='ip address where the server is running',
default='127.0.0.1', # Defaults to loopback
required=True)
parser.add_argument("-p", "--port",
help='port where the server is listening on',
required=True)
parser.add_argument("-f", "--publickey",
help='name of public key',
default='serverPublicKey',
required=False)
parser.add_argument("-v", "--verbose",
help="print out extra info to stdout",
default='True',
required=False)
parser.add_argument("-e", "--eavesdrop",
help="filename of eavesdrop",
default='True',
required=False)
args = parser.parse_args()
f = open(args.eavesdrop, "rb")
b = f.read()
f.close()
# load server's public key
serverPublicKeyFileName = args.publickey
key = ""
with open(serverPublicKeyFileName, 'r') as f:
key = RSA.importKey(f.read())
MESSAGE_LENGTH = 2048
# 256 byte RSA-encrypted AES key from client-server Wireshark capture for default 'True' message
eavesdroppedrsa = b[0:256] #bytearray.fromhex('4a04ac1ffcc305c4c5f0daaeca07bca5be7cc795f812bd57d96933904ec4433d5033bae1729a6e0fae3d62cc081ed51111db6cfe96b2d84c633c827662bc076c83d401bbbb02a0d454b6fb6ab355be62e9dec8542741f2583b49d0794230ffdcdc6aebf444e139f69594cd4cfdc544178611027757cf534c725384a0e35b2eee66772261bc49de4666f9cb16b94e32335cce727664032058259a6ff6e31a110f4f8c03f1ec166a656269c1a126a587d4e472cc082bd08df6c50b2567e29798c84f7abd605aef66a46fdb471c5bad7c02071923a210bbfe236e5a5b32359d12040a37c9db2785f1d11faa2619b617b6deeb7da0011fbba82e44246aac99231d42')
bitsknown = ''
while (len(bitsknown) < 256):
i = 255 - len(bitsknown)
shifty = pow(2, i * key.e, key.n)
sessionkey = (bytes_to_long(eavesdroppedrsa) * shifty) % key.n
for tryabit in ['0', '1']:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
hint = (i << 1) + int(tryabit)
print(hint)
#sock.setsockopt(socket.SOL_TCP, socket.TCP_MAXSEG, 500 + hint)
sock.setsockopt(socket.SOL_IP, socket.IP_TTL, hint % 128 + 32)
differentipaddress = "127.0.0." + str((hint >> 7) + 1)
print(differentipaddress)
server_address = (differentipaddress, int(args.port))
#server_address = (args.ipaddress, int(args.port))
sock.connect(server_address)
sock.settimeout(2)
AESkeytry = long_to_bytes(int(tryabit + bitsknown + '0'*i, 2), 32)
print('guessing...\n{}'.format(wrap64(tryabit + bitsknown + '0'*i)))
aes = AESCipher(AESkeytry)
answer = b''
try:
message = aes.encrypt('GoSeeCal')
msg = long_to_bytes(sessionkey, 256) + message
sock.sendall(msg)
amount_received = 0
amount_expected = len(message)
if amount_expected % 16 != 0:
amount_expected += (16 - (len(message) % 16))
if amount_expected > amount_received:
while amount_received < amount_expected:
data = sock.recv(MESSAGE_LENGTH)
amount_received += len(data)
answer += data
except Exception as e:
print(e)
else:
#messageresult = (aes.decrypt(answer))
if aes.decrypt(answer).strip() == b'GOSEECAL':
bitsknown = str(tryabit) + bitsknown
break
finally:
sock.close()
AESkey = long_to_bytes(int(bitsknown, 2), 32)
aes = AESCipher(AESkey)
eavesdroppedaes = b[256:] #bytes.fromhex('088d72fda25863ae81a27ddc286ee8ffef55bdcd0eeee4487fa42cb9c012155e6c38a32d741c68aaa86fda4c9878cbb4')
print('Recovered plaintext is: {}'.format(aes.decrypt(eavesdroppedaes)))
print('Sending to server...')
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (args.ipaddress, int(args.port))
sock.connect(server_address)
sock.settimeout(2)
aes = AESCipher(AESkey)
answer = b''
sessionkey = bytes_to_long(eavesdroppedrsa)
try:
message = eavesdroppedaes
msg = long_to_bytes(sessionkey, 256) + message
sock.sendall(msg)
amount_received = 0
amount_expected = len(message)
if amount_expected % 16 != 0:
amount_expected += (16 - (len(message) % 16))
if amount_expected > amount_received:
while amount_received < amount_expected:
data = sock.recv(MESSAGE_LENGTH)
amount_received += len(data)
answer += data
except Exception as e:
print(e)
else:
print(aes.decrypt(answer).strip())
finally:
sock.close()

View File

@ -0,0 +1,94 @@
import argparse
import os
import time
#import socket
import sys
import string
#from aes import AESCipher
#from Crypto.PublicKey import RSA
# Handle command-line arguments
parser = argparse.ArgumentParser()
parser.add_argument("-c", "--cipher",
help='cipher... caesar or julia',
required=True)
parser.add_argument("-d", "--decrypt",
help='Decrypt a file',
required=False)
parser.add_argument("-e", "--encrypt",
help='Encrypt a file',
required=False)
parser.add_argument("-o", "--outfile",
help='Output file',
required=False)
args = parser.parse_args()
encrypting = True
def lrot(n, d): return ((n << d)|(n >> (8 - d)))&0xff
try:
ciphertext = open(args.decrypt, "rb").read()
try:
plaintext = open(args.encrypt, "rb").read()
print("You can't specify both -e and -d")
exit(1)
except:
encrypting = False
except:
try:
plaintext = open(args.encrypt, "rb").read()
except:
print("Input file error (did you specify -e or -d?)")
exit(1)
try:
whichcipher = args.cipher
if (whichcipher == 'julia') or (whichcipher == 'caesar'):
output = open(args.outfile, "wb")
else:
print('Available ciphers are julia and caesar, case sensitive')
exit(1)
except:
print("Output file error or you didn't specify cipher")
exit(1)
if (encrypting):
if whichcipher == 'julia':
keybytes = bytes(os.urandom(13))
keyshift = keybytes[0] % 7 + 1
keyxor = []
keyxorasstring = ""
for i in range(1, 13):
keyxor.append(ord(string.ascii_letters[keybytes[i] % len(string.ascii_letters)]))
keyxorasstring = keyxorasstring + chr(keyxor[i-1])
print('Key is shifting by ' + str(keyshift) + ' and XORing with ' + keyxorasstring)
ciphertext = []
for i in range(0, len(plaintext)):
ciphertext.append(lrot(plaintext[i], keyshift) ^ keyxor[i % len(keyxor)])
output.write(bytes(ciphertext))
output.close
elif whichcipher == 'caesar':
keybytes = bytes(os.urandom(1))
keyrotate = int(keybytes[0] % 25) + 1
print('Key is ' + string.ascii_uppercase[keyrotate] + ' i.e. rotating by ' + str(keyrotate))
skipped = 0
ciphertext = ''
for i in range(0, len(plaintext)):
if chr(plaintext[i]) in string.ascii_uppercase:
p = plaintext[i] - ord('A')
c = chr(ord('A') + ((p + keyrotate) % 26))
ciphertext = ciphertext + c
else:
skipped = skipped + 1
output.write(ciphertext.encode('ascii'))
output.close
if skipped != 0:
print('Skipped ' + str(skipped) + ' bytes for not being capital letters')
else:
print('Should not have gotten here')
exit(1)

View File

@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr7GLK94LlBt4NvvzaiAb
YWrDeY6A0Bpmu92p2ZrYskKDKCMDGalJGX8bDS7eRTd2yiTu0tT5xdF/awv1Aeaw
vUszJdLCbN8oFOT/8XUho6qpGPeX1iVtEA0B1oa7TD8nIshV7d4lMqP41I5FED6w
R5fndVGE2ajRdS5yDZB+Mujyqpnl1vwHXxc1gm+shR2zpEO3fbuW/KI1TeO08aYC
OmLnAWZtNU0n4pIsupu1WMc2MGZh+zu6Hg+6gRhbB8NLXHC//lxIwYmnNjieIJu5
o0zP3KNxp0pNzwtGJqi1z9Rr42l+lTXrOTlcfYXAeML83agjUbUuavfDwLjlthMC
swIDAQAB
-----END PUBLIC KEY-----

View File

@ -0,0 +1,36 @@
from Crypto.PublicKey import RSA
class RSACipher:
def __init__(self, publicKeyFileName, privateKeyFileName):
"""
Generate a RSA key pair for server
"""
try:
f = open(privateKeyFileName, 'rb')
self.keys = RSA.importKey(f.read())
except FileNotFoundError:
self.keys = RSA.generate(2048)
self.publickey = self.keys.publickey()
# export public and private keys
privHandle = open(privateKeyFileName, 'wb')
privHandle.write(self.keys.exportKey('PEM'))
privHandle.close()
pubHandle = open(publicKeyFileName, 'wb')
pubHandle.write(self.keys.publickey().exportKey())
pubHandle.close()
self.publickey = self.keys.publickey()
def decrypt(self, ciphertext):
"""-
Decrypt a ciphertext
"""
return self.keys.decrypt(ciphertext)
def encrypt(self, message):
"""
Encrypt a message
"""
return self.publickey.encrypt(message, 32)

View File

@ -0,0 +1,124 @@
import argparse
import os
import time
import socket
import sys
from aes import AESCipher
from Crypto.PublicKey import RSA
# Handle command-line arguments
parser = argparse.ArgumentParser()
parser.add_argument("-ip", "--ipaddress",
help='ip address where the server is running',
default='127.0.0.1', # Defaults to loopback
required=True)
parser.add_argument("-p", "--port",
help='port where the server is listening on',
required=True)
parser.add_argument("-f", "--publickey",
help='name of public key',
default='serverPublicKey',
required=False)
parser.add_argument("-v", "--verbose",
help="print out extra info to stdout",
default='True',
required=False)
parser.add_argument("-m", "--messagefile",
help='what file the message should come from',
default='',
required=True)
parser.add_argument("-e", "--eavesdrop",
help='where to put eavesdropped stuff',
default='',
required=True)
args = parser.parse_args()
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect the socket to the port where the server is listening
server_address = (args.ipaddress, int(args.port))
sock.connect(server_address)
sock.settimeout(2)
AESKey = bytes(os.urandom(32))
while AESKey[0] == 0: # Make sure there aren't leading 0s
AESKey = bytes(os.urandom(32))
if args.verbose is True:
binKey = bin(int.from_bytes(AESKey, byteorder='big'))
print("Using AES key : {}".format(binKey))
# load server's public key
serverPublicKeyFileName = args.publickey
key = ""
with open(serverPublicKeyFileName, 'r') as f:
key = RSA.importKey(f.read())
MESSAGE_LENGTH = 2048
encryptedKey = key.encrypt(AESKey, 32)[0]
while len(encryptedKey) != 2048>>3:
#Python is weird about leading 0's, fix it up
encryptedKey = b'\x00' + encryptedKey
aes = AESCipher(AESKey)
try:
# Send data
try:
filetosend = open(args.messagefile, "r")
plaintext = filetosend.read()
filetosend.close()
print(plaintext)
message = aes.encrypt(plaintext)
except ValueError:
print("Client with port {} failed.".format(args.port),
file=sys.stderr)
exit(1)
fileforeavesdrop = open(args.eavesdrop, "wb")
msg = bytearray(encryptedKey + message)
# msg: AES key encrypted by the public key of RSA
# + message encrypted by the AES key
print('Sending: {}'.format(message.hex()))
sock.sendall(msg)
fileforeavesdrop.write(msg)
fileforeavesdrop.close()
# Look for the response
amount_received = 0
amount_expected = len(message)
# if amount_expected % 16 != 0:
# amount_expected += (16 - (len(message) % 16))
answer = b''
if amount_expected > amount_received:
while amount_received < amount_expected:
try:
data = sock.recv(MESSAGE_LENGTH)
print(data)
except socket.timeout as e:
err = e.args[0]
if err == 'timed out':
print('Connection timed out, waiting for retry',
file=sys.stderr)
time.sleep(1)
continue
else:
print('Another issue: {}'.format(e),
file=sys.stderr)
break
except socket.error as e:
print('Socket error: {}'.format(e),
file=sys.stderr)
break
amount_received += len(data)
answer += data
print('Received: {}'.format(aes.decrypt(answer)))
print('Succeeded for ' + args.messagefile)
finally:
sock.close()

View File

@ -0,0 +1,106 @@
import argparse
import os
import socket
from time import sleep
from rsa import RSACipher
from aes import AESCipher
import binascii
import string
def getSessionKey(rsa, cipher):
"""
Get the AES session key be decrypting the RSA ciphertext
"""
AESEncrypted = cipher[:256]
print('AESEncrypted...')
print(binascii.hexlify(AESEncrypted))
AESKey = rsa.decrypt(AESEncrypted)
return AESKey[(len(AESKey)-32):]
def myDecrypt(rsa, cipher):
"""
Decrypt the client message:
AES key encrypted by the
public RSA key of the server + message encrypted by the AES key
"""
messageEncrypted = cipher[256:]
print('messageEncrypted...')
print(binascii.hexlify(messageEncrypted))
AESKey = getSessionKey(rsa, cipher)
aes = AESCipher(AESKey)
return aes.decrypt(messageEncrypted)
def handle_client(sock, rsa):
print('Waiting for a connection...') # Wait for a conneciton
connection, client_address = sock.accept()
try:
# Receive the data
print("Recieving....")
cipher = connection.recv(2048)
print("Message Received...")
try:
message = myDecrypt(rsa, cipher)
print("Received as: {}".format(message))
#if not message.decode('utf-8').strip().isprintable():
# raise Exception("Not printable?")
aes = AESCipher(getSessionKey(rsa, cipher))
msg = aes.encrypt(message.upper())
except:
connection.sendall("Couldn't decrypt!".encode('utf-8'))
else:
print('decrypted msg is {}'.format(aes.decrypt(msg)))
print('message is {}'.format(message))
connection.sendall(msg)
finally:
# Clean up the connection
connection.close()
return True
# Main routine starts here
parser = argparse.ArgumentParser()
parser.add_argument("-p", "--port",
help='starting port where the server is listening on',
required=True)
parser.add_argument("-kp", "--publickey",
help='the public key for the server',
default='serverPublicKey',
required=False)
parser.add_argument("-ks", "--privatekey",
help='the private key for the server',
default='privateKey.pem',
required=False)
args = parser.parse_args()
port = int(args.port)
server_address = ('0.0.0.0', port)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Bind socket to port
try:
sock.bind(server_address)
except OSError:
print('Address {} already in use'.format(server_address))
# Listen for incoming connections
sock.listen(10)
#pid = os.fork()
#if pid == 0:
rsa = RSACipher(publicKeyFileName=args.publickey,
privateKeyFileName=args.privatekey)
while True:
finished = handle_client(sock, rsa)
if finished is True:
print("Processed client message on port {}".format(port))
#sleep(1)

View File

@ -0,0 +1,64 @@
# pip3 install pyshark
# Then ...
# python3 streamy.py mypcap.pcap | python3 buildkey.py
import pyshark
import sys
# open the pcap file, filtered for a single TCP stream
cap = pyshark.FileCapture(sys.argv[1])
tupledict = {}
datadict = {}
longeststreamlen = -1
skippy = -1
for p in cap:
if p.transport_layer == 'TCP':
stream = p.tcp.stream
if (int(p.tcp.dstport) == 10047):
try:
thisstream = p.data.data.binary_value
if (len(thisstream) > longeststreamlen):
longeststream = thisstream[256:]
longeststreamlen = len(thisstream)
skippy = stream
except AttributeError: # Skip the ACKs.
pass
#if (stream not in tupledict and
if(int(p.tcp.dstport) == 10047):
try:
tupledict[stream] = (p.ip.dst, p.ip.ttl)
except AttributeError: # Skip the ACKs.
pass
#if (stream not in datadict and
if(int(p.tcp.srcport) == 10047):
try:
#if (int(stream) == 190):
# print("PING")
datadict[stream] = p.data.data.binary_value
#if (int(stream) == 190):
# print("PONG")
except AttributeError as error: # Skip the ACKs.
#if (int(stream) == 190):
# print(error)
#val=p.all_fields
datadict[stream] = b'hello'
#print(val)
pass
print(longeststream.hex())
for packettuple in tupledict:
hinttuple = tupledict[packettuple]
if (packettuple in datadict):
if (packettuple != skippy):
if (datadict[packettuple] != b"Couldn't decrypt!"):
print(hinttuple[0][8:] + " " + hinttuple[1])
else:
#pass
print("Something was in tupledict but not datadict")
print("Stream is " + str(int(packettuple)))
exit(1)

View File

@ -1,4 +1,3 @@
import sys
import os
from itertools import cycle
import gzip
@ -8,30 +7,27 @@ def ror(n, rotations, width):
return (2**width - 1) & (n >> rotations | n << (width - rotations))
def rol(n, rotations, width):
return (2**width - 1) & (n << rotations | n >> (width - rotations))
with open("3/withkey/juliakey.txt", "r") as julia_key_file, open(
"3/withkey/juliaplaintext.txt.gz.enc", "rb"
) as julia_cipher_file:
julia_key_content = julia_key_file.read()
key_shift = int(julia_key_content.split()[4])
key_xor = julia_key_content.split()[-1]
print("key shift", key_shift)
print("key xor", key_xor)
julia_cipher_content = julia_cipher_file.read()
result = bytes()
for c_byte, k_byte in zip(julia_cipher_content, cycle(key_xor)):
tmp = c_byte ^ ord(k_byte)
# kinda misleading, question mentions that encryption rotates bits but didn't mention which direction
# imagine spending 3 hours thinking it's gzip when it turns out you rotate RIGHT
result += ror(c_byte ^ ord(k_byte), 1, 8).to_bytes(1, "big")
# gzip - write as bytes, read with decompression
with open("test.gz", "wb") as f:
f.write(result)
with gzip.open("test.gz", "r") as gf:
print("answer starts here-----"+gf.read().decode()+"-----ends here")
os.remove("test.gz")
key_shift = int(julia_key_content.split()[4])
key_xor = julia_key_content.split()[-1]
print("key shift", key_shift)
print("key xor", key_xor)
result = bytes()
for c_byte, k_byte in zip(julia_cipher_content, cycle(key_xor)):
tmp = c_byte ^ ord(k_byte)
# kinda dumb tangent: question mentions that encryption rotates bits but didn't mention which direction
# imagine spending 3 hours thinking the problem is gzip when it turns out you rotate RIGHT, not left
result += ror(tmp, 1, 8).to_bytes(1, "big")
# gzip - write as bytes, read with decompression
with open("test.gz", "wb") as f:
f.write(result)
with gzip.open("test.gz", "r") as gf:
print("answer starts here-----" + gf.read().decode() + "-----ends here")
os.remove("test.gz")

View File

@ -0,0 +1,68 @@
import sys
import os
from itertools import cycle
import gzip
def ror(n, rotations, width):
return (2**width - 1) & (n >> rotations | n << (width - rotations))
with open("3/withoutkey/secretfile.txt.gz.enc", "rb") as julia_cipher_file:
julia_cipher_content = julia_cipher_file.read()
# ASSUMPTION: gzip used with FNAME or FCOMMENT flag, and encodes the (known) filename after the initial 10-byte header
# if not, strat breaks down
filename = "secretfile.txt"
filename_bytes = filename.encode()
filename_bytes_enc = julia_cipher_content[10 : 10 + len(filename)]
# print("[+] Filename bytes:\t\t", filename_bytes.hex())
# print("[+] Filename bytes, encrypted:\t", filename_bytes_enc.hex())
key_length = 12
derived_rotation = 0
derived_key_bytes = bytearray(key_length)
# filename is 14 characters, key length is 12, so key wraps around, allowing us to check rotation amount
for byte in range(0, 256):
possible_key_byte = bytes([byte])
for possible_rotation in range(1, 8):
if (
ror(filename_bytes_enc[0] ^ possible_key_byte[0], possible_rotation, 8)
== filename_bytes[0]
and ror(
filename_bytes_enc[key_length] ^ possible_key_byte[0],
possible_rotation,
8,
)
== filename_bytes[key_length]
):
derived_rotation = possible_rotation
break
else:
continue
break
print("Rotation:", derived_rotation)
for idx in range(0, key_length):
for byte in range(0, 256):
possible_key_byte = bytes([byte])
if (
ror(filename_bytes_enc[idx] ^ possible_key_byte[0], derived_rotation, 8)
== filename_bytes[idx]
):
derived_key_bytes[(idx + 10) % key_length] = possible_key_byte[0]
break
print("Key:", derived_key_bytes.hex())
result = bytes()
for c_byte, k_byte in zip(julia_cipher_content, cycle(derived_key_bytes)):
result += ror(c_byte ^ k_byte, derived_rotation, 8).to_bytes(1, sys.byteorder)
# gzip - write as bytes, read with decompression
with open("test.gz", "wb") as f:
f.write(result)
with gzip.open("test.gz", "r") as gf:
print("answer starts here-----" + gf.read().decode() + "-----ends here")
os.remove("test.gz")