In [1]:
class Vector(object):
def __init__(self, length, values = []):
if(length % 4):
raise ValueError("Length has to be a multiple of 8")
self._value = [None for i in range(length)]
self._lock = [False for i in range(length)]
self._length = length
for pos, val in enumerate(values):
self[pos] = val
def __setitem__(self, iter_, item):
if(not isinstance(item, int)):
raise ValueError("Vector does not support {} items".format(type(item)))
if(not isinstance(iter_, int)):
raise ValueError("Vector indices have to be int, not {}".format(type(iter_)))
if(iter_ >= self._length or iter_ < 0):
raise IndexError("{} out of {}".format(iter_, range(self._length)))
if(self._lock[iter_]):
raise IndexError("Index {} already locked".format(iter_))
self._value[iter_] = item
self._lock[iter_] = True
def __getitem__(self, iter_):
if(isinstance(iter_, int)):
if(not iter_ in range(self._length)):
raise IndexError("Index {} out of {}".format(iter_, range(self._length)))
return self._value[iter_]
if(isinstance(iter_, slice)):
try:
return self._value[iter_]
except:
pass
raise IndexError("Slice {} out of {}".format(iter_, range(self._length)))
raise ValueError("Vector indices have to be int or slice, not {}".format(type(iter_)))
def __str__(self):
return "<Vector>({})".format(self._value)
def __repr__(self):
return "Vector({}, values = {})".format(self._length, repr(self._value))
def __len__(self):
return self._length
def __mul__(self, other):
if(isinstance(other, int)):
return Vector(self._length, values = [v * other for v in self._value])
raise ValueError("Cannot __mul__ Vector and {}".format(type(other)))
def __matmul__(self, other):
if(isinstance(other, Vector)):
return sum([ v1 * v2 for v1, v2 in zip(other._value, self._value)])
raise ValueError("Cannor __matmul__ Vector and {}".format(type(other)))
def _rmatmul__(self, other):
return self.__matmul__(other)
def __rmul__(self, other):
return self.__mul__(other)
def bytes_to_vectors(self, bytes_):
numbytes = len(bytes_)
numvectors = numbytes // (self._length // 8)
for vect in range(numvectors):
yield self.bytes_to_vector(bytes_)
bytes_ = bytes_[self._length // 8:]
if(len(bytes_) != 0):
yield self.bytes_to_vector(bytes_)
def bytes_to_vector(self, bytes_):
if(len(bytes_) < self._length // 8):
bytes_ = bytes_ + b"\x00" * ((self._length // 8) - len(bytes_))
vect = Vector(self._length)
for bytepos, byte in enumerate(bytes_[:self._length // 8]):
for shift in range(8):
vect[bytepos * 8 + shift] = ((byte & (1 << shift)) >> shift)
return vect
Das ist schonmal die erste Vectorimplementierung. (__matmul__
geht ab 3.5.2)
Einen ersten Verschlüsselungsvector kann man ganz leicht erzeugen.
Für einen Verschlüsselungsvector gilt:
v[k] > sum(v[:k])
Also kann man einen Vektor mit Zufallselementen so erzeugen:
v[k] = v[k - 1] * 2 + r
für alle k > 0; r sei eine Zufallszahl
Dann lässt sich ein einfacher Vectorgenerator so implementieren
In [2]:
def vgen(vect, rng):
vect[0] = rng()
for k in range(1, vect._length):
vect[k] = vect[k - 1] * 2 + rng()
Zunächst allerdings ein einfacherer Vector, bei dem
b * v = b
gilt.
In [3]:
vect = Vector(8)
current = 1
for pos in range(8):
vect[pos] = current
current *= 2
vect
Out[3]:
Dann kann das Verschlüsseln ja anfangen...
In [4]:
data = [ v for v in vect.bytes_to_vectors(b"Hallo, Welt!")]
for vector in data:
print(vector)
encrypted = [vect @ d for d in data]
for enc in encrypted:
print(enc)
In [5]:
def long_to_bytes(long_, frame_size):
res = []
for frame in range(frame_size):
res.append( (long_ & (0xff << (frame * 8))) >> (frame * 8))
return bytes(res)
def bytes_to_long(bytes_):
res = 0
for shift, byte in enumerate(bytes_):
res += byte << (shift * 8)
return res
def bytes_to_longs(bytes_, frame_size):
for frame in range(len(bytes_) // frame_size):
yield bytes_to_long(bytes_[:frame_size])
bytes_ = bytes_[frame_size:]
In [6]:
def decrypt(int_, vect):
res = []
for k in range(len(vect) + 1):
pos = len(vect) - k
if(int_ > sum(vect[:pos])):
res.append(1 << pos)
int_ -= vect[pos]
return long_to_bytes(sum(res), vect._length // 8)
decrypted = b"".join([decrypt(enc, vect) for enc in encrypted])
print(decrypted)
In [7]:
import socket, random
# WARNING: DO NOT USE random for real cryptographics!
sender, receiver = socket.socketpair()
vector = Vector(8)
rnd = lambda: random.randint(100, 900)
vgen(vector, rnd)
print(vector)
text = b"Attack in the dawn!"
data = vector.bytes_to_vectors(text)
encrypted = [vector @ d for d in data]
frame_size = max([e.bit_length() for e in encrypted]) // 8 + 1
print(frame_size)
to_send = b"".join([long_to_bytes(enc, frame_size) for enc in encrypted])
print("SENDING", to_send)
l = sender.send(to_send)
received = receiver.recv(l)
received = bytes_to_longs(received, frame_size)
decrypted = b"".join([decrypt(r, vector) for r in received])
print(decrypted)
print(decrypted == text)
Natürlich muss man die frame_size
auch mit verschicken!
In [8]:
import socket, random
# WARNING: DO NOT USE random for real cryptographics!
sender, receiver = socket.socketpair()
vector = Vector(64)
rnd = lambda: random.randint(100, 2000)
vgen(vector, rnd)
print(vector)
text = b"Attack in the dawn!\n\nIt is extremely important that no enemies can read this text!\n they could organize a counter strike! padbytes "
data = vector.bytes_to_vectors(text)
encrypted = [vector @ d for d in data]
frame_size = max([e.bit_length() for e in encrypted]) // 8 + 1
print(frame_size)
to_send = b"".join([long_to_bytes(enc, frame_size) for enc in encrypted])
print("SENDING", to_send)
l = sender.send(to_send)
received = receiver.recv(l)
received = bytes_to_longs(received, frame_size)
decrypted = b"".join([decrypt(r, vector) for r in received])
print(decrypted)
print(decrypted == text)
In [9]:
print(text.decode("UTF-8"))
print("#####################")
print(decrypted.decode("UTF-8"))
Das hier ist natürlich kein sicheres Verschlüsselungssystem. Dafür gibt es einige Gründe, nur ein paar davon sind