Não é possível descriptografar a mensagem RSA-OAEP criptografada com PyCryptodome usando a API SubtleCrypto Web Crypto
No lado do servidor, estou usando o PyCryptodome para criptografar uma mensagem com RSA-OAEP (com SHA-256).
Estou tentando descriptografar a mensagem usando a API SubtleCrypto Web Crypto no lado do cliente, mas isso me dá um erro DOMException sem mais detalhes.
No SubtleCrypto consigo importar a chave privada gerada no PyCryptodome sem problemas, mas dá o erro quando estou tentando descriptografar a mensagem.
Também tentei importar a chave pública gerada no PyCryptodome no lado do cliente para criptografar a mesma mensagem com o SubtleCrypto. Nesse caso, posso descriptografá-lo sem problemas, usando o mesmo fluxo de antes.
Os algoritmos RSA-OAEP entre essas duas bibliotecas são incompatíveis? Percebi que PyCryptodome faz referência a RFC 8017(v2.2) e SubtleCrypto RFC 3447(v2.1) em suas respectivas documentações.
Editar :
Código do lado do servidor (pycryptodome==3.9.8):
from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP class Cipher: def rsa_encrypt(self, data, key_string): key = RSA.importKey(key_string) rsa_encryption_cipher = PKCS1_OAEP.new(key) ciphertext = rsa_encryption_cipher.encrypt(data) return base64.b64encode(ciphertext) def rsa_decrypt(self, data, key_string): data = base64.b64decode(data) key = RSA.importKey(key_string) rsa_decryption_cipher = PKCS1_OAEP.new(key) plaintext = rsa_decryption_cipher.decrypt(data) return plaintext ( ... )Código do lado do cliente
private decryptRSAString (encryptedText: string, privateKey: string) : Observable<ArrayBuffer> { return Observable.create ((observer: any) => { let keyBuffer: ArrayBuffer = this.str2ab(window.atob(privateKey)); let encryptedTextBuffer: ArrayBuffer = this.str2ab(window.atob(encryptedText)); let algorithmParams: RsaHashedImportParams = { name: "RSA-OAEP", hash: "SHA-256" }; window.crypto.subtle.importKey( 'pkcs8', keyBuffer, algorithmParams, true, ["decrypt"] ).then ( (cryptoKey: CryptoKey) => { window.crypto.subtle.decrypt( { name: "RSA-OAEP" }, cryptoKey, encryptedTextBuffer ).then ( (decryptedMessage: ArrayBuffer) => { observer.next (decryptedMessage); observer.complete(); }, (error: any) => { observer.error (error) } ) }, (error: any) => { observer.error (error) } ); }); }
Respostas
PyCryptodome não aplica SHA-256 como resumo padrão para OAEP, mas SHA-1, aqui . Assim, o SHA-1 deve ser usado no lado do WebCrypto :
let algorithmParams: RsaHashedImportParams = {
name: "RSA-OAEP",
hash: "SHA-1"
};
Claro que você também pode aplicar SHA-256 no lado do PyCryptodome , então nenhuma alteração é necessária no lado do WebCrypto .
from Crypto.Hash import SHA256
...
rsa_encryption_cipher = PKCS1_OAEP.new(key, SHA256) # default: Crypto.Hash.SHA1
Com resumos consistentes em ambos os lados, posso descriptografar com êxito um texto cifrado com seu código WebCrypto , que gerei anteriormente com seu código PyCryptodome (usando minhas próprias chaves).