Week 0x6
Crypto
A key exchange proto- col \(P\) is a pair of probabilistic machines \((A, B)\) that take turns in sending messages to each other. At the end of the protocol, when both machines terminate, they both obtain the same value \(k\). A protocol transcript \(T_P\) is the sequence of messages exchanged between the parties in one exe- cution of the protocol.
Since \(A\) and \(B\) are probabilistic machines, we obtain a different transcript every time we run the protocol. Formally, the transcript \(T_P\) of protocol \(P\) is a random variable, which is a function of the random bits generated by \(A\) and \(B\). The eavesdropping adversary \(E\) sees the entire transcript \(T_P\) and its goal is to figure out the secret \(k\).
\[ \exists e, d, p, q \in \mathbb{N} : \forall m \in \mathbb{N} : (m^e)^d \equiv m \pmod{pq} \]
\[ \begin{align} \forall a \in \mathbb{N}, p \in \mathbb{P} : \gcd(p,a) = 1 \implies a^{p-1} \equiv 1 \pmod{p} \\ \end{align} \]
1
mod that prime.\[ a^{p-1} \equiv 1 \pmod{p} \]
\[ a^p \equiv a \pmod{p} \]
necklaces = [
"AAAAA", "AAAAB", "AAABA", "AAABB", "AABAA", "AABAB", "AABBA", "AABBB",
"ABAAA", "ABAAB", "ABABA", "ABABB", "ABBAA", "ABBAB", "ABBBA", "ABBBB",
"BAAAA", "BAAAB", "BAABA", "BAABB", "BABAA", "BABAB", "BABBA", "BABBB",
"BBAAA", "BBAAB", "BBABA", "BBABB", "BBBAA", "BBBAB", "BBBBA", "BBBBB"
]
friends = [
["AAAAB", "AAABA", "AABAA", "ABAAA", "BAAAA"],
["AAABB", "AABBA", "ABBAA", "BBAAA", "BAAAB"],
["AABAB", "ABABA", "BABAA", "ABAAB", "BAABA"],
["AABBB", "ABBBA", "BBBAA", "BBAAB", "BAABB"],
["ABABB", "BABBA", "ABBAB", "BBABA", "BABAB"],
["ABBBB", "BBBBA", "BBBAB", "BBABB", "BABBB"],
["AAAAA"],
["BBBBB"]
]
\[ 2^5 = 32 \equiv 2 \pmod{5} \]
\[ \begin{align} \forall a \in \mathbb{N}, p \in \mathbb{P} : \gcd(p,a) = 1 \implies a^{p-1} \equiv 1 \pmod{p} \\ \end{align} \]
\[ \lambda(n) = \text{min}(\{m : \forall a : gcd(a,n) = 1 : a^m \equiv 1 \pmod{n}\}) \]
5
, it’s not too bad.4096_t
and use, probably, 6k+1 or a performance optimization.gmp_nextprime
65537
in binary?--------------------------------------------------------------------------- ValueError Traceback (most recent call last) File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\IPython\core\formatters.py:711, in PlainTextFormatter.__call__(self, obj) 704 stream = StringIO() 705 printer = pretty.RepresentationPrinter(stream, self.verbose, 706 self.max_width, self.newline, 707 max_seq_length=self.max_seq_length, 708 singleton_pprinters=self.singleton_printers, 709 type_pprinters=self.type_printers, 710 deferred_pprinters=self.deferred_printers) --> 711 printer.pretty(obj) 712 printer.flush() 713 return stream.getvalue() File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\IPython\lib\pretty.py:394, in RepresentationPrinter.pretty(self, obj) 391 for cls in _get_mro(obj_class): 392 if cls in self.type_pprinters: 393 # printer registered in self.type_pprinters --> 394 return self.type_pprinters[cls](obj, self, cycle) 395 else: 396 # deferred printer 397 printer = self._in_deferred_types(cls) File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\IPython\lib\pretty.py:649, in _seq_pprinter_factory.<locals>.inner(obj, p, cycle) 647 p.text(',') 648 p.breakable() --> 649 p.pretty(x) 650 if len(obj) == 1 and isinstance(obj, tuple): 651 # Special case for 1-item tuples. 652 p.text(',') File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\IPython\lib\pretty.py:394, in RepresentationPrinter.pretty(self, obj) 391 for cls in _get_mro(obj_class): 392 if cls in self.type_pprinters: 393 # printer registered in self.type_pprinters --> 394 return self.type_pprinters[cls](obj, self, cycle) 395 else: 396 # deferred printer 397 printer = self._in_deferred_types(cls) File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\IPython\lib\pretty.py:787, in _repr_pprint(obj, p, cycle) 785 """A pprint that just redirects to the normal repr function.""" 786 # Find newlines and replace them with p.break_() --> 787 output = repr(obj) 788 lines = output.splitlines() 789 with p.group(): ValueError: Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit
def find_large_prime(k):
is_prime = lambda n : any([n % i for i in range(2, int(n **.5))])
candidate = 6 * k + 1
# you need a prime tester
while not is_prime(candidate):
candidate += 6
return candidate
def lcm(a, b):
def gcd(a, b):
while b:
a, b = b, a % b
return a
return a * b // gcd(a, b)
s = "C" # a random string
m = ord(s) # to number
hide_p = lambda: find_large_prime(10)
hide_q = lambda: find_large_prime(15)
n = hide_p() * hide_q()
hide_λ = lambda: lcm(hide_p() - 1, hide_q() - 1)
e = 65537 # encryptor
def find_d():
d = 1
while 1 != (d * e % hide_λ()):
d += 1
return d
def modexp(m, e, n):
if e == 0:
return 1
if e == 1:
return m % n
if e % 2:
return (m * modexp(m*m % n, e//2, n)) % n
return modexp(m*m % n, e//2, n) % n
c = modexp(m, e, n) # ciphertext
new_m = modexp(c % n, find_d(), n)
print(chr(modexp(modexp(ord("C"), e, n), find_d(), n)))