window.crypto.subtle.decrypt 的操作错误问题

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

我正在开发一个会话加密方案,但是当我尝试使用私钥解密会话密钥时,我收到一个

OperationError

// This method generates the keys
static async generateKeysForUser(): Promise<{ publicKey: string, privateKey: string }> {
    const keyPair = await window.crypto.subtle.generateKey(
        {
            name: "RSA-OAEP",
            modulusLength: 2048,
            publicExponent: new Uint8Array([1, 0, 1]), // 65537
            hash: "SHA-1",
        },
        true,
        ["encrypt", "decrypt"]
    );

    const publicKey = await window.crypto.subtle.exportKey("jwk", keyPair.publicKey);
    const privateKey = await window.crypto.subtle.exportKey("jwk", keyPair.privateKey);

    const publicKeyStr = JSON.stringify(publicKey);
    const privateKeyStr = JSON.stringify(privateKey);

    await this.storeKeys(privateKeyStr, publicKeyStr);

    return publicKey;
}
// This method encrypts the session on the backend
public static function generateSessionKey($length = 32)
{
    return bin2hex(random_bytes($length)); // 32 bytes = 256 bits
}

public static function jsonToPem($publicKeyJson)
{
    $jwkObject = new JWK($publicKeyJson);
    $rsaKey = RSAKey::createFromJWK($jwkObject);
    return $rsaKey->toPEM();
}

public static function encryptSessionKey($sessionKey, $publicKeyJson): string
{
    $publicKeyPem = self::jsonToPem($publicKeyJson);
    $publicKey = openssl_pkey_get_public($publicKeyPem);
    openssl_public_encrypt($sessionKey, $encryptedSessionKey, $publicKey);
    return base64_encode($encryptedSessionKey);
}
// This method decrypts the session key on the front end
private static async importKey(jwk: JsonWebKey, keyType: 'private' | 'public'): Promise<CryptoKey> {
    console.log(jwk);
    let operation = keyType == 'private' ? 'decrypt' : 'encrypt';
    console.log(keyType, operation);
    let result = await window.crypto.subtle.importKey(
        "jwk",
        jwk,
        {
            name: "RSA-OAEP",
            hash: "SHA-1"
        },
        true,
        [operation]
    );
    console.log(result);
    return result;
}

static async decryptSessionKey(encryptedSessionKeyBase64: string, jwk: JsonWebKey): Promise<ArrayBuffer | null> {
    try {
        let privateKey = await this.importKey(jwk, "private");

        const encryptedSessionKey = Uint8Array.from(atob(encryptedSessionKeyBase64), c => c.charCodeAt(0));

        console.log('Encrypted Session Key (Uint8Array):', encryptedSessionKey);
        console.log('Private Key:', privateKey);

        const result = await window.crypto.subtle.decrypt(
            {
                name: "RSA-OAEP"
            },
            privateKey,
            encryptedSessionKey
        );

        console.log('Decrypted Result (ArrayBuffer):', result);

        return result;
    } catch (e) {
        console.error('Decryption failed:', e);
        return null;
    }
}

我已经尝试检查后端和前端的密钥是否匹配,以确保发送正确的密钥,并且我还尝试将密钥生成密码从 SHA-256 更改为 SHA-1。

我发现问题出在 PADDING 上

    public static function encryptSessionKey($sessionKey, $publicKeyJson): string
    {
        $publicKeyPem = self::jsonToPem($publicKeyJson);
        $publicKey = openssl_pkey_get_public($publicKeyPem);
        openssl_public_encrypt($sessionKey, $encryptedSessionKey, $publicKey,OPENSSL_PKCS1_OAEP_PADDING );
        return base64_encode($encryptedSessionKey);
    }

php typescript encryption webcrypto-api
1个回答
0
投票

我发现了问题;我使用了错误的填充进行加密。我切换到 OPENSSL_PKCS1_OAEP_PADDING 并且它有效。

© www.soinside.com 2019 - 2024. All rights reserved.