def initializeSessionsV2(self, aliceSessionState, bobSessionState):
        aliceIdentityKeyPair = Curve.generateKeyPair()
        aliceIdentityKey     = IdentityKeyPair(IdentityKey(aliceIdentityKeyPair.getPublicKey()),
                                                               aliceIdentityKeyPair.getPrivateKey())
        aliceBaseKey         = Curve.generateKeyPair()
        aliceEphemeralKey    = Curve.generateKeyPair()

        bobIdentityKeyPair   = Curve.generateKeyPair()
        bobIdentityKey       = IdentityKeyPair(IdentityKey(bobIdentityKeyPair.getPublicKey()),
                                                               bobIdentityKeyPair.getPrivateKey())
        bobBaseKey           = Curve.generateKeyPair()
        bobEphemeralKey      = bobBaseKey

        aliceParameters = AliceAxolotlParameters.newBuilder()\
            .setOurIdentityKey(aliceIdentityKey)\
            .setOurBaseKey(aliceBaseKey)\
            .setTheirIdentityKey(bobIdentityKey.getPublicKey())\
            .setTheirSignedPreKey(bobEphemeralKey.getPublicKey())\
            .setTheirRatchetKey(bobEphemeralKey.getPublicKey())\
            .setTheirOneTimePreKey(None)\
            .create()

        bobParameters = BobAxolotlParameters.newBuilder()\
            .setOurIdentityKey(bobIdentityKey)\
            .setOurOneTimePreKey(None)\
            .setOurRatchetKey(bobEphemeralKey)\
            .setOurSignedPreKey(bobBaseKey)\
            .setTheirBaseKey(aliceBaseKey.getPublicKey())\
            .setTheirIdentityKey(aliceIdentityKey.getPublicKey())\
            .create()

        RatchetingSession.initializeSessionAsAlice(aliceSessionState, 2, aliceParameters)
        RatchetingSession.initializeSessionAsBob(bobSessionState, 2, bobParameters)
    def test_badSignedPreKeySignature(self):
        aliceStore          = InMemoryAxolotlStore()
        aliceSessionBuilder = SessionBuilder(aliceStore, aliceStore, aliceStore, aliceStore,
                                             self.__class__.BOB_RECIPIENT_ID, 1)

        bobIdentityKeyStore = InMemoryIdentityKeyStore()

        bobPreKeyPair            = Curve.generateKeyPair()
        bobSignedPreKeyPair      = Curve.generateKeyPair()
        bobSignedPreKeySignature = Curve.calculateSignature(bobIdentityKeyStore.getIdentityKeyPair().getPrivateKey(),
                                                                  bobSignedPreKeyPair.getPublicKey().serialize())

        for i in range(0, len(bobSignedPreKeySignature) * 8):
            modifiedSignature = bytearray(bobSignedPreKeySignature[:])
            modifiedSignature[int(i/8)] ^= 0x01 << (i % 8)

            bobPreKey = PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1,
                                                31337, bobPreKeyPair.getPublicKey(),
                                                22, bobSignedPreKeyPair.getPublicKey(), modifiedSignature,
                                                bobIdentityKeyStore.getIdentityKeyPair().getPublicKey())

            try:
                aliceSessionBuilder.processPreKeyBundle(bobPreKey)
            except Exception:
                pass
                #good
        bobPreKey = PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1,
                                              31337, bobPreKeyPair.getPublicKey(),
                                              22, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature,
                                              bobIdentityKeyStore.getIdentityKeyPair().getPublicKey())

        aliceSessionBuilder.processPreKeyBundle(bobPreKey)
Esempio n. 3
0
    def test_randomAgreements(self):

        for i in range(0, 50):
            alice   = Curve.generateKeyPair()
            bob     = Curve.generateKeyPair()
            sharedAlice = Curve.calculateAgreement(bob.getPublicKey(), alice.getPrivateKey())
            sharedBob   = Curve.calculateAgreement(alice.getPublicKey(), bob.getPrivateKey())
            self.assertEqual(sharedAlice, sharedBob)
Esempio n. 4
0
    def encryptParams(self, params, key):
        """
        :param params:
        :type params: list
        :param key:
        :type key: ECPublicKey
        :return:
        :rtype: list
        """
        keypair = Curve.generateKeyPair()
        encodedparams = self.urlencodeParams(params)

        cipher = AESGCM(Curve.calculateAgreement(key, keypair.privateKey))
        ciphertext = cipher.encrypt(b'\x00\x00\x00\x00' + struct.pack('>Q', 0), encodedparams.encode(), b'')

        payload = base64.b64encode(keypair.publicKey.serialize()[1:] + ciphertext)
        return [('ENC', payload)]
