aes256CbcDecrypt function

Uint8List aes256CbcDecrypt(
  1. Uint8List key32,
  2. Uint8List iv16,
  3. Uint8List ciphertext
)

AES-256-CBC decryption with PKCS#7 padding validation.

Throws FormatException if the ciphertext length is not a positive multiple of 16, or if the PKCS#7 padding is invalid.

Implementation

Uint8List aes256CbcDecrypt(Uint8List key32, Uint8List iv16, Uint8List ciphertext) {
  _checkKeyIv(key32, iv16);
  if (ciphertext.isEmpty || ciphertext.length % _blockSize != 0) {
    throw FormatException(
      'ciphertext length must be a positive multiple of 16, '
      'got ${ciphertext.length}',
    );
  }
  final roundKeys = _expandKey(key32);

  final out = Uint8List(ciphertext.length);
  final prev = Uint8List.fromList(iv16);
  for (var off = 0; off < ciphertext.length; off += _blockSize) {
    final cblock = Uint8List.sublistView(ciphertext, off, off + _blockSize);
    final dec = _aesDecryptBlock(roundKeys, cblock);
    for (var i = 0; i < _blockSize; i++) {
      out[off + i] = dec[i] ^ prev[i];
    }
    prev.setRange(0, _blockSize, cblock);
  }

  // Validate and strip PKCS#7 padding.
  final padLen = out[out.length - 1];
  if (padLen < 1 || padLen > _blockSize) {
    throw const FormatException('invalid PKCS#7 padding length');
  }
  for (var i = out.length - padLen; i < out.length; i++) {
    if (out[i] != padLen) {
      throw const FormatException('invalid PKCS#7 padding bytes');
    }
  }
  return Uint8List.sublistView(out, 0, out.length - padLen);
}