3

在服务器端,我使用PyCryptodome使用RSA-OAEP(使用 SHA-256)加密消息。
我正在尝试在客户端使用SubtleCrypto Web Crypto API 解密消息,但它给了我一个DOMException错误,没有更多详细信息。
在 SubtleCrypto 上,我可以毫无问题地导入 PyCryptodome 中生成的私钥,但是当我尝试解密消息时它给了我错误。

我还尝试在客户端导入 PyCryptodome 上生成的公钥,以使用 SubtleCrypto 加密相同的消息。在这种情况下,我可以使用与以前相同的流程毫无问题地解密它。

这两个库之间的 RSA-OAEP 算法是否不兼容?我注意到 PyCryptodome在各自的文档中引用了RFC 8017(v2.2)和 SubtleCrypto RFC 3447(v2.1) 。

编辑

  • 服务器端代码(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
    
    ( ... ) 
    
  • 客户端代码

    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)
          }
        );
      });
    }
    
4

1 回答 1

7

PyCryptodome不应用 SHA-256 作为 OAEP 的默认摘要,而是 SHA-1 here。因此,必须在WebCrypto端使用 SHA-1:

let algorithmParams: RsaHashedImportParams = {
    name: "RSA-OAEP",
    hash: "SHA-1"
};

当然,您也可以在PyCryptodome端应用 SHA-256,然后在WebCrypto端无需更改。

from Crypto.Hash import SHA256
...
rsa_encryption_cipher = PKCS1_OAEP.new(key, SHA256) # default: Crypto.Hash.SHA1

通过双方一致的摘要,我可以使用您的WebCrypto代码成功解密密文,该代码是我之前使用您的PyCryptodome代码生成的(使用我自己的密钥)。

于 2020-08-26T13:27:58.227 回答