def decodePublicKey(key): if len(key) != 33: raise WireFormatException( "The key field must contain 33 bytes of data.") try: key_type = ord(key[0]) except TypeError: key_type = key[0] if key_type != KEY_TYPE_25519: raise WireFormatException("Unknown key type.") return key[1:]
def messageFromWire(obj): # Due to the nature the mac is calculated by signal, the authentication # verification has to be done later in an additional step. # Remove the mac mac = obj[-MAC_SIZE:] obj = obj[:-MAC_SIZE] # Check and remove the version obj = checkVersion(obj) # Unpack the protobuf structure obj = wtp.SignalMessage.FromString(obj) if not (obj.HasField("dh_ratchet_key") and obj.HasField("n") and obj.HasField("ciphertext")): raise WireFormatException("Message incomplete.") return { "ciphertext": obj.ciphertext, "header": doubleratchet.Header(decodePublicKey(obj.dh_ratchet_key), obj.n, obj.pn), "additional": mac }
def checkVersion(data): try: version = ord(data[0]) except TypeError: version = data[0] major_version = (version >> 4) & 0x0F minor_version = (version >> 0) & 0x0F if major_version < CURRENT_MAJOR_VERSION or minor_version < CURRENT_MINOR_VERSION: raise WireFormatException("Legacy version detected.") if major_version > CURRENT_MAJOR_VERSION or minor_version > CURRENT_MINOR_VERSION: raise WireFormatException("Newer/unknown version detected.") return data[1:]
def finalizeMessageFromWire(obj, additional): dr_additional = additional["DoubleRatchet"] IK_own = dr_additional["ad"][:33] IK_other = dr_additional["ad"][33:] key = dr_additional["key"] mac = calculateMAC(obj[:-MAC_SIZE], key, IK_other, IK_own) if not additional["WireFormat"] == mac: raise WireFormatException("Message authentication failed.")
def preKeyMessageFromWire(obj): obj = checkVersion(obj) obj = wtp.PreKeySignalMessage.FromString(obj) if not (obj.HasField("spk_id") and obj.HasField("ek") and obj.HasField("ik") and obj.HasField("signal_message") and obj.HasField("otpk_id")): raise WireFormatException("Pre key message incomplete.") return { "session_init_data": { "registration_id": obj.registration_id, "otpk_id": obj.otpk_id, "spk_id": obj.spk_id, "ek": decodePublicKey(obj.ek), "ik": decodePublicKey(obj.ik) }, "message": obj.signal_message, "additional": None }