Skip to content

Commit f87b1e0

Browse files
authored
Feature: AES-CTR (#24)
The branch is named AES-CTR as it focuses on implementing AES encryption in Counter (CTR) mode, a widely used and efficient encryption mode that enables parallel processing of data. It does so by turning a block cipher into a stream cipher: it encrypts successive values of a counter and XORs the result with the plaintext. While this implementation currently targets AES256Randomized (256-bit key size), the architecture is designed to be extensible, allowing future support for other AES key lengths (e.g., 128-bit, 192-bit) and additional cipher modes such as (e.g., CBC or GCM). This branch introduces reimplementation of the AES-CTR encryption algorithm using principles and components inspired by the encrypt and pointycastle packages. The goal was to provide a modular, testable, and extensible AES infrastructure, enabling secure encryption and decryption of sensitive data in compliance with cryptographic standards. List of changes: - created aes_ctr.dart, aes256_randomized.dart, and aes_engine.dart to implement AES encryption logic and coordinate the encryption process - created cipher_text.dart to represent the result of an encryption algorithm and encapsulate the encrypted data - created aes_iv.dart to represent the initialization vector (IV), enabling unique encryption sessions - created aes_key.dart to store AES key used in encryption - created i_cipher_key.dart, a_block_cipher.dart, i_cipher_padding.dart, to define the base abstraction to block, padding and cipher key - created cipher_key_with_iv.dart to encapsulate both AES key and IV for cipher initialization - created ctr_stream_cipher.dart to implement CTR (Counter) mode to stream cipher using a block cipher - created padded_block_cipher.dart and ctr_block_cipher.dart to enable AES block cipher processing with support for padding and arbitrary-length input - created pkcs7_padding.dart to implement the PKCS7 padding scheme used for aligning plaintext blocks before encryption - unrelated with domain: changed the Ubuntu Actions runner image to the latest general availability version 24.04, due to the deprecation of the version 20.04
1 parent 693c5b8 commit f87b1e0

37 files changed

Lines changed: 2181 additions & 299 deletions

.github/workflows/version_and_tests.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88

99
jobs:
1010
app-version-check:
11-
runs-on: ubuntu-20.04
11+
runs-on: ubuntu-24.04
1212
steps:
1313
# https://github.com/marketplace/actions/checkout
1414
- uses: actions/checkout@main
@@ -42,7 +42,7 @@ jobs:
4242
exit 1
4343
run-unit-tests:
4444
needs: app-version-check
45-
runs-on: ubuntu-20.04
45+
runs-on: ubuntu-24.04
4646
steps:
4747
# https://github.com/marketplace/actions/checkout
4848
- uses: actions/checkout@main

lib/cryptography_utils.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ library cryptography_utils;
22

33
export 'src/bip/bip.dart';
44
export 'src/cdsa/cdsa.dart';
5+
export 'src/encryption/aes/aes256_randomized.dart';
56
export 'src/hash/hmac.dart';
67
export 'src/hash/keccak/keccak.dart';
78
export 'src/hash/pbkdf2.dart';
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import 'dart:convert';
2+
import 'dart:typed_data';
3+
4+
import 'package:cryptography_utils/cryptography_utils.dart';
5+
import 'package:cryptography_utils/src/encryption/aes/aes_ctr.dart';
6+
import 'package:cryptography_utils/src/encryption/aes/aes_iv.dart';
7+
import 'package:cryptography_utils/src/encryption/aes/aes_key.dart';
8+
import 'package:cryptography_utils/src/encryption/aes/invalid_password_exception.dart';
9+
import 'package:cryptography_utils/src/encryption/cipher/cipher_text.dart';
10+
import 'package:cryptography_utils/src/utils/secure_random.dart';
11+
12+
/// The `AES256Randomized` class provides secure encryption and decryption of text (strings)
13+
/// using the AES-256 algorithm in CTR mode. The class enables confidential storage of textual data
14+
/// and ensuring that access is only possible with the correct password.
15+
///
16+
/// Moreover, the use of a random salt (of length 16) and the SHA-256 hash function enhances security and makes attacks significantly more difficult.
17+
///
18+
class AES256Randomized {
19+
/// Encrypts the provided plaintext using the given password.
20+
/// A random 16-byte salt is generated, and the password is hashed using SHA-256 to produce the encryption key.
21+
/// The salt and password hash are combined and hashed again to derive a secure value,
22+
/// from which the initialization vector (IV), and checksum are extracted.
23+
/// The plaintext is then encrypted using AES-256 in CTR mode and returned as a Base64-encoded string,
24+
/// with the salt prepended and the checksum appended.
25+
static String encrypt(String password, String decryptedString) {
26+
Uint8List decryptedUint8List = utf8.encode(decryptedString);
27+
Uint8List randomUint8List = SecureRandom.getBytes(length: 16, max: 255);
28+
29+
Uint8List hashedPasswordUint8List = Sha256().convert(utf8.encode(password)).byteList;
30+
Uint8List securePasswordUint8List = Sha256().convert(randomUint8List + hashedPasswordUint8List).byteList;
31+
32+
AESKey aesKey = AESKey(hashedPasswordUint8List);
33+
34+
Uint8List initializationVectorUint8List = Uint8List.fromList(securePasswordUint8List.getRange(0, 16).toList());
35+
AESIV aesIV = AESIV(initializationVectorUint8List);
36+
37+
Uint8List encryptedUint8List = AESctr.encrypt(decryptedUint8List, aesKey, aesIV).uint8List;
38+
39+
List<int> checksumUint8List = securePasswordUint8List.getRange(securePasswordUint8List.length - 4, securePasswordUint8List.length).toList();
40+
List<int> encryptedStringUint8List = randomUint8List + encryptedUint8List + checksumUint8List;
41+
String encryptedString = base64Encode(encryptedStringUint8List);
42+
43+
return encryptedString;
44+
}
45+
46+
/// Decrypts the provided encrypted string using the specified password.
47+
/// The password is hashed using SHA-256 to produce the encryption key.
48+
/// The salt and checksum are extracted from the encrypted input.
49+
/// Then, the salt and password hashes are combined and hashed again to derive a secure value,
50+
/// from which the initialization vector (IV) is reconstructed and the checksum is validated.
51+
/// The encrypted data is then decrypted using AES-256 in CTR mode,
52+
/// and the resulting plaintext is returned as a string.
53+
///
54+
/// Throws [InvalidPasswordException] if decryption fails, for example due to an incorrect password.
55+
static String decrypt(String password, String encryptedString) {
56+
try {
57+
Uint8List hashedPasswordUint8List = Sha256().convert(utf8.encode(password)).byteList;
58+
59+
Uint8List encryptedStringUint8List = base64Decode(encryptedString);
60+
Uint8List randomUint8List = Uint8List.fromList(encryptedStringUint8List.getRange(0, 16).toList());
61+
CipherText cipherText = CipherText(Uint8List.fromList(encryptedStringUint8List.getRange(16, encryptedStringUint8List.length - 4).toList()));
62+
Uint8List securePasswordUint8List = Sha256().convert(randomUint8List + hashedPasswordUint8List).byteList;
63+
64+
AESKey aesKey = AESKey(hashedPasswordUint8List);
65+
66+
Uint8List initializationVectorUint8List = Uint8List.fromList(securePasswordUint8List.getRange(0, 16).toList());
67+
AESIV aesIV = AESIV(initializationVectorUint8List);
68+
Uint8List decryptedUint8List = AESctr.decrypt(cipherText, aesKey, aesIV);
69+
String decryptedString = utf8.decode(decryptedUint8List);
70+
return decryptedString;
71+
} catch (e) {
72+
throw InvalidPasswordException('Decryption failed: ${e.toString()}');
73+
}
74+
}
75+
76+
/// Validates whether the provided [password] matches the checksum of the [encryptedString].
77+
/// This function checks if the password-derived checksum matches the stored one in the encrypted payload,
78+
/// without actually decrypting the content.
79+
/// Returns `true` if the password is valid; otherwise `false`.
80+
static bool isPasswordValid(String password, String encryptedString) {
81+
Uint8List hashedPasswordUint8List = Sha256().convert(utf8.encode(password)).byteList;
82+
83+
Uint8List encryptedStringUint8List = base64Decode(encryptedString);
84+
Uint8List randomUint8List = Uint8List.fromList(encryptedStringUint8List.getRange(0, 16).toList());
85+
List<int> expectedChecksumUint8List =
86+
encryptedStringUint8List.getRange(encryptedStringUint8List.length - 4, encryptedStringUint8List.length).toList();
87+
88+
Uint8List securePasswordUint8List = Sha256().convert(randomUint8List + hashedPasswordUint8List).byteList;
89+
List<int> actualChecksumUint8List = securePasswordUint8List.getRange(securePasswordUint8List.length - 4, securePasswordUint8List.length).toList();
90+
91+
return actualChecksumUint8List.toString() == expectedChecksumUint8List.toString();
92+
}
93+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
class AESConstants {
2+
static const List<int> rConList = <int>[
3+
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, //
4+
0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6,
5+
0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
6+
];
7+
8+
static const List<int> sList = <int>[
9+
99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, //
10+
215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212,
11+
162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247,
12+
204, 52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24,
13+
150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44,
14+
26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83,
15+
209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88,
16+
207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80,
17+
60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182,
18+
218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23,
19+
196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42,
20+
144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10,
21+
73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200,
22+
55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174,
23+
8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75,
24+
189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87,
25+
185, 134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148,
26+
155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191,
27+
230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22
28+
];
29+
30+
static const List<int> t0List = <int>[
31+
0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, //
32+
0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
33+
0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
34+
0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
35+
0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41,
36+
0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
37+
0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d,
38+
0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
39+
0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2,
40+
0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795,
41+
0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a,
42+
0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
43+
0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912,
44+
0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc,
45+
0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7,
46+
0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
47+
0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040,
48+
0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
49+
0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0,
50+
0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
51+
0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a,
52+
0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78,
53+
0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080,
54+
0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
55+
0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020,
56+
0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18,
57+
0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488,
58+
0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
59+
0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0,
60+
0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
61+
0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b,
62+
0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
63+
0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992,
64+
0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd,
65+
0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3,
66+
0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
67+
0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8,
68+
0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4,
69+
0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a,
70+
0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
71+
0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96,
72+
0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
73+
0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7,
74+
0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
75+
0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9,
76+
0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9,
77+
0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715,
78+
0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
79+
0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
80+
0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
81+
0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
82+
0x3a16162c
83+
];
84+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
//Copyright (c) 2018, Leo Cavalcante
2+
// All rights reserved.
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are met:
6+
//
7+
// * Redistributions of source code must retain the above copyright notice, this
8+
// list of conditions and the following disclaimer.
9+
//
10+
// * Redistributions in binary form must reproduce the above copyright notice,
11+
// this list of conditions and the following disclaimer in the documentation
12+
// and/or other materials provided with the distribution.
13+
//
14+
// * Neither the name of the copyright holder nor the names of its
15+
// contributors may be used to endorse or promote products derived from
16+
// this software without specific prior written permission.
17+
//
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21+
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22+
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23+
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24+
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25+
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26+
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28+
import 'dart:typed_data';
29+
30+
import 'package:cryptography_utils/src/encryption/aes/aes_engine.dart';
31+
import 'package:cryptography_utils/src/encryption/aes/aes_iv.dart';
32+
import 'package:cryptography_utils/src/encryption/aes/aes_key.dart';
33+
import 'package:cryptography_utils/src/encryption/cipher/block_cipher/ctr_block_cipher.dart';
34+
import 'package:cryptography_utils/src/encryption/cipher/block_cipher/padded_block_cipher.dart';
35+
import 'package:cryptography_utils/src/encryption/cipher/block_cipher/padding/pkcs7_padding.dart';
36+
import 'package:cryptography_utils/src/encryption/cipher/cipher_key_with_iv.dart';
37+
import 'package:cryptography_utils/src/encryption/cipher/cipher_mode.dart';
38+
import 'package:cryptography_utils/src/encryption/cipher/cipher_text.dart';
39+
40+
/// AES provides encryption and decryption using the AES algorithm in stream cipher mode (SIC/CTR).
41+
/// This implementation wraps the AES engine with a counter-based stream cipher and
42+
/// uses PKCS7 padding to support data of arbitrary length.
43+
///
44+
/// ****************** implemented modes ******************
45+
///
46+
/// CTR (Counter mode) – transforms a block cipher into a stream cipher.
47+
/// It generates a stream block by encrypting a nonce combined with a counter,
48+
/// then XORs the stream with the plaintext. CTR mode allows parallel encryption,
49+
/// random read/write access, and avoids block dependencies, making it suitable for
50+
/// high-performance applications, secure disk encryption, and network protocols.
51+
///
52+
/// ****************** NOT implemented modes ******************
53+
///
54+
/// - ECB (Electronic Codebook) – the simplest block cipher mode, where each plaintext block is encrypted independently.
55+
/// It is generally **not recommended for practical use** due to security weaknesses, but can be useful for educational or testing purposes.
56+
///
57+
/// - CBC (Cipher Block Chaining) - block cipher mode where each plaintext block is XORed with the previous ciphertext block
58+
/// before encryption. Suitable for encrypting files, messages, or large datasets,
59+
/// providing confidentiality by introducing dependency between blocks.
60+
///
61+
/// - OFB (Output feedback)- operates as a stream cipher by generating keystream blocks independent of the plaintext,
62+
/// which are then XORed with the plaintext blocks. Well-suited for network communications and streaming applications.
63+
///
64+
/// - CFB (Cipher feedback ) - also a stream cipher mode that encrypts small increments of plaintext,
65+
/// allowing for encryption of data in units smaller than the block size. An error in one ciphertext byte propagates
66+
/// to several subsequent plaintext bytes during decryption. Generally less efficient compared to other modes.
67+
///
68+
/// - XTS (XEX-based Tweaked Codebook mode with ciphertext Stealing) - block cipher mode for encrypting data on storage devices.
69+
/// It allows encryption of data whose length is not a multiple of the block size **without padding** by using ciphertext stealing.
70+
/// Provides high performance and protection against ciphertext manipulation,
71+
/// commonly used for encrypting sectors on hard drives, SSDs, and USB drives.
72+
73+
// TODO(Balldyna): To support multiple AES modes in the future, this class should be refactored.
74+
// Consider the following steps:
75+
// - introduce an enum (`AesMode`) to represent supported block cipher modes
76+
// - add appropriate try-catch blocks for mode-specific behavior
77+
// - rename this class to reflect its extended capability (e.g., 'AES').
78+
79+
class AESctr {
80+
/// Encrypts the given [uint8List] using the specified [aesKey] and [aesIV].
81+
/// The encryption process uses a padded block cipher with PKCS7 padding
82+
/// and AES in CTR mode to ensure compatibility with inputs of any size.
83+
/// Returns an [CipherText] object containing the encrypted bytes.
84+
static CipherText encrypt(Uint8List uint8List, AESKey aesKey, AESIV aesIV) {
85+
PaddedBlockCipher paddedBlockCipher = PaddedBlockCipher(
86+
blockCipher: CTRBlockCipher(
87+
AESEngine(
88+
cipherMode: CipherMode.encryption,
89+
cipherKeyWithIV: CipherKeyWithIV<AESKey>(aesKey, aesIV.uint8List),
90+
),
91+
),
92+
cipherPadding: Pkcs7Padding(),
93+
);
94+
return CipherText(paddedBlockCipher.process(uint8List));
95+
}
96+
97+
/// Decrypts the given [cipherText] data using the specified [aesKey] and [aesIV].
98+
/// The decryption process matches the encryption configuration,
99+
/// using PKCS7 padding removal and AES in CTR mode.
100+
/// Returns the original plaintext as a [Uint8List].
101+
static Uint8List decrypt(CipherText cipherText, AESKey aesKey, AESIV aesIV) {
102+
PaddedBlockCipher paddedBlockCipher = PaddedBlockCipher(
103+
blockCipher: CTRBlockCipher(
104+
AESEngine(
105+
cipherMode: CipherMode.decryption,
106+
cipherKeyWithIV: CipherKeyWithIV<AESKey>(aesKey, aesIV.uint8List),
107+
),
108+
),
109+
cipherPadding: Pkcs7Padding(),
110+
);
111+
return paddedBlockCipher.process(cipherText.uint8List);
112+
}
113+
}

0 commit comments

Comments
 (0)