我正在构建一个移动应用程序,该应用程序应该可以离线工作并离线加密数据。该应用程序是用 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:
,这让我认为问题出在我的离线解密算法上。
有什么关于我做错了什么的指示吗?
问题是我需要向解密过程提供 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))