Esempio n. 5
0
    def test_signature(self):
        aliceIdentityPrivate = bytearray([0xc0, 0x97, 0x24, 0x84, 0x12,
                                   0xe5, 0x8b, 0xf0, 0x5d, 0xf4,
                                   0x87, 0x96, 0x82, 0x05, 0x13,
                                   0x27, 0x94, 0x17, 0x8e, 0x36,
                                   0x76, 0x37, 0xf5, 0x81, 0x8f,
                                   0x81, 0xe0, 0xe6, 0xce, 0x73,
                                   0xe8, 0x65])

        aliceIdentityPublic  = bytearray([0x05, 0xab, 0x7e, 0x71, 0x7d,
                                   0x4a, 0x16, 0x3b, 0x7d, 0x9a,
                                   0x1d, 0x80, 0x71, 0xdf, 0xe9,
                                   0xdc, 0xf8, 0xcd, 0xcd, 0x1c,
                                   0xea, 0x33, 0x39, 0xb6, 0x35,
                                   0x6b, 0xe8, 0x4d, 0x88, 0x7e,
                                   0x32, 0x2c, 0x64])

        aliceEphemeralPublic = bytearray([0x05, 0xed, 0xce, 0x9d, 0x9c,
                                   0x41, 0x5c, 0xa7, 0x8c, 0xb7,
                                   0x25, 0x2e, 0x72, 0xc2, 0xc4,
                                   0xa5, 0x54, 0xd3, 0xeb, 0x29,
                                   0x48, 0x5a, 0x0e, 0x1d, 0x50,
                                   0x31, 0x18, 0xd1, 0xa8, 0x2d,
                                   0x99, 0xfb, 0x4a])

        aliceSignature       = bytearray([0x5d, 0xe8, 0x8c, 0xa9, 0xa8,
                                   0x9b, 0x4a, 0x11, 0x5d, 0xa7,
                                   0x91, 0x09, 0xc6, 0x7c, 0x9c,
                                   0x74, 0x64, 0xa3, 0xe4, 0x18,
                                   0x02, 0x74, 0xf1, 0xcb, 0x8c,
                                   0x63, 0xc2, 0x98, 0x4e, 0x28,
                                   0x6d, 0xfb, 0xed, 0xe8, 0x2d,
                                   0xeb, 0x9d, 0xcd, 0x9f, 0xae,
                                   0x0b, 0xfb, 0xb8, 0x21, 0x56,
                                   0x9b, 0x3d, 0x90, 0x01, 0xbd,
                                   0x81, 0x30, 0xcd, 0x11, 0xd4,
                                   0x86, 0xce, 0xf0, 0x47, 0xbd,
                                   0x60, 0xb8, 0x6e, 0x88])

        alicePrivateKey = Curve.decodePrivatePoint(aliceIdentityPrivate)
        alicePublicKey  = Curve.decodePoint(aliceIdentityPublic, 0)
        aliceEphemeral  = Curve.decodePoint(aliceEphemeralPublic, 0)

        res = Curve.verifySignature(alicePublicKey, aliceEphemeral.serialize(), bytes(aliceSignature))
        self.assertTrue(res)
Esempio n. 6
0
 def getSignature(self, signatureKey, serialized):
     """
     :type signatureKey: ECPrivateKey
     :type serialized: bytearray
     """
     try:
         return Curve.calculateSignature(signatureKey, serialized)
     except InvalidKeyException as e:
         raise AssertionError(e)
    def __init__(self, id = None, iteration = None, chainKey = None, signatureKey = None, serialized = None):
        """
        :type id: int
        :type iteration: int
        :type chainKey: bytearray
        :type signatureKey: ECPublicKey
        """


        assert bool(id is not None and iteration is not None and chainKey is not None and signatureKey is not None)\
               ^ bool(serialized),\
            "Either pass arguments or serialized data"

        if serialized:
            try:
                messageParts = ByteUtil.split(serialized, 1, len(serialized)- 1)
                version      = messageParts[0][0]
                message      = messageParts[1]


                if ByteUtil.highBitsToInt(version) < 3:
                    raise LegacyMessageException("Legacy message: %s" % ByteUtil.highBitsToInt(version))

                if ByteUtil.highBitsToInt(version) > self.__class__.CURRENT_VERSION:
                    raise InvalidMessageException("Unknown version: %s" % ByteUtil.highBitsToInt(version))


                distributionMessage = whisperprotos.SenderKeyDistributionMessage()
                distributionMessage.ParseFromString(message)

                if distributionMessage.id is None or distributionMessage.iteration is None\
                    or distributionMessage.chainKey is None or distributionMessage.signingKey is None:
                    raise InvalidMessageException("Incomplete message")

                self.serialized = serialized

                self.id           = distributionMessage.id
                self.iteration    = distributionMessage.iteration
                self.chainKey     = distributionMessage.chainKey
                self.signatureKey = Curve.decodePoint(bytearray(distributionMessage.signingKey), 0)

            except Exception as e:
                raise InvalidMessageException(e)
        else:
            version = [ByteUtil.intsToByteHighAndLow(self.__class__.CURRENT_VERSION, self.__class__.CURRENT_VERSION)]
            self.id = id
            self.iteration = iteration
            self.chainKey = chainKey
            self.signatureKey = signatureKey
            message = whisperprotos.SenderKeyDistributionMessage()
            message.id = id
            message.iteration = iteration
            message.chainKey= bytes(chainKey)
            message.signingKey = signatureKey.serialize()
            message = message.SerializeToString()
            self.serialized = bytes(ByteUtil.combine(version, message))
Esempio n. 8
0
    def encryptParams(self, params, key):
        """
        :param params:
        :type params: list
        :param key:
        :type key: ECPublicKey
        :return:
        :rtype: list
        """
        keypair = Curve.generateKeyPair()
        encodedparams = self.urlencodeParams(params)

        cipher = AESGCM(Curve.calculateAgreement(key, keypair.privateKey))
        ciphertext = cipher.encrypt(b'\x00\x00\x00\x00' + struct.pack('>Q', 0),
                                    encodedparams.encode(), b'')

        payload = base64.b64encode(keypair.publicKey.serialize()[1:] +
                                   ciphertext)
        return [('ENC', payload)]
