簡體   English   中英

Window Crypto Subtle:如果我們使用“RSASSA-PKCS1-v1_5”算法生成公私鑰,我們如何使用加密/解密方法?

[英]Window Crypto Subtle : How we can use encrypt / decrypt method if we generate public private key with "RSASSA-PKCS1-v1_5" algo?

我想使用相同的公鑰-私鑰在代碼級別進行一些加密/解密,並希望將加密數據連同我附加在 JWT AUTH 令牌中的公鑰一起發送到后端。 因此,如果可能的話,請幫助我使用該方法進行加密/解密,因為由於可重用性,我無法更改此代碼

      const keyDetails = await window.crypto.subtle.generateKey(
          {
              name: 'RSASSA-PKCS1-v1_5',
              modulusLength: 2048, 
              publicExponent: new Uint8Array([1, 0, 1]),
              hash: { name: 'SHA-256' }, 
          },
          true, 
          ['verify', 'sign'] 
      );
      

我嘗試過這種方式,但出現錯誤。

另外,我想使用我用這種方法導出的公鑰和私鑰

const publicKey: any = await window.crypto.subtle.exportKey('jwk', keyDetails.publicKey);
const privateKey: any = await window.crypto.subtle.exportKey('jwk', keyDetails.privateKey);
      const enc = new TextEncoder();
      const encodedText = enc.encode("testing 1234");
    
      const encryptedText = await window.crypto.subtle.encrypt({
        name: "RSASSA-PKCS1-v1_5"
      },
      publicKey,
      encodedText
    )
    console.log(encryptedText);
    const decryptedText = await window.crypto.subtle.decrypt({
        name: "RSASSA-PKCS1-v1_5"
      },
      privateKey,
      encryptedText
    )
TypeError: Failed to execute 'encrypt' on 'SubtleCrypto': parameter 2 is not of type 'CryptoKey'.

RSASSA-PKCS1-v1_5 是在簽名/驗證期間應用的填充。 它不能用於加密/解密。 加解密的padding是RSAES-PKCS1-v1_5,但是WebCrypto API不支持,WebCrypto只支持RSAES-OAEP加解密。 有關詳細信息,請參閱RFC8017WebCrypto API
此外,必須首先修改導出的 JWK 密鑰以進行加密/解密。 然后必須導入密鑰才能用於加密/解密。

以下示例對此進行了演示:首先,生成一個用於使用 RSASSA-PKCS1-v1_5 進行簽名/驗證的密鑰對。 兩個密鑰都導出為 JWK。 然后調整key_opsalg參數。 之后,修改后的密鑰被重新導入並用於使用 RSAES-OAEP 進行加密/解密:

 (async () => { // Generate const keyDetails = await window.crypto.subtle.generateKey( { name: 'RSASSA-PKCS1-v1_5', modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: { name: 'SHA-256' }, }, true, ['verify', 'sign'] ); console.log(keyDetails) // Export const publicKey = await window.crypto.subtle.exportKey('jwk', keyDetails.publicKey); const privateKey = await window.crypto.subtle.exportKey('jwk', keyDetails.privateKey); console.log(publicKey) console.log(privateKey) // Adapt parameters and import publicKey.key_ops = ['encrypt']; privateKey.key_ops = ['decrypt']; publicKey.alg = 'RSA-OAEP-256'; privateKey.alg = 'RSA-OAEP-256'; const publicKeyReloaded = await window.crypto.subtle.importKey("jwk", publicKey, {name: "RSA-OAEP", hash: {name: "SHA-256"}}, true, ["encrypt"]); const privateKeyReloaded = await window.crypto.subtle.importKey("jwk", privateKey,{name: "RSA-OAEP", hash: {name: "SHA-256"}}, true, ["decrypt"]); console.log(publicKeyReloaded) console.log(privateKeyReloaded) // Encrypt/Decrypt const enc = new TextEncoder(); const encodedText = enc.encode("testing 1234"); const encryptedText = await window.crypto.subtle.encrypt({name: "RSA-OAEP"}, publicKeyReloaded, encodedText) console.log(ab2b64(encryptedText)); const dec = new TextDecoder(); const decryptedText = await window.crypto.subtle.decrypt({name: "RSA-OAEP"}, privateKeyReloaded, encryptedText) console.log(dec.decode(decryptedText)); // Helper function ab2b64(arrayBuffer) { return window.btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer))); } })();

請注意,通常相同的密鑰對實際上應該用於簽名/驗證或加密/解密,而不是同時用於兩者,請參見此處
WebCrypto API 通過將密鑰的用途綁定到它來提供一些防止這種濫用的保護(但是,這種保護很容易被規避,如上所示)。

好吧,@topaco 已經提供了答案。 現在我只想在這里添加一個方法。 如果有人想在 [JSON Web 加密 - 密文] JOSE npm lib 的幫助下加密和解密敏感數據。 使用僅為簽名/驗證而生成的公鑰/私鑰!

const jose = require('jose'); // npm i jose
async encryptDecryptLogic(data: string): Promise<any>{

    const keyDetails = await window.crypto.subtle.generateKey(
          {
              name: 'RSASSA-PKCS1-v1_5',
              modulusLength: 2048, 
              publicExponent: new Uint8Array([1, 0, 1]),
              hash: { name: 'SHA-256' }, 
          },
          true, 
          ['verify', 'sign'] 
      );

       // updating operation from sign-varify to encrypt-decrypt.
       // As that private/ public key is generated for sign and verification purposes only but here we extended its purpose. So we need to update a few properties to do encryption/decryption

        publicKey.key_ops = ['encrypt'];
        privateKey.key_ops = ['decrypt'];

        // updating algo from sign-varify[RS256] to encrypt-decrypt[RSA-OAEP]
        // Defines the algorithm used to encrypt the Content Encryption Key (CEK). This MUST be set to “RSA-OAEP”.

        publicKey.alg = 'RSA-OAEP';
        privateKey.alg = 'RSA-OAEP';

 const encodedText =  await this.jose.jwe.encrypt(publicKey, "lets encrypt me!!")
        console.log('encodedText', encodedText);

 const decodedText =  await this.jose.jwe.decrypt(privateKey, encodedText)
        console.log('decodedText', decodedText);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM