[英]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加解密。 有關詳細信息,請參閱RFC8017和WebCrypto API 。
此外,必須首先修改導出的 JWK 密鑰以進行加密/解密。 然后必須導入密鑰才能用於加密/解密。
以下示例對此進行了演示:首先,生成一個用於使用 RSASSA-PKCS1-v1_5 進行簽名/驗證的密鑰對。 兩個密鑰都導出為 JWK。 然后調整key_ops
和alg
參數。 之后,修改后的密鑰被重新導入並用於使用 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.