encryptStream abstract method

Stream<Uint8List> encryptStream(
  1. Stream<List<int>> data,
  2. List<int> counter,
  3. int length
)

Encrypt data with this AesCtrSecretKey using AES in Counter mode, as specified in NIST SP800-38A.

The operation requires a 16 bytes initial counter block counter. The length right most bits of counter are incremented for each encrypted block, the left most 128 - length bits are used as a nonce. The counter value must not be reused for subsequent messages, and the encrypted data must not exceed 2 ^ length * block-size, as this would cause counter blocks to be reused. For detailed discussion of the counter block requirements for AES-CTR, see Appendix B of NIST SP800-38A.

Example

import 'dart:io' show File;
import 'dart:convert' show utf8;
import 'dart:typed_data' show Uint8List;
import 'package:async/async.dart' show collectBytes;
import 'package:webcrypto/webcrypto.dart';

// Generate a new random AES-CTR secret key for AES-256.
final k = await AesCtrSecretKey.generate(256);

// Use a unique counter for each message.
final ctr = Uint8List(16); // always 16 bytes
fillRandomBytes(ctr);

// Length of the counter, the N'th right most bits of ctr are incremented
// for each block, the left most 128 - N bits are used as static nonce.
// Thus, messages must be less than 2^64 * 16 bytes.
final N = 64;

// Encrypt a message from file and write to file
final inputFile = File('message.txt');
final encryptedFile = File('encrypted-message.binary');
final c = await k.encryptStream(
  inputFile.openRead(),
  ctr,
  N,
).pipe(encryptedFile.openWrite());


// Decrypt message (requires the same counter ctr and length N)
final decryptedBytes = await collectBytes(k.decryptStream(
  encryptedFile.openRead(),
  ctr, // same ctr as used for encryption
  N, // same N as used for encryption
));
// decryptedBytes should be equal to contents of inputFile
assert(utf8.decode(decryptedBytes) == inputFile.readAsStringSync());

Remark Firefox does not implement counter rollover for AES-CTR correctly. Picking a sufficiently large length and using a counter that isn't filled with 0xff will likely avoid counter rollovers. See bug 1803105 for details.

Implementation

Stream<Uint8List> encryptStream(
  Stream<List<int>> data,
  List<int> counter,
  int length,
);