def bytes2gl(b, n, p=None): assert len(b) <= n * n X = FiniteGeneralLinearGroup(n, p) padlen = n * n - len(b) b = bytes([padlen]) * padlen + b for i in range(n): for j in range(n): X.set_at((j, i), b[i * n + j]) return X
def sanity(): n = 2 F = bytes2gl("A\0\0\0", n) print(F) p = F.p print(p) U = FiniteGeneralLinearGroup(n, p) while U.determinant() == 0: U.set_random() res = encrypt(U, F) result = solver(parse_stringified(str(res)), p, lambda payload: test_dec_oracle(U, n, p, payload)) print(result)
def recv_gl(p = None): sock.recvline() mat = [] for i in range(n): mat.append([]) r = re.findall(b"\d+", sock.recvline()) for elm in r: mat[-1].append(int(elm)) if p is None: return mat X = Matrix(n, p) for i in range(n): for j in range(n): X.set_at((j, i), mat[i][j]) return X
def sanity4(): n = 2 U = FiniteGeneralLinearGroup(n, bits=8) while U.determinant() == 0: U.set_random() p = U.p print(p) F = bytes2gl("A\0\0\0", n) print(F) res = encrypt(U, F) print(res) print(decrypt(U, res)) F = bytes2gl(chr(res.get_at((0, 0))) + "\0\0\0", n, p) r1 = decrypt(U, F) F = bytes2gl('\0' + chr(res.get_at((1, 0))) + "\0\0", n, p) r2 = decrypt(U, F) F = bytes2gl('\0\0' + chr(res.get_at((0, 1))) + '\0', n, p) r3 = decrypt(U, F) F = bytes2gl('\0\0\0' + chr(res.get_at((1, 1))), n, p) r4 = decrypt(U, F) print(r1 + r2 + r3 + r4)
def solver(res, p, dec_oracle): n = len(res) recovered = FiniteGeneralLinearGroup(n, p) for i in range(n): for j in range(n): print('recovered', i, j) val = res[i][j] k = val / 255 remainder = val % 255 payload = list('\0' * n * n) payload[i * n + j] = chr(255) result_255 = dec_oracle("".join(payload)) X = create_from_matrix(result_255, n, p) recovered += X * k payload[i * n + j] = chr(remainder) result_remainder = dec_oracle("".join(payload)) X = create_from_matrix(result_remainder, n, p) recovered += X return recovered
def encrypt(U, X): return U * X * U**-1 def decrypt(U, X): return U**-1 * X * U if __name__ == '__main__': # Create flag F n = math.ceil(math.sqrt(len(flag))) F = bytes2gl(flag, n) p = F.p # Generate private key U = FiniteGeneralLinearGroup(n, p) while U.determinant() == 0: U.set_random() eF = encrypt(U, F) assert decrypt(U, eF) == F print("Encrypted Flag:", flush=True) print(eF, flush=True) print("p = {}".format(F.p), flush=True) while True: choice = menu() if choice == 1: # Encrypt M = recv_message(U.n, U.p) C = encrypt(U, M)
return split(r, base, result) n = 6 if __name__ == '__main__': if len(sys.argv) != 2: print("solve.py gather/solve") elif sys.argv[1] == 'gather': sock = Socket("13.231.224.102", 3002) # Get eF and p mat = recv_gl() sock.recvuntil("p = ") p = int(sock.recvline()) eF = Matrix(n, p) for i in range(n): for j in range(n): eF.set_at((j, i), mat[i][j]) # Create table T = [[None for j in range(n)] for i in range(n)] R = [[None for j in range(n)] for i in range(n)] for i in range(n): for j in range(n): data = b'\x00' * (n*n) data = data[:i*n+j] + b'\x02' + data[i*n+j+1:] T[i][j] = decrypt(data, p) data = data[:i*n+j] + b'\x01' + data[i*n+j+1:] R[i][j] = decrypt(data, p) print("[+] ({}, {})".format(j, i))
def create_from_matrix(matrix, n, p): res = FiniteGeneralLinearGroup(n, p) for i in range(n): for j in range(n): res.set_at((j, i), matrix[i][j]) return res
def sanity3(): n = 2 F = bytes2gl("ABCD", n) print(F) p = F.p print(p) U = FiniteGeneralLinearGroup(n, p) while U.determinant() == 0: U.set_random() res = encrypt(U, F) print(decrypt(U, res)) print( solver(parse_stringified(str(res)), p, lambda payload: test_dec_oracle(U, n, p, payload))) divisor = 255 mod = 255 v = 255 result = FiniteGeneralLinearGroup(n, p) val = res.get_at((0, 0)) k = val / divisor print(k) remainder = val % mod F = bytes2gl(chr(v) + "\0\0\0", n, p) r1 = decrypt(U, F) result += r1 * k F = bytes2gl(chr(remainder) + "\0\0\0", n, p) r1 = decrypt(U, F) result += r1 val = res.get_at((1, 0)) k = val / divisor print(k) remainder = val % mod F = bytes2gl('\0' + chr(v) + "\0\0", n, p) r2 = decrypt(U, F) result += r2 * k F = bytes2gl('\0' + chr(remainder) + "\0\0", n, p) r2 = decrypt(U, F) result += r2 val = res.get_at((0, 1)) k = val / divisor print(k) remainder = val % mod F = bytes2gl('\0\0' + chr(v) + "\0", n, p) r3 = decrypt(U, F) result += r3 * k F = bytes2gl('\0\0' + chr(remainder) + "\0", n, p) r3 = decrypt(U, F) result += r3 val = res.get_at((1, 1)) k = val / divisor print(k) remainder = val % mod F = bytes2gl('\0\0\0' + chr(v), n, p) r4 = decrypt(U, F) result += r4 * k F = bytes2gl('\0\0\0' + chr(remainder), n, p) r4 = decrypt(U, F) result += r4 print(result)