无法使用SubtleCrypto Web Crypto API解密用PyCryptodome加密的RSA-OAEP消息

问题描述

在服务器端,我正在使用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,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)
          }
        );
      });
    }
    

解决方法

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

在两面都具有一致的摘要的情况下,我可以使用您以前用您的 PyCryptodome 代码(使用我自己的密钥)生成的 WebCrypto 代码成功解密密文。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...