protect method

SecureMessage protect(
  1. Uint8List plaintext
)

Protects plaintext and returns a SecureMessage ready for wire encoding.

INPUT:

  • plaintext: raw bytes to encrypt (non-empty)

OUTPUT:

  • SecureMessage with fields: version = config.protocolVersion window = floor(epochSeconds / windowSeconds) nonce = 8B nonce ciphertext = AES-256-CBC ciphertext tag = HMAC-SHA256 over ("tag" || u64be(window) || nonce || ciphertext)

Throws:

HINT: Serialize with ApiClient.toWire(message) to obtain headers/body.

Implementation

SecureMessage protect(Uint8List plaintext) {
  if (plaintext.isEmpty) {
    throw InvalidMessageException(
      cause: ArgumentError('plaintext must not be empty.'),
    );
  }

  try {
    // 1) Current window
    final int window = _cfg.currentWindow();

    // 2) Fresh nonce (8 bytes)
    final nonce = _nonceGen.nextNonce();

    // 3) IV from macKey + ("iv"||u64be(window)||nonce)
    final iv = IvDeriver.derive(
      macKey: _keys.macKey,
      window: window,
      nonce: nonce,
    );

    // 4) Encrypt
    final ciphertext = OtpCipher.encrypt(
      encKey: _keys.encKey,
      iv: iv,
      plaintext: plaintext,
    );

    // 5) Tag from macKey + ("tag"||u64be(w)||nonce||ciphertext)
    final tag = TagDeriver.derive(
      macKey: _keys.macKey,
      window: window,
      nonce: nonce,
      ciphertext: ciphertext,
    );

    // 6) Build message
    final msg = SecureMessage.fromParts(
      version: _cfg.protocolVersion,
      window: window,
      nonce: nonce,
      ciphertext: ciphertext,
      tag: tag,
    );

    return msg;
  } catch (e, st) {
    // Wrap unexpected issues in a generic internal error.
    throw InternalCryptoException(cause: e, stackTrace: st);
  }
}