def bundle(self): prekeys = [(k.getId(), b64encode(k.getKeyPair().getPublicKey().serialize())) for k in self.store.loadPreKeys()] identityKeyPair = self.store.getIdentityKeyPair() signedPreKey = KeyHelper.generateSignedPreKey( identityKeyPair, KeyHelper.getRandomSequence(65536)) self.store.storeSignedPreKey(signedPreKey.getId(), signedPreKey) result = { 'signedPreKeyId': signedPreKey.getId(), 'signedPreKeyPublic': b64encode(signedPreKey.getKeyPair().getPublicKey().serialize()), 'signedPreKeySignature': b64encode(signedPreKey.getSignature()), 'identityKey': b64encode(identityKeyPair.getPublicKey().serialize()), 'prekeys': prekeys } return result
def _cycle_signed_pre_key(self, ik_pair): # Publish every SPK_CYCLE_TIME a new SignedPreKey # Delete all exsiting SignedPreKeys that are older # then SPK_ARCHIVE_TIME # Check if SignedPreKey exist and create if not if not self._storage.getCurrentSignedPreKeyId(): spk = KeyHelper.generateSignedPreKey( ik_pair, self._storage.getNextSignedPreKeyId()) self._storage.storeSignedPreKey(spk.getId(), spk) self._log.debug('New SignedPreKey created, because none existed') # if SPK_CYCLE_TIME is reached, generate a new SignedPreKey now = int(time.time()) timestamp = self._storage.getSignedPreKeyTimestamp( self._storage.getCurrentSignedPreKeyId()) if int(timestamp) < now - SPK_CYCLE_TIME: spk = KeyHelper.generateSignedPreKey( ik_pair, self._storage.getNextSignedPreKeyId()) self._storage.storeSignedPreKey(spk.getId(), spk) self._log.debug('Cycled SignedPreKey') # Delete all SignedPreKeys that are older than SPK_ARCHIVE_TIME timestamp = now - SPK_ARCHIVE_TIME self._storage.removeOldSignedPreKeys(timestamp)
def cycleSignedPreKey(self, identityKeyPair): # Publish every SPK_CYCLE_TIME a new SignedPreKey # Delete all exsiting SignedPreKeys that are older # then SPK_ARCHIVE_TIME # Check if SignedPreKey exist and create if not if not self.store.getCurrentSignedPreKeyId(): signedPreKey = KeyHelper.generateSignedPreKey( identityKeyPair, self.store.getNextSignedPreKeyId()) self.store.storeSignedPreKey(signedPreKey.getId(), signedPreKey) log.debug(self.account + ' => New SignedPreKey created, because none existed') # if SPK_CYCLE_TIME is reached, generate a new SignedPreKey now = int(time.time()) timestamp = self.store.getSignedPreKeyTimestamp( self.store.getCurrentSignedPreKeyId()) if int(timestamp) < now - SPK_CYCLE_TIME: signedPreKey = KeyHelper.generateSignedPreKey( identityKeyPair, self.store.getNextSignedPreKeyId()) self.store.storeSignedPreKey(signedPreKey.getId(), signedPreKey) log.debug(self.account + ' => Cycled SignedPreKey') # Delete all SignedPreKeys that are older than SPK_ARCHIVE_TIME timestamp = now - SPK_ARCHIVE_TIME self.store.removeOldSignedPreKeys(timestamp)
def setUp(self): super(ResultIqProtocolEntityTest, self).setUp() self.ProtocolEntity = ResultGetKeysIqProtocolEntity listNode = ProtocolTreeNode("list") self.node.addChild(listNode) for i in range(0, 1): userNode = ProtocolTreeNode( "user", {"jid": "user_%s@%s" % (i, YowConstants.WHATSAPP_SERVER)}) listNode.addChild(userNode) registrationNode = ProtocolTreeNode( "registration", data=ResultGetKeysIqProtocolEntity._intToBytes( KeyHelper.generateRegistrationId())) typeNode = ProtocolTreeNode( "type", data=ResultGetKeysIqProtocolEntity._intToBytes(Curve.DJB_TYPE)) identityKeyPair = KeyHelper.generateIdentityKeyPair() identityNode = ProtocolTreeNode("identity", data=identityKeyPair.getPublicKey( ).getPublicKey().getPublicKey()) signedPreKey = KeyHelper.generateSignedPreKey(identityKeyPair, i) signedPreKeyNode = ProtocolTreeNode("skey") signedPreKeyNode_idNode = ProtocolTreeNode( "id", data=ResultGetKeysIqProtocolEntity._intToBytes( signedPreKey.getId())) signedPreKeyNode_valueNode = ProtocolTreeNode( "value", data=signedPreKey.getKeyPair().getPublicKey().getPublicKey()) signedPreKeyNode_sigNode = ProtocolTreeNode( "signature", data=signedPreKey.getSignature()) signedPreKeyNode.addChildren([ signedPreKeyNode_idNode, signedPreKeyNode_valueNode, signedPreKeyNode_sigNode ]) preKey = KeyHelper.generatePreKeys(i * 10, 1)[0] preKeyNode = ProtocolTreeNode("key") preKeyNode_idNode = ProtocolTreeNode( "id", data=ResultGetKeysIqProtocolEntity._intToBytes(preKey.getId())) preKeyNode_valNode = ProtocolTreeNode( "value", data=preKey.getKeyPair().getPublicKey().getPublicKey()) preKeyNode.addChildren([preKeyNode_idNode, preKeyNode_valNode]) userNode.addChildren([ registrationNode, typeNode, identityNode, signedPreKeyNode, preKeyNode ])
def _generate_axolotl_keys(self): identityKeyPair = KeyHelper.generateIdentityKeyPair() registrationId = KeyHelper.generateRegistrationId() preKeys = KeyHelper.generatePreKeys(KeyHelper.getRandomSequence(), DEFAULT_PREKEY_AMOUNT) self.storeLocalData(registrationId, identityKeyPair) for preKey in preKeys: self.storePreKey(preKey.getId(), preKey)
def __init__(self, dbConn): """ :type dbConn: Connection """ self.dbConn = dbConn dbConn.execute("CREATE TABLE IF NOT EXISTS identities (_id INTEGER PRIMARY KEY AUTOINCREMENT," "recipient_id INTEGER UNIQUE," "registration_id INTEGER, public_key BLOB, private_key BLOB," "next_prekey_id INTEGER, timestamp INTEGER);") if self.getLocalRegistrationId() is None or self.getIdentityKeyPair() is None: identity = KeyHelper.generateIdentityKeyPair() registration_id = KeyHelper.generateRegistrationId(True) self._storeLocalData(registration_id, identity)
def setUp(self): super(ResultIqProtocolEntityTest, self).setUp() self.ProtocolEntity = ResultGetKeysIqProtocolEntity listNode = ProtocolTreeNode("list") self.node.addChild(listNode) for i in range(0, 1): userNode = ProtocolTreeNode("user", {"jid": "user_%s@%s" % (i, YowConstants.WHATSAPP_SERVER)}) listNode.addChild(userNode) registrationNode = ProtocolTreeNode("registration", data = ResultGetKeysIqProtocolEntity._intToBytes( KeyHelper.generateRegistrationId())) typeNode = ProtocolTreeNode("type", data = ResultGetKeysIqProtocolEntity._intToBytes(Curve.DJB_TYPE)) identityKeyPair = KeyHelper.generateIdentityKeyPair() identityNode = ProtocolTreeNode("identity", data=identityKeyPair.getPublicKey().getPublicKey().getPublicKey()) signedPreKey = KeyHelper.generateSignedPreKey(identityKeyPair, i) signedPreKeyNode = ProtocolTreeNode("skey") signedPreKeyNode_idNode = ProtocolTreeNode("id", data = ResultGetKeysIqProtocolEntity._intToBytes( signedPreKey.getId())) signedPreKeyNode_valueNode = ProtocolTreeNode("value", data = signedPreKey.getKeyPair().getPublicKey().getPublicKey()) signedPreKeyNode_sigNode = ProtocolTreeNode("signature", data = signedPreKey.getSignature()) signedPreKeyNode.addChildren([signedPreKeyNode_idNode, signedPreKeyNode_valueNode, signedPreKeyNode_sigNode]) preKey = KeyHelper.generatePreKeys(i * 10, 1)[0] preKeyNode = ProtocolTreeNode("key") preKeyNode_idNode = ProtocolTreeNode("id", data = ResultGetKeysIqProtocolEntity._intToBytes(preKey.getId())) preKeyNode_valNode = ProtocolTreeNode("value", data = preKey.getKeyPair().getPublicKey().getPublicKey()) preKeyNode.addChildren([preKeyNode_idNode, preKeyNode_valNode]) userNode.addChildren([ registrationNode, typeNode, identityNode, signedPreKeyNode, preKeyNode ])
def level_prekeys(self, force=False): logger.debug("level_prekeys(force=%s)" % force) pending_prekeys = self._store.loadPreKeys() logger.debug("len(pending_prekeys) = %d" % len(pending_prekeys)) if force or len(pending_prekeys) < self.THRESHOLD_REGEN: count_gen = self.COUNT_GEN_PREKEYS - len(pending_prekeys) logger.info("Generating %d prekeys" % count_gen) ## arbitrary, should keep track of generated prekey ids and create from there prekeys = KeyHelper.generatePreKeys(KeyHelper.getRandomSequence(2**32 // 2), count_gen) logger.info("Storing %d prekeys" % len(prekeys)) for i in range(0, len(prekeys)): key = prekeys[i] if logger.level <= logging.DEBUG: sys.stdout.write("Storing prekey %d/%d \r" % (i + 1, len(prekeys))) sys.stdout.flush() self._store.storePreKey(key.getId(), key) return prekeys return []
def sendKeys(self, fresh=True, countPreKeys=_COUNT_PREKEYS): identityKeyPair = KeyHelper.generateIdentityKeyPair( ) if fresh else self.store.getIdentityKeyPair() registrationId = KeyHelper.generateRegistrationId( ) if fresh else self.store.getLocalRegistrationId() preKeys = KeyHelper.generatePreKeys(KeyHelper.getRandomSequence(), countPreKeys) signedPreKey = KeyHelper.generateSignedPreKey( identityKeyPair, KeyHelper.getRandomSequence(65536)) preKeysDict = {} for preKey in preKeys: keyPair = preKey.getKeyPair() preKeysDict[self.adjustId(preKey.getId())] = self.adjustArray( keyPair.getPublicKey().serialize()[1:]) signedKeyTuple = ( self.adjustId(signedPreKey.getId()), self.adjustArray( signedPreKey.getKeyPair().getPublicKey().serialize()[1:]), self.adjustArray(signedPreKey.getSignature())) setKeysIq = SetKeysIqProtocolEntity( self.adjustArray(identityKeyPair.getPublicKey().serialize()[1:]), signedKeyTuple, preKeysDict, Curve.DJB_TYPE, self.adjustId(registrationId)) onResult = lambda _, __: self.persistKeys( registrationId, identityKeyPair, preKeys, signedPreKey, fresh) self._sendIq(setKeysIq, onResult, self.onSentKeysError)
def generate_signed_prekey(self): logger.debug("generate_signed_prekey") latest_signed_prekey = self.load_latest_signed_prekey(generate=False) if latest_signed_prekey is not None: if latest_signed_prekey.getId() == self.MAX_SIGNED_PREKEY_ID: new_signed_prekey_id = (self.MAX_SIGNED_PREKEY_ID / 2) + 1 else: new_signed_prekey_id = latest_signed_prekey.getId() + 1 else: new_signed_prekey_id = 0 signed_prekey = KeyHelper.generateSignedPreKey(self._identity, new_signed_prekey_id) self._store.storeSignedPreKey(signed_prekey.getId(), signed_prekey) return signed_prekey
def create(self, senderKeyName): """ :type senderKeyName: SenderKeyName """ try: senderKeyRecord = self.senderKeyStore.loadSenderKey(senderKeyName); if senderKeyRecord.isEmpty() : senderKeyRecord.setSenderKeyState(KeyHelper.generateSenderKeyId(), 0, KeyHelper.generateSenderKey(), KeyHelper.generateSenderSigningKey()); self.senderKeyStore.storeSenderKey(senderKeyName, senderKeyRecord); state = senderKeyRecord.getSenderKeyState(); return SenderKeyDistributionMessage(state.getKeyId(), state.getSenderChainKey().getIteration(), state.getSenderChainKey().getSeed(), state.getSigningKeyPublic()); except (InvalidKeyException, InvalidKeyIdException) as e: raise AssertionError(e)
def bundle(self): """ .. highlight: python Returns all data needed to announce bundle information. :: bundle_dict = { 'signedPreKeyPublic': bytes, 'prekeys': [(int, bytes) (int, bytes)], 'identityKey': bytes, 'signedPreKeyId': int, 'signedPreKeySignature': bytes } """ prekeys = [(k.getId(), b64encode(k.getKeyPair().getPublicKey().serialize())) for k in self.store.loadPreKeys()] identityKeyPair = self.store.getIdentityKeyPair() signedPreKey = KeyHelper.generateSignedPreKey( identityKeyPair, KeyHelper.getRandomSequence(65536)) self.store.storeSignedPreKey(signedPreKey.getId(), signedPreKey) result = { 'signedPreKeyId': signedPreKey.getId(), 'signedPreKeyPublic': b64encode(signedPreKey.getKeyPair().getPublicKey().serialize()), 'signedPreKeySignature': b64encode(signedPreKey.getSignature()), 'identityKey': b64encode(identityKeyPair.getPublicKey().serialize()), 'prekeys': prekeys } return result
def bundle(self): prekeys = [ (k.getId(), b64encode(k.getKeyPair().getPublicKey().serialize())) for k in self.store.loadPreKeys() ] identityKeyPair = self.store.getIdentityKeyPair() signedPreKey = KeyHelper.generateSignedPreKey( identityKeyPair, KeyHelper.getRandomSequence(65536)) self.store.storeSignedPreKey(signedPreKey.getId(), signedPreKey) result = { 'signedPreKeyId': signedPreKey.getId(), 'signedPreKeyPublic': b64encode(signedPreKey.getKeyPair().getPublicKey().serialize()), 'signedPreKeySignature': b64encode(signedPreKey.getSignature()), 'identityKey': b64encode(identityKeyPair.getPublicKey().serialize()), 'prekeys': prekeys } return result
def bundle(self): """ .. highlight: python Returns all data needed to announce bundle information. :: bundle_dict = { 'signedPreKeyPublic': bytes, 'prekeys': [(int, bytes) (int, bytes)], 'identityKey': bytes, 'signedPreKeyId': int, 'signedPreKeySignature': bytes } """ prekeys = [ (k.getId(), b64encode(k.getKeyPair().getPublicKey().serialize())) for k in self.store.loadPreKeys() ] identityKeyPair = self.store.getIdentityKeyPair() signedPreKey = KeyHelper.generateSignedPreKey( identityKeyPair, KeyHelper.getRandomSequence(65536)) self.store.storeSignedPreKey(signedPreKey.getId(), signedPreKey) result = { 'signedPreKeyId': signedPreKey.getId(), 'signedPreKeyPublic': b64encode(signedPreKey.getKeyPair().getPublicKey().serialize()), 'signedPreKeySignature': b64encode(signedPreKey.getSignature()), 'identityKey': b64encode(identityKeyPair.getPublicKey().serialize()), 'prekeys': prekeys } return result
def processInitKeyExchangeMessage(self): try: sequence = KeyHelper.getRandomSequence(65534) + 1 flags = KeyExchangeMessage.INITIATE_FLAG baseKey = Curve.generateKeyPair() ratchetKey = Curve.generateKeyPair() identityKey = self.identityKeyStore.getIdentityKeyPair() baseKeySignature = Curve.calculateSignature(identityKey.getPrivateKey(), baseKey.getPublicKey().serialize()) sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId) sessionRecord.getSessionState().setPendingKeyExchange(sequence, baseKey, ratchetKey, identityKey) self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord) return KeyExchangeMessage(2, sequence, flags, baseKey.getPublicKey(), baseKeySignature, ratchetKey.getPublicKey(), identityKey.getPublicKey()) except InvalidKeyException as e: raise AssertionError(e)
def _generate_axolotl_keys(self): identity_key_pair = KeyHelper.generateIdentityKeyPair() registration_id = KeyHelper.getRandomSequence(2147483647) pre_keys = KeyHelper.generatePreKeys( KeyHelper.getRandomSequence(4294967296), DEFAULT_PREKEY_AMOUNT) self.storeLocalData(registration_id, identity_key_pair) signed_pre_key = KeyHelper.generateSignedPreKey( identity_key_pair, KeyHelper.getRandomSequence(65536)) self.storeSignedPreKey(signed_pre_key.getId(), signed_pre_key) for pre_key in pre_keys: self.storePreKey(pre_key.getId(), pre_key)
def init_store(self): """Create new identity key pair and initialize database""" logger.info('Creating new identity...') identityKeyPair = KeyHelper.generateIdentityKeyPair() registrationId = KeyHelper.generateRegistrationId() preKeys = KeyHelper.generatePreKeys(KeyHelper.getRandomSequence(), self.COUNT_PREKEYS) signedPreKey = KeyHelper.generateSignedPreKey(identityKeyPair, KeyHelper.getRandomSequence(65536)) self.store.storeLocalData(registrationId, identityKeyPair) self.store.storeSignedPreKey(signedPreKey.getId(), signedPreKey) for preKey in preKeys: self.store.storePreKey(preKey.getId(), preKey)
def level_prekeys(self, force=False): logger.debug("level_prekeys(force=%s)" % force) len_pending_prekeys = len(self._store.loadPreKeys()) logger.debug("len(pending_prekeys) = %d" % len_pending_prekeys) if force or len_pending_prekeys < self.THRESHOLD_REGEN: count_gen = self.COUNT_GEN_PREKEYS max_prekey_id = self._store.preKeyStore.loadMaxPreKeyId() logger.info("Generating %d prekeys, current max_prekey_id=%d" % (count_gen, max_prekey_id)) prekeys = KeyHelper.generatePreKeys(max_prekey_id + 1, count_gen) logger.info("Storing %d prekeys" % len(prekeys)) for i in range(0, len(prekeys)): key = prekeys[i] if logger.level <= logging.DEBUG: sys.stdout.write("Storing prekey %d/%d \r" % (i + 1, len(prekeys))) sys.stdout.flush() self._store.storePreKey(key.getId(), key) return prekeys return []
def init_store(self): """Create new identity key pair and initialize database""" logger.info('Creating new identity...') identityKeyPair = KeyHelper.generateIdentityKeyPair() registrationId = KeyHelper.generateRegistrationId() preKeys = KeyHelper.generatePreKeys(KeyHelper.getRandomSequence(), self.COUNT_PREKEYS) signedPreKey = KeyHelper.generateSignedPreKey( identityKeyPair, KeyHelper.getRandomSequence(65536)) self.store.storeLocalData(registrationId, identityKeyPair) self.store.storeSignedPreKey(signedPreKey.getId(), signedPreKey) for preKey in preKeys: self.store.storePreKey(preKey.getId(), preKey)
def sendKeys(self, fresh = True, countPreKeys = _COUNT_PREKEYS): identityKeyPair = KeyHelper.generateIdentityKeyPair() if fresh else self.store.getIdentityKeyPair() registrationId = KeyHelper.generateRegistrationId() if fresh else self.store.getLocalRegistrationId() preKeys = KeyHelper.generatePreKeys(KeyHelper.getRandomSequence(), countPreKeys) signedPreKey = KeyHelper.generateSignedPreKey(identityKeyPair, KeyHelper.getRandomSequence(65536)) preKeysDict = {} for preKey in preKeys: keyPair = preKey.getKeyPair() preKeysDict[self.adjustId(preKey.getId())] = self.adjustArray(keyPair.getPublicKey().serialize()[1:]) signedKeyTuple = (self.adjustId(signedPreKey.getId()), self.adjustArray(signedPreKey.getKeyPair().getPublicKey().serialize()[1:]), self.adjustArray(signedPreKey.getSignature())) setKeysIq = SetKeysIqProtocolEntity(self.adjustArray(identityKeyPair.getPublicKey().serialize()[1:]), signedKeyTuple, preKeysDict, Curve.DJB_TYPE, self.adjustId(registrationId)) onResult = lambda _, __: self.persistKeys(registrationId, identityKeyPair, preKeys, signedPreKey, fresh) self._sendIq(setKeysIq, onResult, self.onSentKeysError)
def test_outOfOrder(self): aliceStore = InMemorySenderKeyStore(); bobStore = InMemorySenderKeyStore(); aliceSessionBuilder = GroupSessionBuilder(aliceStore) bobSessionBuilder = GroupSessionBuilder(bobStore) aliceGroupCipher = GroupCipher(aliceStore, GROUP_SENDER) bobGroupCipher = GroupCipher(bobStore, GROUP_SENDER); sentAliceDistributionMessage = aliceSessionBuilder.create(GROUP_SENDER); receivedAliceDistributionMessage = SenderKeyDistributionMessage(serialized = sentAliceDistributionMessage.serialize()); bobSessionBuilder.process(GROUP_SENDER, receivedAliceDistributionMessage) ciphertexts = [] for i in range(0, 100): ciphertexts.append(aliceGroupCipher.encrypt("up the punks")) while len(ciphertexts) > 0: index = KeyHelper.getRandomSequence(2147483647) % len(ciphertexts) ciphertext = ciphertexts.pop(index) plaintext = bobGroupCipher.decrypt(ciphertext) self.assertEqual(plaintext, "up the punks")
def generateNewPreKeys(self, count): prekey_id = self.getCurrentPreKeyId() or 0 pre_keys = KeyHelper.generatePreKeys(prekey_id + 1, count) for pre_key in pre_keys: self.storePreKey(pre_key.getId(), pre_key)
def __init__(self): self.trustedKeys = {} identityKeyPairKeys = Curve.generateKeyPair() self.identityKeyPair = IdentityKeyPair(IdentityKey(identityKeyPairKeys.getPublicKey()), identityKeyPairKeys.getPrivateKey()) self.localRegistrationId = KeyHelper.generateRegistrationId()
def generateNewPreKeys(self, count): startId = self.getCurrentPreKeyId() + 1 preKeys = KeyHelper.generatePreKeys(startId, count) for preKey in preKeys: self.storePreKey(preKey.getId(), preKey)
def test_gensig(self): identityKeyPair = KeyHelper.generateIdentityKeyPair() KeyHelper.generateSignedPreKey(identityKeyPair, 0)