Esempio n. 9
0
    def verifySignature(self, signatureKey):
        """
        :type signatureKey: ECPublicKey
        """
        try:
            parts = ByteUtil.split(self.serialized, len(self.serialized)- self.__class__.SIGNATURE_LENGTH, self.__class__.SIGNATURE_LENGTH)

            if not Curve.verifySignature(signatureKey, parts[0], parts[1]):
                raise InvalidMessageException("Invalid signature!")
        except InvalidKeyException as e:
            raise InvalidMessageException(e)
Esempio n. 10
0
    def test_agreement(self):
        alicePublic  =  bytearray([0x05, 0x1b,  0xb7,  0x59,  0x66,
                        0xf2,  0xe9,  0x3a,  0x36,  0x91,
                        0xdf,  0xff,  0x94,  0x2b,  0xb2,
                        0xa4,  0x66,  0xa1,  0xc0,  0x8b,
                        0x8d,  0x78,  0xca,  0x3f,  0x4d,
                        0x6d,  0xf8,  0xb8,  0xbf,  0xa2,
                        0xe4,  0xee,  0x28])
        alicePrivate = bytearray([0xc8, 0x06, 0x43, 0x9d, 0xc9,
                           0xd2, 0xc4, 0x76, 0xff, 0xed,
                           0x8f, 0x25, 0x80, 0xc0, 0x88,
                           0x8d, 0x58, 0xab, 0x40, 0x6b,
                           0xf7, 0xae, 0x36, 0x98, 0x87,
                           0x90, 0x21, 0xb9, 0x6b, 0xb4,
                           0xbf, 0x59])

        bobPublic    = bytearray([0x05, 0x65, 0x36, 0x14, 0x99,
                           0x3d, 0x2b, 0x15, 0xee, 0x9e,
                           0x5f, 0xd3, 0xd8, 0x6c, 0xe7,
                           0x19, 0xef, 0x4e, 0xc1, 0xda,
                           0xae, 0x18, 0x86, 0xa8, 0x7b,
                           0x3f, 0x5f, 0xa9, 0x56, 0x5a,
                           0x27, 0xa2, 0x2f])

        bobPrivate   = bytearray([0xb0, 0x3b, 0x34, 0xc3, 0x3a,
                           0x1c, 0x44, 0xf2, 0x25, 0xb6,
                           0x62, 0xd2, 0xbf, 0x48, 0x59,
                           0xb8, 0x13, 0x54, 0x11, 0xfa,
                           0x7b, 0x03, 0x86, 0xd4, 0x5f,
                           0xb7, 0x5d, 0xc5, 0xb9, 0x1b,
                           0x44, 0x66])

        shared       = bytearray([0x32, 0x5f, 0x23, 0x93, 0x28,
                           0x94, 0x1c, 0xed, 0x6e, 0x67,
                           0x3b, 0x86, 0xba, 0x41, 0x01,
                           0x74, 0x48, 0xe9, 0x9b, 0x64,
                           0x9a, 0x9c, 0x38, 0x06, 0xc1,
                           0xdd, 0x7c, 0xa4, 0xc4, 0x77,
                           0xe6, 0x29])

        alicePublicKey = Curve.decodePoint(alicePublic, 0)
        alicePrivateKey = Curve.decodePrivatePoint(alicePrivate)

        bobPublicKey = Curve.decodePoint(bobPublic, 0)
        bobPrivateKey = Curve.decodePrivatePoint(bobPrivate)

        sharedOne = Curve.calculateAgreement(alicePublicKey, bobPrivateKey)
        sharedTwo = Curve.calculateAgreement(bobPublicKey, alicePrivateKey)

        self.assertEqual(sharedOne, shared)
        self.assertEqual(sharedTwo, shared)
