encryptStream method
Encrypts a Stream of bytes.
Parameter stream
is the encrypted stream of bytes.
Parameter secretKey
is the secret key. You can generate a random secret
key with newSecretKey.
Optional parameter nonce
(also known as "initialization vector",
"IV", or "salt") is some sequence of bytes.
You can generate a nonce with newNonce.
If you don't define it, the cipher will generate a random nonce for you.
The nonce must be unique for each encryption with the same secret key.
It doesn't have to be secret.
You will receive a Message Authentication Code (MAC) using the callback
onMac
after the input stream is closed and before the output stream is
closed. For example, if your macAlgorithm is MacAlgorithm.empty, the
MAC will be Mac.empty.
You can use aad
to pass Associated Authenticated Data (AAD).
If allowUseSameBytes
is true
, the method is allowed (but not required)
to reduce memory allocations by using the same byte array for input and
output. If you use the same byte array for other purposes, this may be
unsafe.
The default implementation reads the input stream into a buffer and, after the input stream has been closed, calls encrypt. Subclasses are encouraged to override the default implementation so that the input stream is processed as it is received.
Example
import 'package:browser_cryptography.dart';
void main() {
final cipher = Chacha20.poly1305Aead();
final secretKey = cipher.newSecretKey();
final nonce = cipher.newNonce();
final file = File('example.txt');
final encryptedFile = File('example.txt.encrypted');
final sink = encryptedFile.openWrite();
try {
final clearTextStream = file.openRead();
final encryptedStream = state.encryptStream(
clearTextStream,
secretKey: secretKey,
nonce: nonce,
);
await encryptedSink.addStream(encryptedStream);
} finally {
sink.close();
}
}
Implementation
Stream<List<int>> encryptStream(
Stream<List<int>> stream, {
required SecretKey secretKey,
required List<int> nonce,
required void Function(Mac mac) onMac,
List<int> aad = const [],
bool allowUseSameBytes = false,
}) async* {
final state = newState();
await state.initialize(
isEncrypting: true,
secretKey: secretKey,
nonce: nonce,
aad: aad,
);
var count = 0;
await for (var chunk in stream) {
final convertedChunk = state.convertChunkSync(
chunk,
possibleBuffer: allowUseSameBytes && chunk is Uint8List ? chunk : null,
);
yield (convertedChunk);
// Pause every now and then to avoid blocking the event loop.
count += chunk.length;
if (count >= _pauseFrequencyInBytes) {
await Future.delayed(_pauseDuration);
count = 0;
}
}
final convertedSuffix = await state.convert(
_emptyUint8List,
expectedMac: null,
);
if (convertedSuffix.isNotEmpty) {
yield (convertedSuffix);
}
onMac(state.mac);
}