Uso el método kms.decrypt() del paquete boto3. Para escribir soporte, uso el paquete boto3-stubs .
El método de descifrado tiene el atributo EncryptionAlgorithm , que se escribe como
EncryptionAlgorithmSpecType = Literal["RSAES_OAEP_SHA_1", "RSAES_OAEP_SHA_256", "SYMMETRIC_DEFAULT"] Analizo el algoritmo de cifrado a través de la expresión regular de la cadena de entrada, por lo que, en mi caso, el valor de EncryptionAlgorithm es str , no un Literal. Mypy queja por ello.
No quiero deshabilitar la verificación de tipo para esta línea y la única solución que encontré es el método auxiliar que convierte el valor de str en literal de esta manera:
import boto3 from mypy_boto3_kms.literals import EncryptionAlgorithmSpecType def getEncryptionAlgorithmLiteral(algorithm: str) -> EncryptionAlgorithmSpecType: result: EncryptionAlgorithmSpecType if algorithm == "RSAES_OAEP_SHA_1": result = "RSAES_OAEP_SHA_1" elif algorithm == "RSAES_OAEP_SHA_256": result = "RSAES_OAEP_SHA_256" elif algorithm == "SYMMETRIC_DEFAULT": result = "SYMMETRIC_DEFAULT" else: raise Exception(f"Unexpected algorithm '{algorithm}'. It must be one of {EncryptionAlgorithmSpecType}") return result def main(binaryEncData: bytes, keyId: str, algorithm: str): kms = boto3.client('kms') kmsResult = kms.decrypt(CiphertextBlob=binaryEncData, KeyId=keyId, EncryptionAlgorithm=getEncryptionAlgorithmLiteral(algorithm)) Me pregunto si hay alguna forma mejor de lograr la conversión en el método getEncryptionAlgorithmLiteral() para no tener que escribir todos estos valores dos veces. Idealmente, me gustaría usar valores directamente del tipo EncryptionAlgorithmSpecType en lugar de escribirlos nuevamente en mi código.
Puede usar typing.get_args para pasar los argumentos a typing.Literal . En este caso, deberá combinarlo con typing.cast para que pueda señalar a "mypy" que el valor de cadena que devuelve la función es un valor Literal aceptable.
from typing import cast # Import below from `typing` in Python 3.8+ from typing_extensions import Literal, get_args # noinspection SpellCheckingInspection EncryptionAlgorithmSpecType = Literal["RSAES_OAEP_SHA_1", "RSAES_OAEP_SHA_256", "SYMMETRIC_DEFAULT"] _valid_algorithms = get_args(EncryptionAlgorithmSpecType) print(_valid_algorithms) def get_encryption_algorithm_literal( algorithm: str) -> EncryptionAlgorithmSpecType: if algorithm not in _valid_algorithms: valid_values = str(list(_valid_algorithms)).replace("'", "") raise Exception(f"Unexpected algorithm '{algorithm}'. " f"It must be one of {valid_values}") # cast string to literal, so static type checkers such as 'mypy' # don't complain. return cast(EncryptionAlgorithmSpecType, algorithm) def main(): # noinspection SpellCheckingInspection string = 'RSAES_OAEP_SHA_256' my_algorithm = get_encryption_algorithm_literal(string) print(type(my_algorithm), my_algorithm) if __name__ == '__main__': main()Producción:
('RSAES_OAEP_SHA_1', 'RSAES_OAEP_SHA_256', 'SYMMETRIC_DEFAULT') <class 'str'> RSAES_OAEP_SHA_256 Resultado de una entrada no válida como 'RSAES_OAEP_SHA_2567' :
Traceback (most recent call last): ... raise Exception(...) Exception: Unexpected algorithm 'RSAES_OAEP_SHA_2567'. It must be one of [RSAES_OAEP_SHA_1, RSAES_OAEP_SHA_256, SYMMETRIC_DEFAULT]