尝试使用 ethers.Wallet.fromEncryptedJson 时出现“错误:密码无效”

问题描述 投票:0回答:0

我刚开始摆弄密码学,我试图用以太坊钱包公钥加密文档,然后用同一个钱包的私钥解密它。

我有这些功能来实现:

import { stringToWordArray, wordArrayToArrayBuffer, wordArrayToUint8Array } from "./utls";
import { ethers, utils, providers } from 'ethers';
import * as CryptoJS from 'crypto-js';

// Generate a random symmetric key
export const generateSymmetricKey = async (): Promise<{ key: string; iv: string }> => {
    const key = CryptoJS.lib.WordArray.random(256 / 8).toString(CryptoJS.enc.Hex);
    const iv = CryptoJS.lib.WordArray.random(128 / 8).toString(CryptoJS.enc.Hex);
    return { key, iv };
};

// Encrypt a document using a symmetric key
export const encryptDocument = async (publicKey: string, document: Blob, iv: CryptoJS.lib.WordArray): Promise<string> => {
    // Convert document to WordArray
    const fileReader = new FileReader();
    fileReader.readAsArrayBuffer(document);
    const arrayBuffer = await new Promise<ArrayBuffer>((resolve) => {
        fileReader.onload = (event) => {
            if (event.target) {
                resolve(event.target.result as ArrayBuffer);
            }
        };
    });

    const uint8Array = new Uint8Array(arrayBuffer);
    const array = Array.from(uint8Array, (byte) => byte);
    const wordArray = CryptoJS.lib.WordArray.create(array);

    // Generate random AES key
    const aesKey = CryptoJS.lib.WordArray.random(256 / 8);

    // Encrypt document with AES key
    const encryptedDoc = CryptoJS.AES.encrypt(wordArray, aesKey, { mode: CryptoJS.mode.CBC, iv: iv });

    // Encrypt AES key with recipient's public key
    const encryptedAesKey = CryptoJS.enc.Base64.stringify(CryptoJS.AES.encrypt(
        aesKey.toString(),
        publicKey,
        {
            mode: CryptoJS.mode.CBC,
            iv: iv
        },
    ).ciphertext);

    // Return concatenated encrypted AES key and encrypted document
    return `${encryptedAesKey}\n${encryptedDoc}`;
}

// Function to decrypt document
export const decryptDocument = async (encryptedDocument: string, decryptedSymmetricKey: CryptoJS.lib.WordArray, iv: CryptoJS.lib.WordArray): Promise<ArrayBuffer> => {
    // Convert the encrypted document to a WordArray
    const encryptedWordArray = CryptoJS.enc.Hex.parse(encryptedDocument);

    // Decrypt the document using the decrypted symmetric key and IV
    const decryptedDocumentWordArray = CryptoJS.AES.decrypt(
        CryptoJS.lib.CipherParams.create({ ciphertext: encryptedWordArray }),
        decryptedSymmetricKey,
        { iv: iv }
    );

    // Convert the decrypted document to an ArrayBuffer
    const decryptedData = new Uint8Array(decryptedDocumentWordArray.words);
    return decryptedData.buffer;
}

// Encrypt a symmetric key using the Ethereum wallet public key
export const encryptSymmetricKey = async (publicKey: string, symmetricKey: CryptoJS.lib.WordArray, iv: CryptoJS.lib.WordArray): Promise<string> => {
    const aesKey = CryptoJS.enc.Base64.stringify(symmetricKey);
    const aesIv = CryptoJS.enc.Base64.stringify(iv);

    const provider = new ethers.providers.AlchemyProvider('mainnet', 'SF*************9A');
    const wallet = ethers.Wallet.createRandom().connect(provider);
    const encrypted = await wallet.encrypt(JSON.stringify({ key: aesKey, iv: aesIv }), { publicKey });
    return encrypted;
}