Esempio n. 11
0
    def __init__(self, messageVersion = None, sequence = None, flags=None,
                 baseKey = None, baseKeySignature = None,
                 ratchetKey = None,
                 identityKey = None,
                 serialized = None):
        """
        :type messageVersion: int
        :type  sequence: int
        :type flags:int
        :type baseKey: ECPublicKey
        :type baseKeySignature: bytearray
        :type ratchetKey: ECPublicKey
        :type identityKey: IdentityKey
        :type serialized: bytearray
        """
        if serialized:
            try:
                parts                 = ByteUtil.split(serialized, 1, len(serialized)- 1)
                self.version          = ByteUtil.highBitsToInt(parts[0][0])
                self.supportedVersion = ByteUtil.lowBitsToInt(parts[0][0])
                if self.version <= CiphertextMessage.UNSUPPORTED_VERSION:
                    raise LegacyMessageException("Unsupportmessageed legacy version: %s" % self.version)
                if self.version > CiphertextMessage.CURRENT_VERSION:
                    raise InvalidVersionException("Unkown version: %s" % self.version)
                message = whisperprotos.KeyExchangeMessage()
                message.ParseFromString(bytes(parts[1]))

                if not message.HasField("id") or not message.HasField("baseKey")\
                    or not message.HasField("ratchetKey") or not message.HasField("identityKey")\
                    or (self.version >= 3 and not message.HasField("baseKeySignature")):
                    raise InvalidMessageException("Some required fields are missing!")

                self.sequence = message.id >> 5
                self.flags = message.id & 0x1f
                self.serialized = serialized
                self.baseKey = Curve.decodePoint(bytearray(message.baseKey), 0)
                self.baseKeySignature = message.baseKeySignature
                self.ratchetKey = Curve.decodePoint(bytearray(message.ratchetKey), 0)
                self.identityKey = IdentityKey(message.identityKey, 0)

            except InvalidKeyException as e:
                raise InvalidMessageException(e)
        else:

            self.supportedVersion = CiphertextMessage.CURRENT_VERSION
            self.version          = messageVersion
            self.sequence         = sequence
            self.flags            = flags
            self.baseKey          = baseKey
            self.baseKeySignature = baseKeySignature
            self.ratchetKey       = ratchetKey
            self.identityKey      = identityKey

            version = [ByteUtil.intsToByteHighAndLow(self.version, self.supportedVersion)]
            keyExchangeMessage = whisperprotos.KeyExchangeMessage()
            keyExchangeMessage.id = (self.sequence << 5) | self.flags
            keyExchangeMessage.baseKey = baseKey.serialize()
            keyExchangeMessage.ratchetKey = ratchetKey.serialize()
            keyExchangeMessage.identityKey = identityKey.serialize()

            if messageVersion >= 3:
                keyExchangeMessage.baseKeySignature = baseKeySignature

            self.serialized = ByteUtil.combine(version, keyExchangeMessage.SerializeToString())
 def __init__(self):
     self.trustedKeys = {}
     identityKeyPairKeys = Curve.generateKeyPair()
     self.identityKeyPair = IdentityKeyPair(IdentityKey(identityKeyPairKeys.getPublicKey()),
                                            identityKeyPairKeys.getPrivateKey())
     self.localRegistrationId = KeyHelper.generateRegistrationId()
Esempio n. 13
0
    def test_basicPreKeyV3(self):
        aliceStore = InMemoryAxolotlStore()
        aliceSessionBuilder = SessionBuilder(aliceStore, aliceStore, aliceStore, aliceStore, self.__class__.BOB_RECIPIENT_ID, 1)

        bobStore =   InMemoryAxolotlStore()
        bobPreKeyPair = Curve.generateKeyPair()
        bobSignedPreKeyPair = Curve.generateKeyPair()
        bobSignedPreKeySignature = Curve.calculateSignature(bobStore.getIdentityKeyPair().getPrivateKey(),
                                                                           bobSignedPreKeyPair.getPublicKey().serialize())

        bobPreKey = PreKeyBundle(bobStore.getLocalRegistrationId(), 1,
                                              31337, bobPreKeyPair.getPublicKey(),
                                              22, bobSignedPreKeyPair.getPublicKey(),
                                              bobSignedPreKeySignature,
                                              bobStore.getIdentityKeyPair().getPublicKey())

        aliceSessionBuilder.processPreKeyBundle(bobPreKey)
        self.assertTrue(aliceStore.containsSession(self.__class__.BOB_RECIPIENT_ID, 1))
        self.assertTrue(aliceStore.loadSession(self.__class__.BOB_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3)

        originalMessage    = "L'homme est condamné à être libre"
        aliceSessionCipher = SessionCipher(aliceStore, aliceStore, aliceStore, aliceStore, self.__class__.BOB_RECIPIENT_ID, 1)
        outgoingMessage    = aliceSessionCipher.encrypt(originalMessage)

        self.assertTrue(outgoingMessage.getType() == CiphertextMessage.PREKEY_TYPE)

        incomingMessage = PreKeyWhisperMessage(serialized=outgoingMessage.serialize())
        bobStore.storePreKey(31337, PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair))
        bobStore.storeSignedPreKey(22, SignedPreKeyRecord(22, int(time.time() * 1000), bobSignedPreKeyPair, bobSignedPreKeySignature))

        bobSessionCipher = SessionCipher(bobStore, bobStore, bobStore, bobStore, self.__class__.ALICE_RECIPIENT_ID, 1)

        plaintext = bobSessionCipher.decryptPkmsg(incomingMessage)
        self.assertEqual(originalMessage, plaintext)
        # @@TODO: in callback assertion
        # self.assertFalse(bobStore.containsSession(self.__class__.ALICE_RECIPIENT_ID, 1))

        self.assertTrue(bobStore.containsSession(self.__class__.ALICE_RECIPIENT_ID, 1))

        self.assertTrue(bobStore.loadSession(self.__class__.ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3)
        self.assertTrue(bobStore.loadSession(self.__class__.ALICE_RECIPIENT_ID, 1).getSessionState().getAliceBaseKey() != None)
        self.assertEqual(originalMessage, plaintext)

        bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage)
        self.assertTrue(bobOutgoingMessage.getType() == CiphertextMessage.WHISPER_TYPE)

        alicePlaintext = aliceSessionCipher.decryptMsg(WhisperMessage(serialized=bobOutgoingMessage.serialize()))
        self.assertEqual(alicePlaintext, originalMessage)

        self.runInteraction(aliceStore, bobStore)

        aliceStore          = InMemoryAxolotlStore()
        aliceSessionBuilder = SessionBuilder(aliceStore, aliceStore, aliceStore, aliceStore, self.__class__.BOB_RECIPIENT_ID, 1)
        aliceSessionCipher  = SessionCipher(aliceStore, aliceStore, aliceStore, aliceStore, self.__class__.BOB_RECIPIENT_ID, 1)

        bobPreKeyPair            = Curve.generateKeyPair()
        bobSignedPreKeyPair      = Curve.generateKeyPair()
        bobSignedPreKeySignature = Curve.calculateSignature(bobStore.getIdentityKeyPair().getPrivateKey(), bobSignedPreKeyPair.getPublicKey().serialize())
        bobPreKey = PreKeyBundle(bobStore.getLocalRegistrationId(),
                                 1, 31338, bobPreKeyPair.getPublicKey(),
                                 23, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature,
                                 bobStore.getIdentityKeyPair().getPublicKey())

        bobStore.storePreKey(31338, PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair))
        bobStore.storeSignedPreKey(23, SignedPreKeyRecord(23, int(time.time() * 1000), bobSignedPreKeyPair, bobSignedPreKeySignature))
        aliceSessionBuilder.processPreKeyBundle(bobPreKey)

        outgoingMessage = aliceSessionCipher.encrypt(originalMessage)

        try:
            plaintext = bobSessionCipher.decryptPkmsg(PreKeyWhisperMessage(serialized=outgoingMessage))
            raise AssertionError("shouldn't be trusted!")
        except Exception:
            bobStore.saveIdentity(self.__class__.ALICE_RECIPIENT_ID, PreKeyWhisperMessage(serialized=outgoingMessage.serialize()).getIdentityKey())

        plaintext = bobSessionCipher.decryptPkmsg(PreKeyWhisperMessage(serialized=outgoingMessage.serialize()))
        self.assertEqual(plaintext, originalMessage)


        bobPreKey = PreKeyBundle(bobStore.getLocalRegistrationId(), 1,
                                 31337, Curve.generateKeyPair().getPublicKey(),
                                 23, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature,
                                 aliceStore.getIdentityKeyPair().getPublicKey())
        try:
            aliceSessionBuilder.process(bobPreKey)
            raise AssertionError("shouldn't be trusted!")
        except Exception:
            #good
            pass
