Exemplo n.º 1
0
 def cipher_key(self,
                sender: ID,
                receiver: ID,
                generate: bool = False) -> Optional[SymmetricKey]:
     if receiver.is_broadcast:
         return SymmetricKey.generate(algorithm=PlainKey.PLAIN)
     # get key from cache
     key = self.__cipher_key(sender, receiver)
     if key is None and generate:
         key = SymmetricKey.generate(algorithm=SymmetricKey.AES)
         self.__cache_cipher_key(key=key, sender=sender, receiver=receiver)
     return key
Exemplo n.º 2
0
    def decrypt(self,
                password: DecryptKey = None,
                private_key: DecryptKey = None) -> bytes:
        """
        Decrypt data
            1. decrypt key with private key (such as RSA) to a password
            2. decrypt data with password (symmetric key, such as AES, DES, ...)

        :param password:    symmetric key
        :param private_key: asymmetric private key
        :return: plaintext
        """
        if self.__plaintext is None:
            # get symmetric key
            key = None
            if password is not None:
                assert isinstance(
                    password, SymmetricKey), 'password error: %s' % password
                key = password
            elif private_key is not None:
                # assert isinstance(private_key, PrivateKey), 'private key error: %s' % private_key
                key_data = private_key.decrypt(self.key)
                key = SymmetricKey.parse(key=json_decode(data=key_data))
            # get encrypted data
            data = self.data
            if key is not None and data is not None:
                self.__plaintext = key.decrypt(data=data)
        return self.__plaintext
Exemplo n.º 3
0
def register_key_factories():
    # Public Key: ECC
    factory = GeneralPublicFactory()
    PublicKey.register(algorithm=AsymmetricKey.ECC, factory=factory)
    # Public Key: RSA
    PublicKey.register(algorithm=AsymmetricKey.RSA, factory=factory)
    PublicKey.register(algorithm='SHA256withRSA', factory=factory)
    PublicKey.register(algorithm='RSA/ECB/PKCS1Padding', factory=factory)

    # Private Key: ECC
    factory = GeneralPrivateFactory(algorithm=AsymmetricKey.ECC)
    PrivateKey.register(algorithm=AsymmetricKey.ECC, factory=factory)

    # Private Key: RSA
    factory = GeneralPrivateFactory(algorithm=AsymmetricKey.RSA)
    PrivateKey.register(algorithm=AsymmetricKey.RSA, factory=factory)
    PrivateKey.register(algorithm='SHA256withRSA', factory=factory)
    PrivateKey.register(algorithm='RSA/ECB/PKCS1Padding', factory=factory)

    # Symmetric Key: AES
    factory = GeneralSymmetricFactory(algorithm=SymmetricKey.AES)
    SymmetricKey.register(algorithm=SymmetricKey.AES, factory=factory)
    SymmetricKey.register(algorithm='AES/CBC/PKCS7Padding', factory=factory)

    # Symmetric Key: Plain
    factory = GeneralSymmetricFactory(algorithm=PlainKey.PLAIN)
    SymmetricKey.register(algorithm=PlainKey.PLAIN, factory=factory)
Exemplo n.º 4
0
 def cipher_key(self,
                sender: ID,
                receiver: ID,
                generate: bool = False) -> Optional[SymmetricKey]:
     if receiver.is_broadcast:
         return plain_key
     # get key from cache
     key = self.__cipher_key(sender, receiver)
     if key is None and generate:
         # generate and cache it
         key = SymmetricKey.generate(algorithm=SymmetricKey.AES)
         assert key is not None, 'failed to generate key'
         self.cache_cipher_key(key=key, sender=sender, receiver=receiver)
     return key
Exemplo n.º 5
0
 def upload(self, content: FileContent, password: SymmetricKey,
            msg: InstantMessage):
     data = content.data
     if data is None or len(data) == 0:
         raise ValueError('failed to get file data: %s' % content)
     # encrypt and upload file data onto CDN and save the URL in message content
     encrypted = password.encrypt(data=data)
     if encrypted is None or len(encrypted) == 0:
         raise ValueError('failed to encrypt file data with key: %s' %
                          password)
     url = self.messenger.upload_data(data=encrypted, msg=msg)
     if url is not None:
         # replace 'data' with 'URL'
         content.url = url
         content.data = None
         return True
Exemplo n.º 6
0
    def update_keys(self, key_map: dict) -> bool:
        """
        Update cipher key table into memory cache

        :param key_map: cipher keys(with direction) from local storage
        :return:        False on nothing changed
        """
        changed = False
        for _from in key_map:
            sender = ID.parse(identifier=_from)
            table = key_map.get(_from)
            assert isinstance(
                table, dict), 'sender table error: %s, %s' % (_from, table)
            for _to in table:
                receiver = ID.parse(identifier=_to)
                pw = table.get(_to)
                key = SymmetricKey.parse(key=pw)
                # TODO: check whether exists an old key
                changed = True
                # cache key with direction
                self.__cache_cipher_key(key, sender, receiver)
        return changed
Exemplo n.º 7
0
 def __cache_cipher_key(self, key: SymmetricKey, sender: ID, receiver: ID):
     table = self.__key_map.get(sender)
     if table is None:
         table = {}
         self.__key_map[sender] = table
     else:
         old = table.get(receiver)
         if old is not None:
             # check whether same key exists
             equals = True
             # assert isinstance(key, dict), 'key info error: %s' % key
             for k in key:
                 v1 = key.get(k)
                 v2 = old.get(k)
                 if v1 == v2:
                     continue
                 equals = False
                 break
             if equals:
                 # no need to update
                 return
     table[receiver] = key
Exemplo n.º 8
0
 def download(self, content: FileContent, password: SymmetricKey,
              msg: SecureMessage):
     url = content.url
     if url is None or url.find('://') < 0:
         # download URL not found
         return False
     i_msg = InstantMessage.create(head=msg.envelope, body=content)
     # download from CDN
     encrypted = self.messenger.download_data(url=url, msg=i_msg)
     if encrypted is None or len(encrypted) == 0:
         # save symmetric key for decrypting file data after download from CDN
         content.password = password
         return False
     else:
         # decrypt file data
         data = password.decrypt(data=encrypted)
         if data is None or len(data) == 0:
             raise ValueError('failed to decrypt file data with key: %s' %
                              password)
         content.data = data
         content.url = None
         return True