Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
jvdsn
GitHub Repository: jvdsn/crypto-attacks
Path: blob/master/attacks/gcm/forbidden_attack.py
2589 views
1
from sage.all import GF
2
3
x = GF(2)["x"].gen()
4
gf2e = GF(2 ** 128, name="y", modulus=x ** 128 + x ** 7 + x ** 2 + x + 1)
5
6
7
# Converts an integer to a gf2e element, little endian.
8
def _to_gf2e(n):
9
return gf2e([(n >> i) & 1 for i in range(127, -1, -1)])
10
11
12
# Converts a gf2e element to an integer, little endian.
13
def _from_gf2e(p):
14
n = 0
15
polynomial = p.polynomial()
16
for i in range(128):
17
n <<= 1
18
n |= int(polynomial[i])
19
20
return n
21
22
23
# Calculates the GHASH polynomial.
24
def _ghash(h, a, c):
25
la = len(a)
26
lc = len(c)
27
p = gf2e(0)
28
for i in range(la // 16):
29
p += _to_gf2e(int.from_bytes(a[16 * i:16 * (i + 1)], byteorder="big"))
30
p *= h
31
32
if la % 16 != 0:
33
p += _to_gf2e(int.from_bytes(a[-(la % 16):] + bytes(16 - la % 16), byteorder="big"))
34
p *= h
35
36
for i in range(lc // 16):
37
p += _to_gf2e(int.from_bytes(c[16 * i:16 * (i + 1)], byteorder="big"))
38
p *= h
39
40
if lc % 16 != 0:
41
p += _to_gf2e(int.from_bytes(c[-(lc % 16):] + bytes(16 - lc % 16), byteorder="big"))
42
p *= h
43
44
p += _to_gf2e(((8 * la) << 64) | (8 * lc))
45
p *= h
46
return p
47
48
49
def recover_possible_auth_keys(a1, c1, t1, a2, c2, t2):
50
"""
51
Recovers possible authentication keys from two messages encrypted with the same authentication key.
52
More information: Joux A., "Authentication Failures in NIST version of GCM"
53
:param a1: the associated data of the first message (bytes)
54
:param c1: the ciphertext of the first message (bytes)
55
:param t1: the authentication tag of the first message (bytes)
56
:param a2: the associated data of the second message (bytes)
57
:param c2: the ciphertext of the second message (bytes)
58
:param t2: the authentication tag of the second message (bytes)
59
:return: a generator generating possible authentication keys (gf2e element)
60
"""
61
h = gf2e["h"].gen()
62
p1 = _ghash(h, a1, c1) + _to_gf2e(int.from_bytes(t1, byteorder="big"))
63
p2 = _ghash(h, a2, c2) + _to_gf2e(int.from_bytes(t2, byteorder="big"))
64
for h, _ in (p1 + p2).roots():
65
yield h
66
67
68
def forge_tag(h, a, c, t, target_a, target_c):
69
"""
70
Forges an authentication tag for a target message given a message with a known tag.
71
This method is best used with the authentication keys generated by the recover_possible_auth_keys method.
72
More information: Joux A., "Authentication Failures in NIST version of GCM"
73
:param h: the authentication key to use (gf2e element)
74
:param a: the associated data of the message with the known tag (bytes)
75
:param c: the ciphertext of the message with the known tag (bytes)
76
:param t: the known authentication tag (bytes)
77
:param target_a: the target associated data (bytes)
78
:param target_c: the target ciphertext (bytes)
79
:return: the forged authentication tag (bytes)
80
"""
81
ghash = _from_gf2e(_ghash(h, a, c))
82
target_ghash = _from_gf2e(_ghash(h, target_a, target_c))
83
return (ghash ^ int.from_bytes(t, byteorder="big") ^ target_ghash).to_bytes(16, byteorder="big")
84
85