Repository: juliansteenbakker/flutter_secure_storage

Issue #345: UNKNOWN_ERROR on windows for large secrets (>2561 bytes)
Created: 2021-12-03T10:38:10Z
The following error occurs on windows whenever I try to save a secret that's larger than 2561 bytes:
    PlatformException(Exception encountered: UNKNOWN_ERROR, write, null, null)
    
    #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:607:7)
    #1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:156:18)
    <asynchronous suspension>

This error does not appear with a secret that is 2560 bytes or less. This is happening with 5.0.2 on Windows 10 Enterprise.
For reference here's the secret I reproduce the error with:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

This happens when using:
flutterSecureStorage.write('key1', secret);

Duplicate issue #361: Exception has occurred. PlatformException (PlatformException(Exception encountered: UNKNOWN_ERROR, write, null, null))
Created: 2022-02-02T22:45:31Z
i'm getting this error when trying to store a large object on Windows
class Usuario implements ModelBase {
  @override
  String getClassName() {
    return 'Usuario';
  }

  Usuario({
    this.id,
    required this.username,
    required this.password,
  });

  Usuario.fromMap(Map<String, dynamic> map) {
    id = map.containsKey('id') ? map['id'] : id;
    username = map.containsKey('username') ? map['username'] : username;
    password = map.containsKey('password') ? map['password'] : password;
    ativo = map.containsKey('ativo') ? map['ativo'] : ativo;
    idPerfil = map.containsKey('idPerfil') ? map['idPerfil'] : idPerfil;
    idPessoa = map.containsKey('idPessoa') ? map['idPessoa'] : idPessoa;
    dataCadastroAsString = map.containsKey('dataCadastro')
        ? map['dataCadastro']
        : dataCadastroAsString;

    if (map.containsKey('perfil')) {
      if (map['perfil'] is Map<String, dynamic>) {
        perfil = Perfil.fromMap(map['perfil'] as Map<String, dynamic>);
      }
    }
    if (map.containsKey('pessoa')) {
      if (map['pessoa'] is Map<String, dynamic>) {
        pessoa = Pessoa.fromMap(map['pessoa'] as Map<String, dynamic>);
      }
    }
    if (map.containsKey('accessToken')) {
      accessToken = map['accessToken'];
    }
    if (map.containsKey('expiresIn')) {
      expiresIn = DateTime.parse(map['expiresIn']);
    }

    if (map.containsKey('usuarioJubarte')) {
      usuarioJubarte = UsuarioJubarte.fromMap(map['usuarioJubarte']);
    }
  }

  int? id;
  late String username;
  String? password;
  bool ativo = true;
  int? idPerfil;
  int? idPessoa;
  DateTime? dataCadastro;
  String? accessToken;
  DateTime? expiresIn;
  UsuarioJubarte? usuarioJubarte;

  String get dataCadastroAsString {
    final dt = dataCadastro != null
        ? dataCadastro!.toIso8601String().substring(0, 10)
        : '';
    return dt;
  }

  set dataCadastroAsString(dynamic value) {
    if (value is DateTime) {
      dataCadastro = value;
    } else if (value is String) {
      dataCadastro = DateTime.tryParse(value);
    }
  }

  Perfil? _perfil;
  Pessoa? _pessoa;

  Pessoa? get pessoa {
    return _pessoa;
  }

  set pessoa(Pessoa? p) {
    _pessoa = p;
    idPessoa = p?.id;
  }

  Perfil? get perfil {
    return _perfil;
  }

  set perfil(Perfil? p) {
    _perfil = p;
    idPerfil = p?.id;
  }

  static const String ID_KEY = 'id';
  static const String USERNAME_KEY = 'username';
  static const String PASSWORD_KEY = 'password';
  static const String ATIVO_KEY = 'ativo';
  static const String ID_PERFIL_KEY = 'idPerfil';
  static const String ID_PESSOA_KEY = 'idPessoa';
  static const String DATA_CADASTRO_KEY = 'dataCadastro';

