From 2573c122952dacc940d8ab788b4856acb51f851c Mon Sep 17 00:00:00 2001 From: hinuiiik Date: Thu, 22 Oct 2026 20:46:42 -0400 Subject: [PATCH] Copy some functions over from the signal docs --- main.py | 2 ++ messenger.py | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/main.py b/main.py index 3377cfc..9c9f5fc 100644 --- a/main.py +++ b/main.py @@ -54,6 +54,8 @@ print("Testing Reporting") content = "inappropriate message contents" reportPT, reportCT = alice.report("Bob", content) decryptedReport = server.decryptReport(reportCT) +print(reportPT) +print(decryptedReport) if decryptedReport != reportPT: error("report did not decrypt properly") print(reportPT) diff --git a/messenger.py b/messenger.py index d8be088..4903cc7 100644 --- a/messenger.py +++ b/messenger.py @@ -49,6 +49,80 @@ class MessengerClient: self.dh = GENERATE_DH() self.certificate = None + def RatchetInitAlice(state, SK, bob_dh_public_key): + state.DHs = GENERATE_DH() + state.DHr = bob_dh_public_key + state.RK, state.CKs = KDF_RK(SK, DH(state.DHs, state.DHr)) + state.CKr = None + state.Ns = 0 + state.Nr = 0 + state.PN = 0 + state.MKSKIPPED = {} + + def RatchetInitBob(state, SK, bob_dh_key_pair): + state.DHs = bob_dh_key_pair + state.DHr = None + state.RK = SK + state.CKs = None + state.CKr = None + state.Ns = 0 + state.Nr = 0 + state.PN = 0 + state.MKSKIPPED = {} + + def RatchetSendKey(state): + state.CKs, mk = KDF_CK(state.CKs) + Ns = state.Ns + state.Ns += 1 + return Ns, mk + + def RatchetEncrypt(state, plaintext, AD): + Ns, mk = RatchetSendKey(state) + header = HEADER(state.DHs, state.PN, Ns) + return header, ENCRYPT(mk, plaintext, CONCAT(AD, header)) + + def RatchetReceiveKey(state, header): + mk = TrySkippedMessageKeys(state, header) + if mk != None: + return mk + if header.dh != state.DHr: + SkipMessageKeys(state, header.pn) + DHRatchet(state, header) + SkipMessageKeys(state, header.n) + state.CKr, mk = KDF_CK(state.CKr) + state.Nr += 1 + return mk + + def RatchetDecrypt(state, header, ciphertext, AD): + mk = RatchetReceiveKey(state, header) + return DECRYPT(mk, ciphertext, CONCAT(AD, header)) + + def TrySkippedMessageKeys(state, header): + if (header.dh, header.n) in state.MKSKIPPED: + mk = state.MKSKIPPED[header.dh, header.n] + del state.MKSKIPPED[header.dh, header.n] + return mk + else: + return None + + def SkipMessageKeys(state, until): + if state.Nr + MAX_SKIP < until: + raise Error() + if state.CKr != None: + while state.Nr < until: + state.CKr, mk = KDF_CK(state.CKr) + state.MKSKIPPED[state.DHr, state.Nr] = mk + state.Nr += 1 + + def DHRatchet(state, header): + state.PN = state.Ns + state.Ns = 0 + state.Nr = 0 + state.DHr = header.dh + state.RK, state.CKr = KDF_RK(state.RK, DH(state.DHs, state.DHr)) + state.DHs = GENERATE_DH() + state.RK, state.CKs = KDF_RK(state.RK, DH(state.DHs, state.DHr)) + def generateCertificate(self): self.certificate = pickle.dumps((self.name, self.dh.public_key().public_bytes(serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint)))