fromWire static method

SecureMessage fromWire({
  1. required Map<String, String> headers,
  2. required String body,
})

Parses a SecureMessage from wire headers/body.

headers must contain keys: "version","window","nonce","ciphertext" (all strings). body must be the Base64-encoded tag string.

Throws InvalidMessageException on missing fields, bad integers/base64, nonce length != 8, or empty ciphertext.

HINT: This is a format parser only; MAC verification is done elsewhere.

Implementation

static SecureMessage fromWire({
  required Map<String, String> headers,
  required String body,
}) {
  try {
    // -- Required header fields -------------------------------------------
    final versionStr = headers['version'];
    final windowStr = headers['window'];
    final nonceStr = headers['nonce'];
    final ciphertextStr = headers['ciphertext'];

    if (versionStr == null || windowStr == null || nonceStr == null || ciphertextStr == null) {
      throw ArgumentError('missing required headers v/w/n/c');
    }

    // Parse integers (version, window). Reject non-integers / negatives.
    final version = int.parse(versionStr);
    final window = int.parse(windowStr);
    if (version < 1) {
      throw ArgumentError.value(version, 'version', 'Protocol version must be >= 1.');
    }
    if (window < 0) {
      throw ArgumentError.value(window, 'window', 'Window must be non-negative.');
    }

    // Decode Base64 fields.
    final nonce = Bytes.fromBase64Strict(nonceStr);
    final ciphertext = Bytes.fromBase64Strict(ciphertextStr);
    final tag = Bytes.fromBase64Strict(body);

    // Enforce lengths.
    NonceGenerator.validate(nonce);
    if (ciphertext.isEmpty) {
      throw ArgumentError('ciphertext must not be empty.');
    }
    if (tag.length != 32) {
      throw ArgumentError.value(tag.length, 'tag.length', 'HMAC-SHA256 tag must be 32 bytes.');
    }

    return SecureMessage._internal(
      version: version,
      window: window,
      nonce: nonce,
      ciphertext: ciphertext,
      tag: tag,
    );
  } catch (e, st) {
    throw InvalidMessageException(cause: e, stackTrace: st);
  }
}