  @override
  List<String> fillable = [
    USERNAME_KEY,
    PASSWORD_KEY,
    ATIVO_KEY,
    ID_PERFIL_KEY,
    ID_PESSOA_KEY,
    DATA_CADASTRO_KEY,
  ];

  @override
  Map<String, dynamic> toMap() {
    final map = <String, dynamic>{};
    if (id != null) {
      map['id'] = id;
    }
    map['username'] = username;
    map['password'] = password;
    map['ativo'] = ativo;
    map['idPerfil'] = idPerfil;
    map['idPessoa'] = idPessoa;
    map['dataCadastro'] = dataCadastro?.toString();

    if (perfil != null) {
      map['perfil'] = perfil!.toMap();
    }
    if (pessoa != null) {
      map['pessoa'] = pessoa!.toMap();
    }

    map['accessToken'] = accessToken;
    map['expiresIn'] = expiresIn.toString();

    if (usuarioJubarte != null) {
      map['usuarioJubarte'] = usuarioJubarte!.toMap();
    }

    return map;
  }

  @override
  Map<String, dynamic> toInsert() {
    var map = toMap();
    map.remove('perfil');
    map.remove('pessoa');
    return map;
  }

  @override
  String get tableName => 'usuarios';

  @override
  void validate() {
    if (!CoreUtils.isNotNullOrEmpty(username)) {
      throw Exception('Nome de usuário não pode ser vazio!');
    }

    if (!CoreUtils.isNotNullOrEmpty(password)) {
      throw Exception('Senha não pode ser vazia!');
    }
  }
}

 Future<void> persistUser(Usuario usuario) async {  
    await _storage.write(key: _key, value: jsonEncode(usuario.toMap()));
    return;
  }
class UsuarioJubarte implements ModelBase {
  late int idPessoa;
  late String nome;
  int? idOrganograma;
  String? secretaria;
  String? sigla;
  late String login;
  String? imagem;
  bool isGuarda = false;
  late DateTime dataNascimento;
  String? grupoSanguineo;
  String? fatorRH;
  late String sexo;
  late String cpf;
  late String rg;
  String? nomeMae;
  String? nomePai;
  String? matricula;
  DateTime? dataAdmissao;
  String? nacionalidade;

  late String emailPrincipal;
  String? cargo;
  String? profissao;
  DateTime? dataExoneracao;
  bool? ativo;
  String? vinculo;
  String? funcaoGratificada;
  List<Map<String, dynamic>> modulosJubarte = <Map<String, dynamic>>[];

  UsuarioJubarte({
    required this.idPessoa,
    required this.nome,
    this.idOrganograma,
    this.secretaria,
    this.sigla,
    required this.login,
    this.imagem,
    required this.isGuarda,
    required this.dataNascimento,
    this.grupoSanguineo,
    this.fatorRH,
    required this.sexo,
    required this.cpf,
    required this.rg,
    this.nomeMae,
    this.nomePai,
    this.matricula,
    this.dataAdmissao,
    this.nacionalidade,
    required this.emailPrincipal,
    this.cargo,
    this.profissao,
    this.dataExoneracao,
    this.ativo,
    this.vinculo,
    this.funcaoGratificada,
  });

