AWS SDK Decrypt - 调用 Decrypt 操作时发生错误 (InvalidCiphertextException):

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

我正在构建一个移动应用程序,该应用程序应该可以离线工作并离线加密数据。该应用程序是用 ionic 构建的。

我编写了一个加密服务,给定文件名,加密数据并输出加密文件。

import { Injectable } from '@angular/core';
import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
import * as CryptoJS from 'crypto-js';
import { environment } from 'src/environments/environment';

@Injectable({
  providedIn: 'root',
})
export class EncryptionService {
  private encryptionKey: string;

  constructor() {
    // Initialize the encryption key (base64 encoded string)
    this.encryptionKey = environment.encryptionKey;
  }

  // Function to encrypt file content using AES
  public async encryptFile(fileName: string): Promise<void> {
    try {
      // Step 1: Read the file content
      const file = await Filesystem.readFile({
        path: fileName,
        directory: Directory.Documents,
        encoding: Encoding.UTF8, // Assuming text-based files (change if necessary)
      });

      let fileContents: string;

      // Step 2: Ensure fileContents is a string
      if (typeof file.data === 'string') {
        fileContents = file.data;
      } else {
        throw new Error('Unsupported file format, expected string.');
      }

      // Step 3: Encrypt the content using AES
      const iv = CryptoJS.lib.WordArray.random(12); // Generate a random 16-byte IV
      const encrypted = CryptoJS.AES.encrypt(fileContents, CryptoJS.enc.Base64.parse(this.encryptionKey), {
        iv: iv,
        format: CryptoJS.format.OpenSSL, // Using OpenSSL formatting
      });

      // Step 4: Combine the IV and ciphertext
      const combinedData = iv.concat(encrypted.ciphertext);
      const encryptedDataBase64 = CryptoJS.enc.Base64.stringify(combinedData);
      console.log('Encrypted data:', encryptedDataBase64);

      // Step 5: Write the encrypted content back to the file system
      const encryptedFileName = `encrypted_${fileName}`;

      await Filesystem.writeFile({
        path: encryptedFileName,
        data: encryptedDataBase64,
        directory: Directory.Documents,
        encoding: Encoding.UTF8,
      });

      console.log('File encrypted and saved as:', encryptedFileName);
    } catch (error) {
      console.error('Error encrypting file:', error);
    }
  }
}

这效果很好,加密了数据和所有内容。数据应该从 AWS 解密。

问题是,当我尝试使用 was cli 解密数据时,出现错误。

ENCRYPTED_DATA=$(cat encrypted_sample.txt)
DECRYPTED_DATA=$(aws kms decrypt --profile <profile-string-here> \
  --key-id <key-id-string-here> \
  --ciphertext-blob fileb://<(echo "$ENCRYPTED_DATA" | base64 --decode) \
  --region eu-west-1 \
  --query Plaintext \
  --output text)
echo "Decrypted data: $(echo "$DECRYPTED_DATA" | base64 --decode)"

我得到

An error occurred (InvalidCiphertextException) when calling the Decrypt operation:
,这让我认为问题出在我的离线解密算法上。

有什么关于我做错了什么的指示吗?

amazon-web-services ionic-framework encryption aes
1个回答
0
投票

问题是我需要向解密过程提供 Iv。 我必须生成 IV 和加密数据的组合来进行解密过程。

import { Injectable } from '@angular/core';
import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
import * as CryptoJS from 'crypto-js';
import { environment } from 'src/environments/environment';

@Injectable({
  providedIn: 'root',
})
export class EncryptionService {
  private dek: string;
  constructor() {
    this.dek = environment.encryptionKey;
  }

  public async encryptFile(fileName: string): Promise<void> {
    try {
      const file = await Filesystem.readFile({
        path: fileName,
        directory: Directory.Documents,
        encoding: Encoding.UTF8,
      });

      const fileContents = file.data as string;

      // Generate a 16-byte IV
      const iv = CryptoJS.lib.WordArray.random(16);
      const key = CryptoJS.enc.Base64.parse(this.dek);

      // Encrypt using AES
      const encryptedData = CryptoJS.AES.encrypt(fileContents, key, {
        iv: iv,
        format: CryptoJS.format.OpenSSL, // Using OpenSSL formatting
      });

      // Concatenate the IV and encrypted data, then convert to Base64
      const ivBase64 = CryptoJS.enc.Base64.stringify(iv);
      const encryptedDataBase64 = encryptedData.toString();

      const combinedData = ivBase64 + ':' + encryptedDataBase64; // Separate IV and encrypted data
      let encryptedFileName = `encrypted_${fileName}`;

      await Filesystem.writeFile({
        path: encryptedFileName,
        data: combinedData,
        directory: Directory.Documents,
        encoding: Encoding.UTF8,
      });
    } catch (error) {
      console.error('Error encrypting file:', error);
    }
  }
}

解密Python函数然后将IV与加密数据分离并使用相同的DEK。

import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from decouple import config

def decrypt_file(encrypted_data: str, dek: str) -> str:
    # Decode the Base64 encoded key
    key = base64.b64decode(dek)

    # Split the IV and the ciphertext
    iv_base64, cipher_text_base64 = encrypted_data.split(':')
    iv = base64.b64decode(iv_base64)  # Decode the Base64 IV
    cipher_text = base64.b64decode(cipher_text_base64)  # Decode the Base64 ciphertext

    # Create AES cipher
    cipher = AES.new(key, AES.MODE_CBC, iv)

    # Decrypt and unpad the data
    decrypted_data = unpad(cipher.decrypt(cipher_text), AES.block_size)
    
    return decrypted_data.decode('utf-8')


if __name__ == "__main__":
    # read encrypted sample from file
    with open('encrypted_sample.txt', 'r') as file:
        encrypted_sample = file.read()
    
    # read DEK from environment variable
    dek_base64 = config('ENCRYPTION_KEY')
    decoded_key = base64.b64decode(dek_base64)

    try:
        decrypted_text = decrypt_file(encrypted_sample, dek_base64)
        print("Decrypted Data:", decrypted_text)
    except Exception as e:
        print("Decryption failed:", str(e))

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