AES.py
1 # Reticulum License 2 # 3 # Copyright (c) 2016-2025 Mark Qvist 4 # 5 # Permission is hereby granted, free of charge, to any person obtaining a copy 6 # of this software and associated documentation files (the "Software"), to deal 7 # in the Software without restriction, including without limitation the rights 8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 # copies of the Software, and to permit persons to whom the Software is 10 # furnished to do so, subject to the following conditions: 11 # 12 # - The Software shall not be used in any kind of system which includes amongst 13 # its functions the ability to purposefully do harm to human beings. 14 # 15 # - The Software shall not be used, directly or indirectly, in the creation of 16 # an artificial intelligence, machine learning or language model training 17 # dataset, including but not limited to any use that contributes to the 18 # training or development of such a model or algorithm. 19 # 20 # - The above copyright notice and this permission notice shall be included in 21 # all copies or substantial portions of the Software. 22 # 23 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 # SOFTWARE. 30 31 import RNS.Cryptography.Provider as cp 32 import RNS.vendor.platformutils as pu 33 34 if cp.PROVIDER == cp.PROVIDER_INTERNAL: 35 from .aes import AES128 36 from .aes import AES256 37 38 elif cp.PROVIDER == cp.PROVIDER_PYCA: 39 from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes 40 if pu.cryptography_old_api(): from cryptography.hazmat.backends import default_backend 41 42 43 class AES_128_CBC: 44 @staticmethod 45 def encrypt(plaintext, key, iv): 46 if len(key) != 16: raise ValueError(f"Invalid key length {len(key)*8} for {self}") 47 if cp.PROVIDER == cp.PROVIDER_INTERNAL: 48 cipher = AES128(key) 49 return cipher.encrypt(plaintext, iv) 50 51 elif cp.PROVIDER == cp.PROVIDER_PYCA: 52 if not pu.cryptography_old_api(): 53 cipher = Cipher(algorithms.AES(key), modes.CBC(iv)) 54 else: 55 cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()) 56 57 encryptor = cipher.encryptor() 58 ciphertext = encryptor.update(plaintext) + encryptor.finalize() 59 return ciphertext 60 61 @staticmethod 62 def decrypt(ciphertext, key, iv): 63 if len(key) != 16: raise ValueError(f"Invalid key length {len(key)*8} for {self}") 64 if cp.PROVIDER == cp.PROVIDER_INTERNAL: 65 cipher = AES128(key) 66 return cipher.decrypt(ciphertext, iv) 67 68 elif cp.PROVIDER == cp.PROVIDER_PYCA: 69 if not pu.cryptography_old_api(): 70 cipher = Cipher(algorithms.AES(key), modes.CBC(iv)) 71 else: 72 cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()) 73 74 decryptor = cipher.decryptor() 75 plaintext = decryptor.update(ciphertext) + decryptor.finalize() 76 return plaintext 77 78 class AES_256_CBC: 79 @staticmethod 80 def encrypt(plaintext, key, iv): 81 if len(key) != 32: raise ValueError(f"Invalid key length {len(key)*8} for {self}") 82 if cp.PROVIDER == cp.PROVIDER_INTERNAL: 83 cipher = AES256(key) 84 return cipher.encrypt_cbc(plaintext, iv) 85 86 elif cp.PROVIDER == cp.PROVIDER_PYCA: 87 if not pu.cryptography_old_api(): 88 cipher = Cipher(algorithms.AES(key), modes.CBC(iv)) 89 else: 90 cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()) 91 92 encryptor = cipher.encryptor() 93 ciphertext = encryptor.update(plaintext) + encryptor.finalize() 94 return ciphertext 95 96 @staticmethod 97 def decrypt(ciphertext, key, iv): 98 if len(key) != 32: raise ValueError(f"Invalid key length {len(key)*8} for {self}") 99 if cp.PROVIDER == cp.PROVIDER_INTERNAL: 100 cipher = AES256(key) 101 return cipher.decrypt_cbc(ciphertext, iv) 102 103 elif cp.PROVIDER == cp.PROVIDER_PYCA: 104 if not pu.cryptography_old_api(): 105 cipher = Cipher(algorithms.AES(key), modes.CBC(iv)) 106 else: 107 cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()) 108 109 decryptor = cipher.decryptor() 110 plaintext = decryptor.update(ciphertext) + decryptor.finalize() 111 return plaintext