Esempio n. 14
0
 def getSigningKeyPublic(self):
     return Curve.decodePoint(bytearray(self.senderKeyStateStructure.senderSigningKey.public), 0)
Esempio n. 15
0
    def test_rootKeyDerivationV2(self):
        rootKeySeed = bytearray(
            [
                0x7B,
                0xA6,
                0xDE,
                0xBC,
                0x2B,
                0xC1,
                0xBB,
                0xF9,
                0x1A,
                0xBB,
                0xC1,
                0x36,
                0x74,
                0x04,
                0x17,
                0x6C,
                0xA6,
                0x23,
                0x09,
                0x5B,
                0x7E,
                0xC6,
                0x6B,
                0x45,
                0xF6,
                0x02,
                0xD9,
                0x35,
                0x38,
                0x94,
                0x2D,
                0xCC,
            ]
        )

        alicePublic = bytearray(
            [
                0x05,
                0xEE,
                0x4F,
                0xA6,
                0xCD,
                0xC0,
                0x30,
                0xDF,
                0x49,
                0xEC,
                0xD0,
                0xBA,
                0x6C,
                0xFC,
                0xFF,
                0xB2,
                0x33,
                0xD3,
                0x65,
                0xA2,
                0x7F,
                0xAD,
                0xBE,
                0xFF,
                0x77,
                0xE9,
                0x63,
                0xFC,
                0xB1,
                0x62,
                0x22,
                0xE1,
                0x3A,
            ]
        )

        alicePrivate = bytearray(
            [
                0x21,
                0x68,
                0x22,
                0xEC,
                0x67,
                0xEB,
                0x38,
                0x04,
                0x9E,
                0xBA,
                0xE7,
                0xB9,
                0x39,
                0xBA,
                0xEA,
                0xEB,
                0xB1,
                0x51,
                0xBB,
                0xB3,
                0x2D,
                0xB8,
                0x0F,
                0xD3,
                0x89,
                0x24,
                0x5A,
                0xC3,
                0x7A,
                0x94,
                0x8E,
                0x50,
            ]
        )

        bobPublic = bytearray(
            [
                0x05,
                0xAB,
                0xB8,
                0xEB,
                0x29,
                0xCC,
                0x80,
                0xB4,
                0x71,
                0x09,
                0xA2,
                0x26,
                0x5A,
                0xBE,
                0x97,
                0x98,
                0x48,
                0x54,
                0x06,
                0xE3,
                0x2D,
                0xA2,
                0x68,
                0x93,
                0x4A,
                0x95,
                0x55,
                0xE8,
                0x47,
                0x57,
                0x70,
                0x8A,
                0x30,
            ]
        )

        nextRoot = bytearray(
            [
                0xB1,
                0x14,
                0xF5,
                0xDE,
                0x28,
                0x01,
                0x19,
                0x85,
                0xE6,
                0xEB,
                0xA2,
                0x5D,
                0x50,
                0xE7,
                0xEC,
                0x41,
                0xA9,
                0xB0,
                0x2F,
                0x56,
                0x93,
                0xC5,
                0xC7,
                0x88,
                0xA6,
                0x3A,
                0x06,
                0xD2,
                0x12,
                0xA2,
                0xF7,
                0x31,
            ]
        )

        nextChain = bytearray(
            [
                0x9D,
                0x7D,
                0x24,
                0x69,
                0xBC,
                0x9A,
                0xE5,
                0x3E,
                0xE9,
                0x80,
                0x5A,
                0xA3,
                0x26,
                0x4D,
                0x24,
                0x99,
                0xA3,
                0xAC,
                0xE8,
                0x0F,
                0x4C,
                0xCA,
                0xE2,
                0xDA,
                0x13,
                0x43,
                0x0C,
                0x5C,
                0x55,
                0xB5,
                0xCA,
                0x5F,
            ]
        )

        alicePublicKey = Curve.decodePoint(alicePublic, 0)
        alicePrivateKey = Curve.decodePrivatePoint(alicePrivate)
        aliceKeyPair = ECKeyPair(alicePublicKey, alicePrivateKey)
        bobPublicKey = Curve.decodePoint(bobPublic, 0)
        rootKey = RootKey(HKDF.createFor(2), rootKeySeed)
        rootKeyChainKeyPair = rootKey.createChain(bobPublicKey, aliceKeyPair)

        nextRootKey = rootKeyChainKeyPair[0]
        nextChainKey = rootKeyChainKeyPair[1]

        self.assertEqual(rootKey.getKeyBytes(), rootKeySeed)
        self.assertEqual(nextRootKey.getKeyBytes(), nextRoot)
        self.assertEqual(nextChainKey.getKey(), nextChain)
    def test_ratchetingSessionAsBob(self):
        bobPublic   = bytearray([0x05, 0x2c, 0xb4, 0x97,
                                    0x76, 0xb8, 0x77, 0x02,
                                    0x05, 0x74, 0x5a, 0x3a,
                                    0x6e, 0x24, 0xf5, 0x79,
                                    0xcd, 0xb4, 0xba, 0x7a,
                                    0x89, 0x04, 0x10, 0x05,
                                    0x92, 0x8e, 0xbb, 0xad,
                                    0xc9, 0xc0, 0x5a, 0xd4,
                                    0x58])

        bobPrivate  = bytearray([0xa1, 0xca, 0xb4, 0x8f,
                                    0x7c, 0x89, 0x3f, 0xaf,
                                    0xa9, 0x88, 0x0a, 0x28,
                                    0xc3, 0xb4, 0x99, 0x9d,
                                    0x28, 0xd6, 0x32, 0x95,
                                    0x62, 0xd2, 0x7a, 0x4e,
                                    0xa4, 0xe2, 0x2e, 0x9f,
                                    0xf1, 0xbd, 0xd6, 0x5a])

        bobIdentityPublic   = bytearray([0x05, 0xf1, 0xf4, 0x38,
                                    0x74, 0xf6, 0x96, 0x69,
                                    0x56, 0xc2, 0xdd, 0x47,
                                    0x3f, 0x8f, 0xa1, 0x5a,
                                    0xde, 0xb7, 0x1d, 0x1c,
                                    0xb9, 0x91, 0xb2, 0x34,
                                    0x16, 0x92, 0x32, 0x4c,
                                    0xef, 0xb1, 0xc5, 0xe6,
                                    0x26])

        bobIdentityPrivate    = bytearray([0x48, 0x75, 0xcc, 0x69,
                                    0xdd, 0xf8, 0xea, 0x07,
                                    0x19, 0xec, 0x94, 0x7d,
                                    0x61, 0x08, 0x11, 0x35,
                                    0x86, 0x8d, 0x5f, 0xd8,
                                    0x01, 0xf0, 0x2c, 0x02,
                                    0x25, 0xe5, 0x16, 0xdf,
                                    0x21, 0x56, 0x60, 0x5e])

        aliceBasePublic     = bytearray([0x05, 0x47, 0x2d, 0x1f,
                                    0xb1, 0xa9, 0x86, 0x2c,
                                    0x3a, 0xf6, 0xbe, 0xac,
                                    0xa8, 0x92, 0x02, 0x77,
                                    0xe2, 0xb2, 0x6f, 0x4a,
                                    0x79, 0x21, 0x3e, 0xc7,
                                    0xc9, 0x06, 0xae, 0xb3,
                                    0x5e, 0x03, 0xcf, 0x89,
                                    0x50])

        aliceEphemeralPublic  = bytearray([0x05, 0x6c, 0x3e, 0x0d,
                                    0x1f, 0x52, 0x02, 0x83,
                                    0xef, 0xcc, 0x55, 0xfc,
                                    0xa5, 0xe6, 0x70, 0x75,
                                    0xb9, 0x04, 0x00, 0x7f,
                                    0x18, 0x81, 0xd1, 0x51,
                                    0xaf, 0x76, 0xdf, 0x18,
                                    0xc5, 0x1d, 0x29, 0xd3,
                                    0x4b])

        aliceIdentityPublic   = bytearray([0x05, 0xb4, 0xa8, 0x45,
                                    0x56, 0x60, 0xad, 0xa6,
                                    0x5b, 0x40, 0x10, 0x07,
                                    0xf6, 0x15, 0xe6, 0x54,
                                    0x04, 0x17, 0x46, 0x43,
                                    0x2e, 0x33, 0x39, 0xc6,
                                    0x87, 0x51, 0x49, 0xbc,
                                    0xee, 0xfc, 0xb4, 0x2b,
                                    0x4a])

        senderChain           = bytearray([0xd2, 0x2f, 0xd5, 0x6d, 0x3f,
                                    0xec, 0x81, 0x9c, 0xf4, 0xc3,
                                    0xd5, 0x0c, 0x56, 0xed, 0xfb,
                                    0x1c, 0x28, 0x0a, 0x1b, 0x31,
                                    0x96, 0x45, 0x37, 0xf1, 0xd1,
                                    0x61, 0xe1, 0xc9, 0x31, 0x48,
                                    0xe3, 0x6b])

        bobIdentityKeyPublic   = IdentityKey(bobIdentityPublic, 0)
        bobIdentityKeyPrivate  = Curve.decodePrivatePoint(bobIdentityPrivate)
        bobIdentityKey         =  IdentityKeyPair(bobIdentityKeyPublic, bobIdentityKeyPrivate)
        bobEphemeralPublicKey  = Curve.decodePoint(bobPublic, 0)
        bobEphemeralPrivateKey = Curve.decodePrivatePoint(bobPrivate)
        bobEphemeralKey        = ECKeyPair(bobEphemeralPublicKey, bobEphemeralPrivateKey)
        bobBaseKey             = bobEphemeralKey

        aliceBasePublicKey       = Curve.decodePoint(aliceBasePublic, 0)
        aliceEphemeralPublicKey  = Curve.decodePoint(aliceEphemeralPublic, 0)
        aliceIdentityPublicKey   = IdentityKey(aliceIdentityPublic, 0)

        parameters = BobAxolotlParameters.newBuilder()\
        .setOurIdentityKey(bobIdentityKey)\
        .setOurSignedPreKey(bobBaseKey)\
        .setOurRatchetKey(bobEphemeralKey)\
        .setOurOneTimePreKey(None)\
        .setTheirIdentityKey(aliceIdentityPublicKey)\
        .setTheirBaseKey(aliceBasePublicKey)\
        .create()

        session = SessionState()

        RatchetingSession.initializeSessionAsBob(session, 2, parameters)
        self.assertEqual(session.getLocalIdentityKey(), bobIdentityKey.getPublicKey())
        self.assertEqual(session.getRemoteIdentityKey(), aliceIdentityPublicKey)
        self.assertEqual(session.getSenderChainKey().getKey(), senderChain)
