encrypt method
Future<SecretBox>
encrypt(
- List<
int> clearText, { - required SecretKey secretKey,
- List<
int> ? nonce, - List<
int> aad = const <int>[], - int keyStreamIndex = 0,
override
Encrypts bytes and returns SecretBox. Authenticates SecretBox with macAlgorithm, decrypts it, and returns the cleartext.
You must give a SecretKey that has the correct length and type.
Optional parameter nonce
(also known as "initialization vector",
"IV", or "salt") is some non-secret unique sequence of bytes.
If you don't define it, the cipher will generate nonce for you.
Parameter aad
can be used to pass Associated Authenticated Data (AAD).
If you pass a non-empty list and the underlying cipher doesn't support
AAD, the method will throw ArgumentError.
Implementation
@override
Future<SecretBox> encrypt(
List<int> clearText, {
required SecretKey secretKey,
List<int>? nonce,
List<int> aad = const <int>[],
int keyStreamIndex = 0,
}) async {
// Check parameters
final secretKeyData = await secretKey.extract();
final actualSecretKeyLength = secretKeyData.bytes.length;
final expectedSecretKeyLength = secretKeyLength;
if (actualSecretKeyLength != expectedSecretKeyLength) {
throw ArgumentError.value(
secretKey,
'secretKey',
'Expected $secretKeyLength bytes, got $actualSecretKeyLength bytes',
);
}
nonce ??= newNonce();
if (nonceLength != 16) {
throw ArgumentError.value(
nonce,
'nonce',
'Expected nonce with 16 bytes, got $nonceLength bytes',
);
}
if (keyStreamIndex < 0) {
throw ArgumentError.value(
keyStreamIndex,
'keyStreamIndex',
);
}
// Expand key
final expandedKey = aesExpandKeyForEncrypting(secretKeyData);
// Construct Uint32List list for the output
final paddingLength = 16 - clearText.length % 16;
final cipherTextBlocks = Uint32List(
(clearText.length + paddingLength) ~/ 16 * 4,
);
final cipherTextBytes = Uint8List.view(cipherTextBlocks.buffer);
// Fill output with input + PKCS7 padding
cipherTextBytes.setRange(0, clearText.length, clearText);
cipherTextBytes.fillRange(
clearText.length,
cipherTextBytes.lengthInBytes,
paddingLength,
);
if (Endian.host == Endian.big) {
final outputByteData = ByteData.view(cipherTextBytes.buffer);
for (var i = 0; i < cipherTextBytes.length; i += 4) {
cipherTextBytes[i] = outputByteData.getUint32(i, Endian.big);
}
}
for (var i = 0; i < cipherTextBlocks.length; i += 4) {
if (i == 0) {
// block ^= nonce
final nonceBytes = nonce;
for (var i = 0; i < nonceBytes.length; i++) {
cipherTextBytes[i] ^= nonceBytes[i];
}
} else {
// block ^= previous_block
for (var j = 0; j < 4; j++) {
cipherTextBlocks[i + j] ^= cipherTextBlocks[i + j - 4];
}
}
// Block function
aesEncryptBlock(
cipherTextBlocks,
i,
cipherTextBlocks,
i,
expandedKey,
);
}
final mac = await macAlgorithm.calculateMac(
cipherTextBytes,
secretKey: secretKey,
nonce: nonce,
aad: aad,
);
return SecretBox(cipherTextBytes, nonce: nonce, mac: mac);
}