Compare commits
3
Commits
No files matched your search
@@ -0,0 +1 @@
|
|||||||
|
__pycache__/
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
"""
|
||||||
|
# Mode of Operation
|
||||||
|
|
||||||
|
so uhhh those diagrams are Shit Ass, so with the help of claude i turned it into python.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from itertools import batched
|
||||||
|
|
||||||
|
|
||||||
|
def AES(key, x):
|
||||||
|
"stub"
|
||||||
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
def chunk(message: bytes, size: int):
|
||||||
|
return batched(message, size) # yields tuples of `size` bytes
|
||||||
|
|
||||||
|
|
||||||
|
def xor_bytes(a, b):
|
||||||
|
return bytes(x ^ y for x, y in zip(a, b))
|
||||||
|
|
||||||
|
|
||||||
|
# --- ECB ---
|
||||||
|
def ecb(key, message):
|
||||||
|
"things go in things go out"
|
||||||
|
for block in chunk(message, 16):
|
||||||
|
yield AES(key, block) # message goes straight in
|
||||||
|
|
||||||
|
|
||||||
|
# --- CBC ---
|
||||||
|
def cbc(key, message, iv):
|
||||||
|
"y_i = AES(x_i ^ y_{i-1})"
|
||||||
|
prev = iv
|
||||||
|
for block in chunk(message, 16):
|
||||||
|
x_i = xor_bytes(block, prev) # XOR with previous ciphertext
|
||||||
|
prev = AES(key, x_i)
|
||||||
|
yield prev
|
||||||
|
|
||||||
|
|
||||||
|
# --- OFB ---
|
||||||
|
def ofb(key, message, iv):
|
||||||
|
"keystream s evolves on itself, we yield y_i = x_i ^ s_i"
|
||||||
|
keystream = iv
|
||||||
|
for block in chunk(message, 16):
|
||||||
|
keystream = AES(key, keystream) # encrypt previous *keystream*
|
||||||
|
yield xor_bytes(block, keystream)
|
||||||
|
# keystream feeds back, independent of ciphertext
|
||||||
|
|
||||||
|
|
||||||
|
# --- CFB ---
|
||||||
|
def cfb(key, message, iv):
|
||||||
|
"difference to OFB is that the y_i is coming back instead of s_i"
|
||||||
|
prev = iv
|
||||||
|
for block in chunk(message, 16):
|
||||||
|
keystream = AES(key, prev) # encrypt previous ciphertext
|
||||||
|
prev = xor_bytes(block, keystream)
|
||||||
|
yield prev # ciphertext feeds back, not keystream
|
||||||
|
|
||||||
|
|
||||||
|
# --- CTR ---
|
||||||
|
def ctr(key, message, nonce):
|
||||||
|
"ts is so easy to understand in python"
|
||||||
|
for i, block in enumerate(chunk(message, 16)):
|
||||||
|
x_i = nonce + i.to_bytes(8) # counter, message never touches AES
|
||||||
|
yield xor_bytes(block, AES(key, x_i)) # WHATTTTT NO FUCKING WAY
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
import math
|
||||||
|
|
||||||
|
|
||||||
|
class Elgamal:
|
||||||
|
def __init__(self, p: int, alpha: int, d: int) -> None:
|
||||||
|
"contract: p is prime, and"
|
||||||
|
if not 0 <= alpha < p or math.gcd(alpha, p) != 1:
|
||||||
|
# set Z*_n is all i [0, n) st gcd(i, n) = 1, if n is prime thats jus the whole thing
|
||||||
|
raise ValueError()
|
||||||
|
if not 2 <= d <= p - 2:
|
||||||
|
raise ValueError()
|
||||||
|
self.p, self.alpha, self.d = p, alpha, d
|
||||||
|
self.beta = pow(alpha, d, p)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pubkey(self):
|
||||||
|
return (self.p, self.alpha, self.beta)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def privkey(self):
|
||||||
|
return self.d
|
||||||
|
|
||||||
|
def sig_gen(self, x: int, ke: int) -> tuple[int, int]:
|
||||||
|
if not 2 <= ke <= self.p - 2 or math.gcd(ke, self.p - 1) != 1:
|
||||||
|
raise ValueError()
|
||||||
|
r = pow(self.alpha, ke, self.p)
|
||||||
|
kei = pow(ke, -1, self.p - 1) # mod p - 1
|
||||||
|
s = ((x - self.d * r) * kei) % (self.p - 1)
|
||||||
|
return r, s
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def sig_verify(x: int, rs: tuple[int, int], pab: tuple[int, int, int]) -> bool:
|
||||||
|
r, s = rs
|
||||||
|
p, alpha, beta = pab
|
||||||
|
t = (pow(beta, r, p) * pow(r, s, p)) % p
|
||||||
|
return (t - pow(alpha, x, p)) % p == 0
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
bob = Elgamal(29, 2, 12)
|
||||||
|
assert bob.beta % 29 == 7
|
||||||
|
|
||||||
|
r, s = bob.sig_gen(26, 5)
|
||||||
|
assert r % 29 == 3, f"{r = }"
|
||||||
|
assert s % 28 == 26, f"{s = }"
|
||||||
|
assert Elgamal.sig_verify(26, (r, s), bob.pubkey)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -69,9 +69,12 @@ def theREALsmx(x, e, n):
|
|||||||
|
|
||||||
|
|
||||||
def realest(x=None, y=None, n=None):
|
def realest(x=None, y=None, n=None):
|
||||||
x = x or random.randint(-10e9, 10e9)
|
# no way
|
||||||
y = y or random.randint(-10e9, 10e9)
|
m10e9 = int(-10*10**9)
|
||||||
n = n or random.randint(2, 10e9)
|
p10e9 = int(10*10**9)
|
||||||
|
x = x or random.randint(m10e9, p10e9)
|
||||||
|
y = y or random.randint(m10e9, p10e9)
|
||||||
|
n = n or random.randint(2, p10e9)
|
||||||
# print(x, y, n)
|
# print(x, y, n)
|
||||||
if y < 0:
|
if y < 0:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from proto_rsa import LdaRsahh
|
from proto_rsa import LdaRSA
|
||||||
|
|
||||||
|
|
||||||
def e1():
|
def e1():
|
||||||
@@ -18,16 +18,16 @@ def e2():
|
|||||||
|
|
||||||
|
|
||||||
def e3():
|
def e3():
|
||||||
a = LdaRsahh(p=251, q=191, e=65537).enc(26729)
|
a = LdaRSA(p=251, q=191, e=65537).enc(26729)
|
||||||
|
|
||||||
b = LdaRsahh(p=233, q=151, d=9473).dec(29600)
|
b = LdaRSA(p=233, q=151, d=9473).dec(29600)
|
||||||
|
|
||||||
return a, b
|
return a, b
|
||||||
|
|
||||||
|
|
||||||
def e4():
|
def e4():
|
||||||
C = 412589464
|
C = 412589464
|
||||||
M = LdaRsahh(p=81401, q=27109, e=65537).dec(C)
|
M = LdaRSA(p=81401, q=27109, e=65537).dec(C)
|
||||||
return dec_ascii(M)
|
return dec_ascii(M)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
class Person:
|
||||||
|
def __init__(self, p: int, g: int, k: int):
|
||||||
|
self.p, self.g, self.k = p, g, k
|
||||||
|
self.s = None
|
||||||
|
|
||||||
|
def public_key(self, recieved: int | None = None) -> int:
|
||||||
|
return pow(recieved or self.g, self.k, self.p)
|
||||||
|
|
||||||
|
def recieve_public_key(self, K: int) -> int:
|
||||||
|
self.s = self.public_key(K)
|
||||||
|
return self.s
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
p = 23
|
||||||
|
g = 5
|
||||||
|
alice = Person(p, g, 4)
|
||||||
|
bob = Person(p, g, 3)
|
||||||
|
assert (
|
||||||
|
alice.recieve_public_key(bob.public_key())
|
||||||
|
== bob.recieve_public_key(alice.public_key())
|
||||||
|
== 18
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
print("done")
|
||||||
+23
-19
@@ -7,25 +7,35 @@ def inv(a: int, n: int):
|
|||||||
return pow(a, -1, n)
|
return pow(a, -1, n)
|
||||||
|
|
||||||
|
|
||||||
class LdaRsahh:
|
class LdaRSA:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
p: int,
|
p: int,
|
||||||
q: int,
|
q: int,
|
||||||
d: int | None = None,
|
*,
|
||||||
e: int | None = None,
|
e: int | None = None,
|
||||||
|
d: int | None = None,
|
||||||
ln_ops: Callable[[int, int], int] | None = None,
|
ln_ops: Callable[[int, int], int] | None = None,
|
||||||
):
|
):
|
||||||
|
"""
|
||||||
|
p and q is Prime.
|
||||||
|
|
||||||
|
ln = lcm(p-1,q-1)
|
||||||
|
|
||||||
|
e needs to be in range (1, ln) and be coprime with ln, and is the public key.
|
||||||
|
|
||||||
|
d s.t. d*e === 1 mod ln is the private key
|
||||||
|
"""
|
||||||
# operator.mul or math.lcm
|
# operator.mul or math.lcm
|
||||||
self._lnops: Callable[[int, int], int] = ln_ops or math.lcm
|
self._lnops: Callable[[int, int], int] = ln_ops or math.lcm
|
||||||
self._p, self._q = p, q
|
self.__p, self.__q = p, q
|
||||||
if d is None and e is None:
|
if d is None and e is None:
|
||||||
raise ValueError("at least d or e needs to be fed in")
|
raise ValueError("at least e or d needs to be fed in")
|
||||||
ln = self.ln
|
ln = self.ln
|
||||||
if e is None:
|
if e is None:
|
||||||
e = inv(d, ln) # type: ignore
|
e = inv(d, ln) # type: ignore
|
||||||
elif not 1 < e < ln:
|
# elif not 1 < e < ln:
|
||||||
e %= ln # bad
|
# e %= ln # bad
|
||||||
if not 1 < e < ln:
|
if not 1 < e < ln:
|
||||||
raise ValueError(f"{e = }, {ln = }, 1 < e < ln not satisfied")
|
raise ValueError(f"{e = }, {ln = }, 1 < e < ln not satisfied")
|
||||||
if math.gcd(e, ln) != 1:
|
if math.gcd(e, ln) != 1:
|
||||||
@@ -34,34 +44,28 @@ class LdaRsahh:
|
|||||||
)
|
)
|
||||||
if d is None:
|
if d is None:
|
||||||
d = inv(e, ln)
|
d = inv(e, ln)
|
||||||
self._d, self._e = d, e
|
self.__d, self.__e = d, e
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def n(self):
|
def n(self):
|
||||||
return self._p * self._q
|
return self.__p * self.__q
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def ln(self):
|
def ln(self):
|
||||||
return self._lnops((self._p - 1), (self._q - 1))
|
return self._lnops((self.__p - 1), (self.__q - 1))
|
||||||
|
|
||||||
# @property
|
|
||||||
# def p(self):
|
|
||||||
# return self._p
|
|
||||||
|
|
||||||
# @property
|
|
||||||
# def q(self):
|
|
||||||
# return self._q
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def d(self):
|
def d(self):
|
||||||
return self._d
|
return self.__d
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def e(self):
|
def e(self):
|
||||||
return self._e
|
return self.__e
|
||||||
|
|
||||||
def enc(self, m: int):
|
def enc(self, m: int):
|
||||||
|
"encode message m"
|
||||||
return pow(m, self.e, self.n)
|
return pow(m, self.e, self.n)
|
||||||
|
|
||||||
def dec(self, c: int):
|
def dec(self, c: int):
|
||||||
|
"decode encoded msg c"
|
||||||
return pow(c, self.d, self.n)
|
return pow(c, self.d, self.n)
|
||||||
Reference in new issue
Block a user