|
|
- import 'dart:convert';
- import 'dart:typed_data';
- import "package:pointycastle/export.dart";
-
- Uint8List createUint8ListFromString(String s) {
- var ret = Uint8List(s.length);
- for (var i = 0; i < s.length; i++) {
- ret[i] = s.codeUnitAt(i);
- }
- return ret;
- }
-
- // AES key size
- const keySize = 32; // 32 byte key for AES-256
- const iterationCount = 1000;
-
- class AesHelper {
- static const cbcMode = 'CBC';
- static const cfbMode = 'CFB';
-
- static Uint8List deriveKey(dynamic password,
- {String salt = '',
- int iterationCount = iterationCount,
- int derivedKeyLength = keySize}) {
-
- if (password == null || password.isEmpty) {
- throw ArgumentError('password must not be empty');
- }
-
- if (password is String) {
- password = createUint8ListFromString(password);
- }
-
- Uint8List saltBytes = createUint8ListFromString(salt);
- Pbkdf2Parameters params = Pbkdf2Parameters(saltBytes, iterationCount, derivedKeyLength);
- KeyDerivator keyDerivator = PBKDF2KeyDerivator(HMac(SHA256Digest(), 64));
- keyDerivator.init(params);
-
- return keyDerivator.process(password);
- }
-
- static Uint8List pad(Uint8List src, int blockSize) {
- var pad = PKCS7Padding();
- pad.init(null);
-
- int padLength = blockSize - (src.length % blockSize);
- var out = Uint8List(src.length + padLength)..setAll(0, src);
- pad.addPadding(out, src.length);
-
- return out;
- }
-
- static Uint8List unpad(Uint8List src) {
- var pad = PKCS7Padding();
- pad.init(null);
-
- int padLength = pad.padCount(src);
- int len = src.length - padLength;
-
- return Uint8List(len)..setRange(0, len, src);
- }
-
- static String aesEncrypt(String password, Uint8List plaintext,
- {String mode = cbcMode}) {
- Uint8List derivedKey = deriveKey(password);
- KeyParameter keyParam = KeyParameter(derivedKey);
- BlockCipher aes = AESEngine();
-
- var rnd = FortunaRandom();
- rnd.seed(keyParam);
- Uint8List iv = rnd.nextBytes(aes.blockSize);
-
- BlockCipher cipher;
- ParametersWithIV params = ParametersWithIV(keyParam, iv);
- switch (mode) {
- case cbcMode:
- cipher = CBCBlockCipher(aes);
- break;
- case cfbMode:
- cipher = CFBBlockCipher(aes, aes.blockSize);
- break;
- default:
- throw ArgumentError('incorrect value of the "mode" parameter');
- }
- cipher.init(true, params);
-
- Uint8List paddedText = pad(plaintext, aes.blockSize);
- Uint8List cipherBytes = _processBlocks(cipher, paddedText);
- Uint8List cipherIvBytes = Uint8List(cipherBytes.length + iv.length)
- ..setAll(0, iv)
- ..setAll(iv.length, cipherBytes);
-
- return base64.encode(cipherIvBytes);
- }
-
- static String aesDecrypt(String password, Uint8List ciphertext,
- {String mode = cbcMode}) {
- Uint8List derivedKey = deriveKey(password);
- KeyParameter keyParam = KeyParameter(derivedKey);
- BlockCipher aes = AESEngine();
-
- Uint8List iv = Uint8List(aes.blockSize)
- ..setRange(0, aes.blockSize, ciphertext);
-
- BlockCipher cipher;
- ParametersWithIV params = ParametersWithIV(keyParam, iv);
- switch (mode) {
- case cbcMode:
- cipher = CBCBlockCipher(aes);
- break;
- case cfbMode:
- cipher = CFBBlockCipher(aes, aes.blockSize);
- break;
- default:
- throw ArgumentError('incorrect value of the "mode" parameter');
- }
- cipher.init(false, params);
-
- int cipherLen = ciphertext.length - aes.blockSize;
- Uint8List cipherBytes = Uint8List(cipherLen)
- ..setRange(0, cipherLen, ciphertext, aes.blockSize);
- Uint8List paddedText = _processBlocks(cipher, cipherBytes);
- Uint8List textBytes = unpad(paddedText);
-
- return String.fromCharCodes(textBytes);
- }
-
- static Uint8List _processBlocks(BlockCipher cipher, Uint8List inp) {
- var out = Uint8List(inp.lengthInBytes);
-
- for (var offset = 0; offset < inp.lengthInBytes;) {
- var len = cipher.processBlock(inp, offset, out, offset);
- offset += len;
- }
-
- return out;
- }
- }
|