Esempio n. 17
0
class WARequest(object):
    OK = 200
    ENC_PUBKEY = Curve.decodePoint(
        bytearray([
            5, 142, 140, 15, 116, 195, 235, 197, 215, 166, 134, 92, 108, 60,
            132, 56, 86, 176, 97, 33, 204, 232, 234, 119, 77, 34, 251, 111, 18,
            37, 18, 48, 45
        ]))

    def __init__(self, config):
        """
       :type method: str
       :param config:
       :type config: yowsup.config.v1.config.Config
       """

        self.pvars = []
        self.port = 443
        self.type = "GET"
        self.parser = None
        self.params = []
        self.headers = {}

        self.sent = False
        self.response = None

        self._config = config
        self._p_in = str(config.phone)[len(str(config.cc)):]
        self._axolotlmanager = AxolotlManagerFactory() \
            .get_manager(self._config.phone)  # type: yowsup.axolotl.manager.Axolotlmanager

        if config.expid is None:
            config.expid = WATools.generateDeviceId()

        if config.fdid is None:
            config.fdid = WATools.generatePhoneId()

        if config.client_static_keypair is None:
            config.client_static_keypair = WATools.generateKeyPair()

        self.addParam("cc", config.cc)
        self.addParam("in", self._p_in)
        self.addParam("lg", "en")
        self.addParam("lc", "GB")
        self.addParam("mistyped", "6")
        self.addParam("authkey",
                      self.b64encode(config.client_static_keypair.public.data))
        self.addParam(
            "e_regid",
            self.b64encode(
                struct.pack('>I', self._axolotlmanager.registration_id)))
        self.addParam("e_keytype", self.b64encode(b"\x05"))
        self.addParam(
            "e_ident",
            self.b64encode(
                self._axolotlmanager.identity.publicKey.serialize()[1:]))

        signedprekey = self._axolotlmanager.load_latest_signed_prekey(
            generate=True)
        self.addParam(
            "e_skey_id",
            self.b64encode(struct.pack('>I', signedprekey.getId())[1:]))
        self.addParam(
            "e_skey_val",
            self.b64encode(
                signedprekey.getKeyPair().publicKey.serialize()[1:]))
        self.addParam("e_skey_sig",
                      self.b64encode(signedprekey.getSignature()))

        self.addParam("fdid", config.fdid)
        self.addParam("expid", self.b64encode(config.expid))

        self.addParam("network_radio_type", "1")
        self.addParam("simnum", "1")
        self.addParam("hasinrc", "1")
        self.addParam("pid", int(random.uniform(100, 9999)))
        self.addParam("rc", 0)
        if self._config.id:
            self.addParam("id", self._config.id)

    def setParsableVariables(self, pvars):
        self.pvars = pvars

    def onResponse(self, name, value):
        if name == "status":
            self.status = value
        elif name == "result":
            self.result = value

    def addParam(self, name, value):
        self.params.append((name, value))

    def removeParam(self, name):
        for i in range(0, len(self.params)):
            if self.params[i][0] == name:
                del self.params[i]

    def addHeaderField(self, name, value):
        self.headers[name] = value

    def clearParams(self):
        self.params = []

    def getUserAgent(self):
        return YowsupEnv.getCurrent().getUserAgent()

    def send(self, parser=None, encrypt=True, preview=False):
        logger.debug(
            "send(parser=%s, encrypt=%s, preview=%s)" %
            (None if parser is None else "[omitted]", encrypt, preview))
        if self.type == "POST":
            return self.sendPostRequest(parser)

        return self.sendGetRequest(parser, encrypt, preview=preview)

    def setParser(self, parser):
        if isinstance(parser, ResponseParser):
            self.parser = parser
        else:
            logger.error("Invalid parser")

    def getConnectionParameters(self):

        if not self.url:
            return "", "", self.port

        try:
            url = self.url.split("://", 1)
            url = url[0] if len(url) == 1 else url[1]

            host, path = url.split('/', 1)
        except ValueError:
            host = url
            path = ""

        path = "/" + path

        return host, self.port, path

    def encryptParams(self, params, key):
        """
        :param params:
        :type params: list
        :param key:
        :type key: ECPublicKey
        :return:
        :rtype: list
        """
        keypair = Curve.generateKeyPair()
        encodedparams = self.urlencodeParams(params)

        cipher = AESGCM(Curve.calculateAgreement(key, keypair.privateKey))
        ciphertext = cipher.encrypt(b'\x00\x00\x00\x00' + struct.pack('>Q', 0),
                                    encodedparams.encode(), b'')

        payload = base64.b64encode(keypair.publicKey.serialize()[1:] +
                                   ciphertext)
        return [('ENC', payload)]

    def sendGetRequest(self, parser=None, encrypt_params=True, preview=False):
        logger.debug(
            "sendGetRequest(parser=%s, encrypt_params=%s, preview=%s)" %
            (None if parser is None else "[omitted]", encrypt_params, preview))
        self.response = None

        if encrypt_params:
            logger.debug("Encrypting parameters")
            if logger.level <= logging.DEBUG:
                logger.debug("pre-encrypt (encoded) parameters = \n%s",
                             (self.urlencodeParams(self.params)))
            params = self.encryptParams(self.params, self.ENC_PUBKEY)
        else:
            ## params will be logged right before sending
            params = self.params

        parser = parser or self.parser or ResponseParser()

        headers = dict(
            list({
                "User-Agent": self.getUserAgent(),
                "Accept": parser.getMeta()
            }.items()) + list(self.headers.items()))

        host, port, path = self.getConnectionParameters()

        self.response = WARequest.sendRequest(host,
                                              port,
                                              path,
                                              headers,
                                              params,
                                              "GET",
                                              preview=preview)

        if preview:
            logger.info(
                "Preview request, skip response handling and return None")
            return None

        if not self.response.status == WARequest.OK:
            logger.error("Request not success, status was %s" %
                         self.response.status)
            return {}

        data = self.response.read()
        logger.info(data)

        self.sent = True
        return parser.parse(data.decode(), self.pvars)

    def sendPostRequest(self, parser=None):
        self.response = None
        params = self.params  # [param.items()[0] for param in self.params];

        parser = parser or self.parser or ResponseParser()

        headers = dict(
            list({
                "User-Agent": self.getUserAgent(),
                "Accept": parser.getMeta(),
                "Content-Type": "application/x-www-form-urlencoded"
            }.items()) + list(self.headers.items()))

        host, port, path = self.getConnectionParameters()
        self.response = WARequest.sendRequest(host, port, path, headers,
                                              params, "POST")

        if not self.response.status == WARequest.OK:
            logger.error("Request not success, status was %s" %
                         self.response.status)
            return {}

        data = self.response.read()

        logger.info(data)

        self.sent = True
        return parser.parse(data.decode(), self.pvars)

    def b64encode(self, value):
        return base64.urlsafe_b64encode(value).replace(b'=', b'')

    @classmethod
    def urlencode(cls, value):
        if type(value) not in (str, bytes):
            value = str(value)

        out = ""
        for char in value:
            if type(char) is int:
                char = bytearray([char])
            quoted = urllib_quote(char, safe='')
            out += quoted if quoted[0] != '%' else quoted.lower()

        return out \
            .replace('-', '%2d') \
            .replace('_', '%5f') \
            .replace('~', '%7e')

    @classmethod
    def urlencodeParams(cls, params):
        merged = []
        for k, v in params:
            merged.append("%s=%s" % (k, cls.urlencode(v)))
        return "&".join(merged)

    @classmethod
    def sendRequest(cls,
                    host,
                    port,
                    path,
                    headers,
                    params,
                    reqType="GET",
                    preview=False):
        logger.debug(
            "sendRequest(host=%s, port=%s, path=%s, headers=%s, params=%s, reqType=%s, preview=%s)"
            % (host, port, path, headers, params, reqType, preview))

        params = cls.urlencodeParams(params)

        path = path + "?" + params if reqType == "GET" and params else path

        if not preview:
            logger.debug("Opening connection to %s" % host)
            conn = httplib.HTTPSConnection(
                host, port) if port == 443 else httplib.HTTPConnection(
                    host, port)
        else:
            logger.debug(
                "Should open connection to %s, but this is a preview" % host)
            conn = None

        if not preview:
            logger.debug("Sending %s request to %s" % (reqType, path))
            conn.request(reqType, path, params, headers)
        else:
            logger.debug(
                "Should send %s request to %s, but this is a preview" %
                (reqType, path))
            return None

        response = conn.getresponse()
        return response
Esempio n. 18
0
 def getSigningKeyPrivate(self):
     return Curve.decodePrivatePoint(self.senderKeyStateStructure.senderSigningKey.private)