calculateMac method

  1. @override
Future<Mac> calculateMac(
  1. List<int> bytes, {
  2. required SecretKey secretKey,
  3. List<int> nonce = const <int>[],
  4. List<int> aad = const <int>[],
})
override

Calculates message authentication code.

The parameter secretKey must be non-empty.

The parameter nonce is optional and rarely required by MAC algorithms. The default value is const <int>[].

The parameter aad is Associated Authenticated Data (AAD). It can be empty. If it's non-empty and the algorithm does not support AAD, the the method throws ArgumentError.

Implementation

@override
Future<Mac> calculateMac(
  List<int> bytes, {
  required SecretKey secretKey,
  List<int> nonce = const <int>[],
  List<int> aad = const <int>[],
}) async {
  final secretKeyForPoly1305 = await _poly1305SecretKeyFromChacha20(
    secretKey: secretKey,
    nonce: nonce,
  );
  final sink = await _poly1305.newMacSink(
    secretKey: secretKeyForPoly1305,
  );

  var length = 0;

  late ByteData tmpByteData;
  late Uint8List tmpUint8List;
  if (_useStaticBuffer) {
    tmpByteData = _tmpByteData;
    tmpUint8List = _tmpUint8List;
  } else {
    tmpByteData = ByteData(16);
    tmpUint8List = Uint8List.view(tmpByteData.buffer);
  }
  tmpByteData.setUint32(0, 0);
  tmpByteData.setUint32(4, 0);
  tmpByteData.setUint32(8, 0);
  tmpByteData.setUint32(12, 0);

  // Add Additional Authenticated Data (AAD)
  final aadLength = aad.length;
  if (aadLength != 0) {
    sink.add(aad);
    length += aad.length;

    final rem = length % 16;
    if (rem != 0) {
      // Add padding
      final paddingLength = 16 - rem;
      sink.add(tmpUint8List.sublist(0, paddingLength));
      length += paddingLength;
    }
  }

  // Add cipherText
  sink.add(bytes);
  length += bytes.length;
  final rem = length % 16;
  if (rem != 0) {
    // Add padding
    final paddingLength = 16 - rem;
    sink.add(tmpUint8List.sublist(0, paddingLength));
    length += paddingLength;
  }

  // Add 16-byte footer.
  // We can't use setUint64() because it's not supported in the browsers.
  tmpByteData.setUint32(
    0,
    uint32mask & aadLength,
    Endian.little,
  );
  tmpByteData.setUint32(
    4,
    aadLength ~/ (uint32mask + 1),
    Endian.little,
  );
  tmpByteData.setUint32(
    8,
    uint32mask & bytes.length,
    Endian.little,
  );
  tmpByteData.setUint32(
    12,
    bytes.length ~/ (uint32mask + 1),
    Endian.little,
  );
  sink.add(tmpUint8List);

  // Reset the static buffer.
  tmpByteData.setUint32(0, 0);
  tmpByteData.setUint32(4, 0);
  tmpByteData.setUint32(8, 0);
  tmpByteData.setUint32(12, 0);

  // Return MAC
  sink.close();

  return sink.mac();
}