create static method

UPdfEncryption? create(
  1. UPdfDict encrypt,
  2. Uint8List firstId,
  3. String password
)

Implementation

static UPdfEncryption? create(UPdfDict encrypt, Uint8List firstId, String password) {
  final Object? filterName = encrypt["Filter"];
  if (filterName is UPdfName && filterName.value != "Standard") return null;
  final int version = (encrypt["V"] as num?)?.toInt() ?? 0;
  final int revision = (encrypt["R"] as num?)?.toInt() ?? 2;
  final int bits = (encrypt["Length"] as num?)?.toInt() ?? 40;
  final int permissionFlags = (encrypt["P"] as num?)?.toInt() ?? -1;
  final bool encryptMetadata = encrypt["EncryptMetadata"] as bool? ?? true;
  final Uint8List owner = encrypt["O"] is UPdfString ? (encrypt["O"]! as UPdfString).bytes : Uint8List(0);
  final Uint8List user = encrypt["U"] is UPdfString ? (encrypt["U"]! as UPdfString).bytes : Uint8List(0);
  final UPdfDict? filters = encrypt["CF"] is UPdfDict ? encrypt["CF"]! as UPdfDict : null;
  final UPdfCryptMethod streamMethod = _methodFor(filters, encrypt["StmF"], version);
  final UPdfCryptMethod stringMethod = _methodFor(filters, encrypt["StrF"], version);
  final List<int> passwordBytes = utf8.encode(password);

  if (revision >= 5) {
    final Uint8List ownerExtra = encrypt["OE"] is UPdfString ? (encrypt["OE"]! as UPdfString).bytes : Uint8List(0);
    final Uint8List userExtra = encrypt["UE"] is UPdfString ? (encrypt["UE"]! as UPdfString).bytes : Uint8List(0);
    final _UPdfV5Result? result = _authenticateV5(passwordBytes, owner, user, ownerExtra, userExtra, revision);
    if (result == null) {
      return UPdfEncryption._(
        revision: revision,
        version: version,
        keyLength: 32,
        streamMethod: streamMethod,
        stringMethod: stringMethod,
        fileKey: Uint8List(0),
        permissionFlags: permissionFlags,
        authenticated: false,
        ownerAuthenticated: false,
        encryptMetadata: encryptMetadata,
      );
    }
    return UPdfEncryption._(
      revision: revision,
      version: version,
      keyLength: 32,
      streamMethod: streamMethod,
      stringMethod: stringMethod,
      fileKey: result.key,
      permissionFlags: permissionFlags,
      authenticated: true,
      ownerAuthenticated: result.owner,
      encryptMetadata: encryptMetadata,
    );
  }

  final int keyLength = version == 1 ? 5 : (bits ~/ 8).clamp(5, 16);
  Uint8List key = _legacyKey(passwordBytes, owner, permissionFlags, firstId, revision, keyLength, encryptMetadata);
  bool authenticated = _checkUser(key, user, firstId, revision);
  bool ownerAuthenticated = false;
  if (!authenticated) {
    final List<int>? recovered = _recoverUserPassword(passwordBytes, owner, revision, keyLength);
    if (recovered != null) {
      final Uint8List ownerKey = _legacyKey(recovered, owner, permissionFlags, firstId, revision, keyLength, encryptMetadata);
      if (_checkUser(ownerKey, user, firstId, revision)) {
        key = ownerKey;
        authenticated = true;
        ownerAuthenticated = true;
      }
    }
  }
  return UPdfEncryption._(
    revision: revision,
    version: version,
    keyLength: keyLength,
    streamMethod: streamMethod,
    stringMethod: stringMethod,
    fileKey: key,
    permissionFlags: permissionFlags,
    authenticated: authenticated,
    ownerAuthenticated: ownerAuthenticated,
    encryptMetadata: encryptMetadata,
  );
}