| 76 | |
| 77 | |
| 78 | class Cipher(typing.Generic[Mode]): |
| 79 | def __init__( |
| 80 | self, |
| 81 | algorithm: CipherAlgorithm, |
| 82 | mode: Mode, |
| 83 | backend: typing.Any = None, |
| 84 | ) -> None: |
| 85 | if not isinstance(algorithm, CipherAlgorithm): |
| 86 | raise TypeError("Expected interface of CipherAlgorithm.") |
| 87 | |
| 88 | if mode is not None: |
| 89 | # mypy needs this assert to narrow the type from our generic |
| 90 | # type. Maybe it won't some time in the future. |
| 91 | assert isinstance(mode, modes.Mode) |
| 92 | mode.validate_for_algorithm(algorithm) |
| 93 | |
| 94 | self.algorithm = algorithm |
| 95 | self.mode = mode |
| 96 | |
| 97 | @typing.overload |
| 98 | def encryptor( |
| 99 | self: Cipher[modes.ModeWithAuthenticationTag], |
| 100 | ) -> AEADEncryptionContext: ... |
| 101 | |
| 102 | @typing.overload |
| 103 | def encryptor( |
| 104 | self: _CIPHER_TYPE, |
| 105 | ) -> CipherContext: ... |
| 106 | |
| 107 | def encryptor(self): |
| 108 | if isinstance(self.mode, modes.ModeWithAuthenticationTag): |
| 109 | if self.mode.tag is not None: |
| 110 | raise ValueError( |
| 111 | "Authentication tag must be None when encrypting." |
| 112 | ) |
| 113 | |
| 114 | return rust_openssl.ciphers.create_encryption_ctx( |
| 115 | self.algorithm, self.mode |
| 116 | ) |
| 117 | |
| 118 | @typing.overload |
| 119 | def decryptor( |
| 120 | self: Cipher[modes.ModeWithAuthenticationTag], |
| 121 | ) -> AEADDecryptionContext: ... |
| 122 | |
| 123 | @typing.overload |
| 124 | def decryptor( |
| 125 | self: _CIPHER_TYPE, |
| 126 | ) -> CipherContext: ... |
| 127 | |
| 128 | def decryptor(self): |
| 129 | return rust_openssl.ciphers.create_decryption_ctx( |
| 130 | self.algorithm, self.mode |
| 131 | ) |
| 132 | |
| 133 | |
| 134 | _CIPHER_TYPE = Cipher[ |
no outgoing calls