  UsuarioJubarte.fromMap(Map<String, dynamic> json) {
    idPessoa = json['idPessoa'];
    nome = json['nome'];
    idOrganograma = json['idOrganograma'];
    secretaria = json['secretaria'];
    sigla = json['sigla'];
    login = json['login'];
    imagem = json['imagem'];
    isGuarda = json['isGuarda'];

    dataNascimento = json['dataNascimento'] is DateTime
        ? json['dataNascimento']
        : DateTime.parse(json['dataNascimento']);

    grupoSanguineo = json['grupoSanguineo'];
    fatorRH = json['fatorRH'];
    sexo = json['sexo'];
    cpf = json['cpf'];
    rg = json['rg'];
    nomeMae = json['nomeMae'];
    nomePai = json['nomePai'];
    matricula = json['matricula'];

    dataAdmissao = json['dataAdmissao'] is DateTime
        ? json['dataAdmissao']
        : DateTime.tryParse(json['dataAdmissao']);

    nacionalidade = json['nacionalidade'];
    //novos
    emailPrincipal = json['emailPrincipal'];
    cargo = json['cargo'];
    profissao = json['profissao'];
    dataExoneracao = json['dataExoneracao'] is DateTime
        ? json['dataExoneracao']
        : DateTime.tryParse(json['dataExoneracao'].toString());
    ativo = json['ativo'];
    vinculo = json['vinculo'];
    funcaoGratificada = json['funcaoGratificada'];
    if (json.containsKey('modulosJubarte') && json['modulosJubarte'] != null) {
      var mjs = json['modulosJubarte'] as List;
      mjs.forEach((element) {
        modulosJubarte.add(element as Map<String, dynamic>);
      });
    }
  }

  @override
  Map<String, dynamic> toMap() {
    final data = <String, dynamic>{};
    data['idPessoa'] = idPessoa;
    data['nome'] = nome;
    data['idOrganograma'] = idOrganograma;
    data['secretaria'] = secretaria;
    data['sigla'] = sigla;
    data['login'] = login;
    data['imagem'] = imagem;
    data['isGuarda'] = isGuarda;
    data['dataNascimento'] = dataNascimento.toString();
    data['grupoSanguineo'] = grupoSanguineo;
    data['fatorRH'] = fatorRH;
    data['sexo'] = sexo;
    data['cpf'] = cpf;
    data['rg'] = rg;
    data['nomeMae'] = nomeMae;
    data['nomePai'] = nomePai;
    data['matricula'] = matricula;
    data['dataAdmissao'] = dataAdmissao.toString();
    data['nacionalidade'] = nacionalidade;
    //novos
    data['emailPrincipal'] = emailPrincipal;
    data['cargo'] = cargo;
    data['profissao'] = profissao;
    data['dataExoneracao'] = dataExoneracao.toString();
    data['ativo'] = ativo;
    data['vinculo'] = vinculo;
    data['funcaoGratificada'] = funcaoGratificada;

    if (modulosJubarte.isNotEmpty) {
      data['modulosJubarte'] = modulosJubarte;
    }
    return data;
  }

  @override
  List<String> fillable = [];

  @override
  String getClassName() {
    return 'UsuarioJubarte';
  }

  @override
  String get tableName => throw UnimplementedError();

  @override
  Map<String, dynamic> toInsert() {
    throw UnimplementedError();
  }

  @override
  void validate() {
    throw UnimplementedError();
  }

  String get filiacaoFormatado {
    if (nomeMae == null) {
      return '';
    }
    return '$nomeMae \r\n$nomePai';
  }

  String get info {
    return '''
Identidade Funcional - Fé Pública Válido em todo o Território Nacional Lei Federal Nº 13.022 de 08/08/2014 Integrante Operacional do Sistema Único de Segurança Pública nos Termos do Art. 9º §2º Inc. VII da Lei Federal Nº 13.675/2018 Decreto Municipal Nº 2476/2020\r\n
  ''';
  }

  String get sangueFormatado {
    if (grupoSanguineo == null) {
      return '';
    }
    var f = fatorRH?.trim() == 'Positivo' ? '+' : '-';
    return '$grupoSanguineo$f';
  }

  String get matriculaFormatada {
    if (matricula == null) {
      return '';
    }

    return matricula!;
  }

  String get dataNascimentoFormatado {
    if (grupoSanguineo == null) {
      return '';
    }
    var format = DateFormat('dd/MM/yyyy');
    return format.format(dataNascimento);
  }

  String get dataDeAdmissao {
    if (dataAdmissao == null) {
      return '';
    }
    var format = DateFormat('dd/MM/yyyy');
    return format.format(dataAdmissao!);
  }
}

Closing comment (2022-02-04T00:49:25Z): Duplicate of #345