// Decrypt a symmetric key using the Ethereum wallet private key
export const decryptSymmetricKey = async (privateKey: string, encryptedSymmetricKey: string, iv: string): Promise<{ key: CryptoJS.lib.WordArray; iv: CryptoJS.lib.WordArray }> => {
    // Decrypt encrypted symmetric key with private key
    // const encryptedJson = JSON.parse(encryptedSymmetricKey);
    const wallet = await ethers.Wallet.fromEncryptedJson(encryptedSymmetricKey, privateKey);

    console.log('Wallet: ', wallet)

    // Decrypt AES key from encrypted data
    const decryptedAesKey = CryptoJS.enc.Utf8.parse(wallet.privateKey.slice(2));
    const ivWordArray = CryptoJS.enc.Hex.parse(iv);

    return {
        key: decryptedAesKey,
        iv: ivWordArray,
    };
}

然后我在以下测试函数中测试它们:

async function test(file: Blob) {
        const wallet = ethers.Wallet.createRandom();

        const { key, iv } = await generateSymmetricKey();
        const encryptedDocument = await encryptDocument(wallet.publicKey, file, stringToWordArray(iv));

        const encryptedSymmetricKey = await encryptSymmetricKey(wallet.publicKey, stringToWordArray(key), stringToWordArray(iv));

        console.log('encryptedDocument: ', encryptedDocument)
        console.log('encryptedSymmetricKey: ', encryptedSymmetricKey)

        // Decrypt the symmetric key using the ethereum wallet private key
        const decryptedSymmetricKey = await decryptSymmetricKey(wallet.privateKey, encryptedSymmetricKey, iv);

        // Decrypt the document using the decrypted symmetric key
        const decryptedDocument = await decryptDocument(encryptedDocument, decryptedSymmetricKey.key, decryptedSymmetricKey.iv);

        console.log('decryptedSymmetricKey: ', decryptedSymmetricKey)
        console.log('decryptedDocument: ', decryptedDocument)
}

我能够成功加密文档和对称密钥。因此,当记录它们时,我得到类似这样的 encryptedDocument 的东西,它是非常长的字符串。

encryptedDocument:  atsbkigb2TrbyAe3kJ0uyBgAAku/Pllua83TJao018fmCmbZ6WCA/qVdO7dEf7SUdvpxPA/wq6aJkP1K61831sKLZORI3TrA0szGi3RjnC4=
aTsKhdzRufdtFmtirmdm5S4a8ppf+OSix6Rnr7QNzBzpZ9cqvpl/UuR0pphtCeW1xR8Bq6nPb26WxvrWlUaa2F855S1K0J0wzpeyYHnYBEGairjgU7vkemP2gVB9iOm76J2Hhd7t2aSJg7Ds4vBKwdlmbPP+vVmyl4YFSbi1vz20+4T7N/P7sC5VIKva5Y8738qtvt2l1vpg...

对于加密的对称密钥:

{"address":"7bd44*****************6eee81","id":"3e9dbab7-cda1-44d3-9b75-0d653b775264","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"cc5c23****************626d0"},"ciphertext":"873******************9d97bc3c40","kdf":"scrypt","kdfparams":{"salt":"5114b**********************11a93b64","n":131072,"dklen":32,"p":1,"r":8},"mac":"ded3de**********ed2e18033a"},"x-ethers":{"client":"ethers.js","gethFilename":"UTC--2023-02-23T08-09-41.0Z--7bd44a2656bc6fa08ab07e12034a2c94936eee81","mnemonicCounter":"88d13d*********19fd9540","mnemonicCiphertext":"74643be**********03ae0e6e","path":"m/44'/60'/0'/0/0","locale":"en","version":"0.1"}}

当我尝试解密对称密钥时出现问题。所以在

decryptSymmetricKey
函数中,错误发生在这一行:

const wallet = await ethers.Wallet.fromEncryptedJson(encryptedSymmetricKey, privateKey);

Error: invalid password

看来以太坊钱包的privateKey是不正确的

我不确定我在哪里犯了错误,因为我确定我正在从同一个以太坊钱包传递用于加密的公钥和用于解密的私钥。

cryptography public-key-encryption cryptojs encryption-symmetric ethers.js
© www.soinside.com 2019 - 2024. All rights reserved.