需要帮助加密/解密这种格式的文件=> openssl aes-256-cbc -d -salt -pbkdf2 -iter 10000 -in cryptofilename -out plaintextfilename

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

我有一个网站来加密和解密文件,我想创建一个flutter应用程序来使用相同的格式加密和解密,但我不知道如何做到这一点,下面是加密的格式

openssl aes-256-cbc -d -salt -pbkdf2 -iter 10000 -in encryptedfilename -out plaintextfilename

关于如何使用上述格式创建加密/解密函数有什么建议吗?我已经尝试了大部分flutter加密包但没有找到任何解决方案

   static Future<File?> aesEncryptTest(String password, File file) async {
    final _password = Password.hash(password, PBKDF2());
    var bytes = utf8.encode(_password);
    var digest = sha256.convert(bytes);
    var fDigest = md5.convert(digest.bytes);

    final key = Key.fromUtf8(fDigest.toString());
    final iv = IV.fromLength(16);

    final encrypter = Encrypter(AES(key, mode: AESMode.cbc, padding: "PKCS7"));

    final fileBytes = await file.readAsBytes();
    final encryptedData = encrypter.encryptBytes(fileBytes, iv: iv);

    File _file =
        await File(file.path + '.enc').writeAsBytes(encryptedData.bytes);

    _file.writeAsBytesSync(encryptedData.bytes);

    await FileServices.saveFile(_file.path);

    
    return encryptedFile;
  }

  static Future<File?> aesDecryptTest(String password, File file) async {
    final _password = Password.hash(password, PBKDF2());
    var bytes = utf8.encode(_password);
    var digest = sha256.convert(bytes);
    var fDigest = md5.convert(digest.bytes);

    final key = Key.fromUtf8(fDigest.toString());
    final iv = IV.fromLength(16);

    final encrypter = Encrypter(AES(key, mode: AESMode.cbc, padding: "PKCS7"));

    final fileBytes = await file.readAsBytes();
    final decryptedBytes = encrypter.decryptBytes(Encrypted(fileBytes), iv: iv);

    File _file =
        await File(withoutExtension(file.path)).writeAsBytes(decryptedBytes);

    _file.writeAsBytesSync(decryptedBytes);

    await FileServices.saveFile(_file.path, extraName: 'DECRYPTED');

    return File(decryptedFile);
  }
flutter dart encryption openssl aes
1个回答
0
投票

对于加密,在 Dart 代码中:

  • 必须生成随机的 8 字节盐,
  • 必须使用 PBKDF2 从密码和盐中派生出 32 字节密钥和 16 字节 IV,
  • 必须使用派生密钥和 IV 使用 AES-256、CBC 模式和 PKCS#7 填充对明文进行加密,
  • 数据必须采用 OpenSSL 格式:
    Salted__
    的 ASCII 编码加上 8 字节的 Sals 加上密文。

一个可能的实现是:

import 'dart:math';
import 'dart:typed_data';
import 'dart:convert';
import 'package:pointycastle/export.dart';
import 'dart:io';

...

// generate random 8 bytes salt
SecureRandom secureRandom = getSecureRandom();
Uint8List salt = secureRandom.nextBytes(8);

// derive key and IV via password and salt
Uint8List passphrase = Uint8List.fromList(utf8.encode('my passphrase'));
Uint8List keyIv = deriveKeyIv(salt, passphrase);
Uint8List key = keyIv.sublist(0, 32);
Uint8List iv = keyIv.sublist(32);

// encrypt using AES-256, CBC mode
File ptFile = File('<path to plaintext.txt file>');
Uint8List ptFileBytes = await ptFile.readAsBytes();
Uint8List ciphertext = encryptAesCbcPkcs7(ptFileBytes, key, iv);

// apply OpenSSL format: Salted__ | <8 bytes salt> | ciphertext
Uint8List prefixSaltCiphertext = concatAndEncode(salt, ciphertext);

File ctFile = File('path to ciphertext.enc file');
await ctFile.writeAsBytes(prefixSaltCiphertext);

Uint8List deriveKeyIv(Uint8List salt, Uint8List passphrase){
  KeyDerivator derivator = KeyDerivator('SHA-256/HMAC/PBKDF2');
  Pbkdf2Parameters params = Pbkdf2Parameters(salt, 10000, (256 + 128)~/8);
  derivator.init(params);
  return derivator.process(passphrase);
}

Uint8List encryptAesCbcPkcs7(Uint8List plaintext, Uint8List key, Uint8List iv){
  CBCBlockCipher cipher = CBCBlockCipher(AESEngine());
  ParametersWithIV<KeyParameter> params = ParametersWithIV<KeyParameter>(KeyParameter(key), iv);
  PaddedBlockCipherParameters<ParametersWithIV<KeyParameter>, Null> paddingParams = PaddedBlockCipherParameters<ParametersWithIV<KeyParameter>, Null>(params, null);
  PaddedBlockCipherImpl paddingCipher = PaddedBlockCipherImpl(PKCS7Padding(), cipher);
  paddingCipher.init(true, paddingParams);
  Uint8List ciphertext = paddingCipher.process(plaintext);
  return ciphertext;
}

Uint8List concatAndEncode(Uint8List salt, Uint8List ciphertext){
  BytesBuilder prefixSaltCiphertext = BytesBuilder();
  prefixSaltCiphertext.add(utf8.encode('Salted__'));
  prefixSaltCiphertext.add(salt);
  prefixSaltCiphertext.add(ciphertext);
  return prefixSaltCiphertext.toBytes();
}

以这种方式生成的密文可以使用发布的 OpenSSL 语句进行解密(顺便说一句,这是用于解密而不是加密)。

这里必须考虑到,OpenSSL 在早期版本中使用 MD5 作为默认数字,从 v1.1.0 开始使用 SHA256。上面的代码假设 SHA256。如果您有较旧的 OpenSSL 版本,您可以在 OpenSSL 语句中设置

-md sha256
。或者,代码必须适应 MD5。


对于加密,在 Dart 代码中:

  • 必须从 OpenSSL 格式的加密数据中提取 8 字节盐和密文,
  • 必须使用 PBKDF2 从密码和盐中派生出 32 字节密钥和 16 字节 IV,
  • 必须使用此密钥和 IV 使用 AES-256、CBC 模式和 PKCS#7 填充来解密密文。

实现方式类似于加密。

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