@ -6,6 +6,7 @@ import 'dart:typed_data';
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:archive/archive.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:argon2_ffi_base/argon2_ffi_base.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:collection/collection.dart '  show  IterableExtension ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:convert/convert.dart '  as  convert ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:crypto/crypto.dart '  as  crypto ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:kdbx/kdbx.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:kdbx/src/crypto/key_encrypter_kdf.dart ' ;  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -13,14 +14,11 @@ import 'package:kdbx/src/crypto/protected_salt_generator.dart';
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:kdbx/src/internal/consts.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:kdbx/src/internal/crypto_utils.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:kdbx/src/internal/extension_utils.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:kdbx/src/internal/pointycastle_argon2.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:kdbx/src/kdbx_deleted_object.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:kdbx/src/kdbx_entry.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:kdbx/src/kdbx_group.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:kdbx/src/kdbx_header.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:kdbx/src/kdbx_xml.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:kdbx/src/utils/byte_utils.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:kdbx/src/utils/sequence.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:logging/logging.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:meta/meta.dart ' ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  ' package:pointycastle/export.dart ' ;  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -30,6 +28,40 @@ import 'package:xml/xml.dart' as xml;
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					final  _logger  =  Logger ( ' kdbx.format ' ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					abstract  class  Credentials  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  factory  Credentials ( ProtectedValue  password )  = >   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      Credentials . composite ( password ,  null ) ;  / / PasswordCredentials ( password ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  factory  Credentials . composite ( ProtectedValue ?  password ,  Uint8List ?  keyFile )  = >   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      KeyFileComposite (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        password:  password ? . let ( ( that )  = >  PasswordCredentials ( that ) ) ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        keyFile:  keyFile  = =  null  ?  null  :  KeyFileCredentials ( keyFile ) ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  factory  Credentials . fromHash ( Uint8List  hash )  = >  HashCredentials ( hash ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  Uint8List  getHash ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					class  KeyFileComposite  implements  Credentials  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  KeyFileComposite ( { required  this . password ,  required  this . keyFile } ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  PasswordCredentials ?  password ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  KeyFileCredentials ?  keyFile ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  @ override   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  Uint8List  getHash ( )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  buffer  =  [ . . . ? password ? . getBinary ( ) ,  . . . ? keyFile ? . getBinary ( ) ] ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  crypto . sha256 . convert ( buffer ) . bytes  as  Uint8List ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					/ /     final  output  =  convert . AccumulatorSink < crypto . Digest > ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					/ /     final  input  =  crypto . sha256 . startChunkedConversion ( output ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					/ / / /     input . add ( password . getHash ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					/ /     input . add ( buffer ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					/ /     input . close ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					/ /     return  output . events . single . bytes  as  Uint8List ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					/ / /  Context  used  during  reading  and  writing .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					class  KdbxReadWriteContext  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  KdbxReadWriteContext ( {   
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -89,11 +121,11 @@ class KdbxReadWriteContext {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  / / /  finds  the  ID  of  the  given  binary .   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  / / /  if  it  can ' t be found, [KdbxCorruptedFileException] is thrown.   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  int  findBinaryId ( KdbxBinary  binary )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    assert ( ! binary . isInline ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    assert ( ! binary . isInline ! ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  id  =  _binaries . indexOf ( binary ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( id  <  0 )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      throw  KdbxCorruptedFileException ( ' Unable to find binary. '   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					          '  ( ${ binary . value . length } , ${ binary . isInline } ) ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					          '  ( ${ binary . value ! . length } , ${ binary . isInline } ) ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  id ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -106,12 +138,76 @@ class KdbxReadWriteContext {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					          ' Tried to remove binary which is not in this file. ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  void  addDeletedObject ( KdbxUuid  uuid ,  [ DateTime ?  now ] )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    _deletedObjects . add ( KdbxDeletedObject . create ( this ,  uuid ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					abstract  class  CredentialsPart  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  Uint8List  getBinary ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					class  KeyFileCredentials  implements  CredentialsPart  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  factory  KeyFileCredentials ( Uint8List  keyFileContents )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    try  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  keyFileAsString  =  utf8 . decode ( keyFileContents ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      if  ( _hexValuePattern . hasMatch ( keyFileAsString ) )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        return  KeyFileCredentials . _ ( ProtectedValue . fromBinary (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            convert . hex . decode ( keyFileAsString )  as  Uint8List ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  xmlContent  =  xml . XmlDocument . parse ( keyFileAsString ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  metaVersion  =   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					          xmlContent . findAllElements ( ' Version ' ) . singleOrNull ? . text ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  key  =  xmlContent . findAllElements ( ' Key ' ) . single ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  dataString  =  key . findElements ( ' Data ' ) . single ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  encoded  =  dataString . text . replaceAll ( RegExp ( r'\s' ) ,  ' ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      Uint8List  dataBytes ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      if  ( metaVersion  ! =  null  & &  metaVersion . startsWith ( ' 2. ' ) )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        dataBytes  =  convert . hex . decode ( encoded )  as  Uint8List ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      }  else  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        dataBytes  =  base64 . decode ( encoded ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      _logger . finer ( ' Decoded base64 of keyfile. ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      return  KeyFileCredentials . _ ( ProtectedValue . fromBinary ( dataBytes ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }  catch  ( e ,  stackTrace )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      _logger . warning (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					          ' Unable to parse key file as hex or XML, use as is. ' ,  e ,  stackTrace ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  bytes  =  crypto . sha256 . convert ( keyFileContents ) . bytes  as  Uint8List ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      return  KeyFileCredentials . _ ( ProtectedValue . fromBinary ( bytes ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  KeyFileCredentials . _ ( this . _keyFileValue ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  static  final  RegExp  _hexValuePattern  =   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      RegExp ( r'^[a-f\d]{64}' ,  caseSensitive:  false ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  final  ProtectedValue  _keyFileValue ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  @ override   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  Uint8List  getBinary ( )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  _keyFileValue . binaryValue ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					/ /     return  crypto . sha256 . convert ( _keyFileValue . binaryValue ) . bytes  as  Uint8List ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					class  PasswordCredentials  implements  CredentialsPart  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  PasswordCredentials ( this . _password ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  final  ProtectedValue  _password ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  @ override   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  Uint8List  getBinary ( )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  _password . hash ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					class  HashCredentials  implements  Credentials  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  HashCredentials ( this . hash ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  final  Uint8List  hash ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  @ override   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  Uint8List  getHash ( )  = >  hash ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					class  KdbxBody  extends  KdbxNode  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  KdbxBody . create ( this . meta ,  this . rootGroup )  :  super . create ( ' KeePassFile ' )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    node . children . add ( meta . node ) ;   
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -169,14 +265,14 @@ class KdbxBody extends KdbxNode {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      KdbxFile  kdbxFile ,  Uint8List ?  compressedBytes )  async  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  byteWriter  =  WriterHelper ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    byteWriter . writeBytes (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        kdbxFile . header . fields [ HeaderFields . StreamStartBytes ] ! . bytes ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        kdbxFile . header . fields [ HeaderFields . StreamStartBytes ] ! . bytes ! ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    HashedBlockReader . writeBlocks ( ReaderHelper ( compressedBytes ) ,  byteWriter ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  bytes  =  byteWriter . output . toBytes ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  masterKey  =  await  KdbxFormat . _generateMasterKeyV3 (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        kdbxFile . header ,  kdbxFile . credentials ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  encrypted  =  KdbxFormat . _encryptDataAes ( masterKey ,  bytes ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        kdbxFile . header . fields [ HeaderFields . EncryptionIV ] ! . bytes ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        kdbxFile . header . fields [ HeaderFields . EncryptionIV ] ! . bytes ! ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  encrypted ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -230,7 +326,7 @@ class KdbxBody extends KdbxNode {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      if  ( ctx . findBinaryByValue ( binary )  = =  null )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ctx . addBinary ( binary ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        mergeContext . trackChange ( this ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            debug:  ' adding new binary  ${ binary . value . length } ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            debug:  ' adding new binary  ${ binary . value ! . length } ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    meta . merge ( other . meta ) ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -238,25 +334,7 @@ class KdbxBody extends KdbxNode {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    / /  remove  deleted  objects   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    for  ( final  incomingDelete  in  incomingDeleted . values )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  object  =  mergeContext . objectIndex [ incomingDelete . uuid ] ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      if  ( object  = =  null )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        mergeContext . trackWarning (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            ' Incoming deleted object not found locally  ${ incomingDelete . uuid } ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        continue ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  parent  =  object . parent ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      if  ( parent  = =  null )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        mergeContext . trackWarning ( ' Unable to delete object  $ object  -  '   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            ' already deleted? ( ${ incomingDelete . uuid } ) ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        continue ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      if  ( object  is  KdbxGroup )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        parent . internalRemoveGroup ( object ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      }  else  if  ( object  is  KdbxEntry )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        parent . internalRemoveEntry ( object ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      }  else  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        throw  StateError ( ' Invalid object type  $ object ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  object  =  mergeContext . objectIndex ! [ incomingDelete . uuid ! ] ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      mergeContext . trackChange ( object ,  debug:  ' was deleted. ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -265,11 +343,11 @@ class KdbxBody extends KdbxNode {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    _logger . info ( ' Finished merging: \n ${ mergeContext . debugChanges ( ) } ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  incomingObjects  =  other . _createObjectIndex ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    _logger . info ( ' Merged:  ${ mergeContext . merged }  vs.  '   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ' (local objects:  ${ mergeContext . objectIndex . length } ,  '   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ' (local objects:  ${ mergeContext . objectIndex ! . length } ,  '   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ' incoming objects:  ${ incomingObjects . length } ) ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    / /  sanity  checks   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( mergeContext . merged . keys . length  ! =  mergeContext . objectIndex . length )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( mergeContext . merged . keys . length  ! =  mergeContext . objectIndex ! . length )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      / /  TODO  figure  out  what  went  wrong .   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  mergeContext ;   
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -347,28 +425,12 @@ class MergeChange {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					class  MergeWarning  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  MergeWarning ( this . debug ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  final  String  debug ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  @ override   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  String  toString ( )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  debug ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					class  MergeContext  implements  OverwriteContext  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  MergeContext ( { required  this . objectIndex ,  required   this . deletedObjects } ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  final  Map < KdbxUuid ,  KdbxObject >  objectIndex ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  final  Map < KdbxUuid ? ,  KdbxDeletedObject >  deletedObjects ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  MergeContext ( { this . objectIndex ,  this . deletedObjects } ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  final  Map < KdbxUuid ,  KdbxObject > ?  objectIndex ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  final  Map < KdbxUuid ? ,  KdbxDeletedObject > ?  deletedObjects ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  final  Map < KdbxUuid ,  KdbxObject >  merged  =  { } ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  final  List < MergeChange >  changes  =  [ ] ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  final  List < MergeWarning >  warnings  =  [ ] ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  int  totalChanges ( )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  deletedObjects . length  +  changes . length ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  void  markAsMerged ( KdbxObject  object )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( merged . containsKey ( object . uuid ) )  {   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -387,11 +449,6 @@ class MergeContext implements OverwriteContext {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  void  trackWarning ( String  warning )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    _logger . warning ( warning ,  StackTrace . current ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    warnings . add ( MergeWarning ( warning ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  String  debugChanges ( )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  group  =   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        changes . groupBy ( ( element )  = >  element . object ,  valueTransform:  ( x )  = >  x ) ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -402,17 +459,6 @@ class MergeContext implements OverwriteContext {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            ] . join ( ' \n      ' ) )   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        . join ( ' \n ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  String  debugSummary ( )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  ' Changes:  ${ changes . length } ,  '   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ' Deleted:  ${ deletedObjects . length } ,  '   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ' Warnings:  ${ warnings . isEmpty  ?  ' None '  :  warnings . join ( ' ,  ' ) } ' ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  @ override   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  String  toString ( )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  ' $ runtimeType { ${ debugSummary ( ) } } ' ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					class  _KeysV4  {  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -423,13 +469,9 @@ class _KeysV4 {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					class  KdbxFormat  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  KdbxFormat ( [ Argon2 ?  argon2 ] )   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      :  assert ( kdbxKeyCommonAssertConsistency ( ) ) ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        argon2  =  argon2  = =  null  | |  ! argon2 . isImplemented   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            ?  const  PointyCastleArgon2 ( )   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            :  argon2 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  KdbxFormat ( [ this . argon2 ] )  :  assert ( kdbxKeyCommonAssertConsistency ( ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  final  Argon2  argon2 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  final  Argon2 ?  argon2 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  static  bool  dartWebWorkaround  =  false ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  / / /  Creates  a  new ,  empty  [ KdbxFile ]  with  default  settings .   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -440,7 +482,7 @@ class KdbxFormat {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    String ?  generator ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    KdbxHeader ?  header ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  } )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    header  ? ? =  KdbxHeader . createV4 ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    header  ? ? =  argon2  = =  null  ?  KdbxHeader . createV3 ( )  :  KdbxHeader . createV4 ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  ctx  =  KdbxReadWriteContext ( binaries:  [ ] ,  header:  header ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  meta  =  KdbxMeta . create (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      databaseName:  name ,   
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -474,20 +516,10 @@ class KdbxFormat {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  / / /  Saves  the  given  file .   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  Future < T >  save < T > ( KdbxFile  file ,  FileSaveCallback < T >  saveBytes )  async  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  Future < Uint8List >  save ( KdbxFile  file )  async  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    _logger . finer ( ' Saving  ${ file . body . rootGroup . uuid }   '   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ' (locked:  ${ file . saveLock . locked } ) ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  file . saveLock . synchronized ( ( )  async  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  savedAt  =  TimeSequence . now ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  bytes  =  await  _saveSynchronized ( file ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      _logger . fine ( ' Saving bytes. ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  ret  =  await  saveBytes ( bytes ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      _logger . fine ( ' Saved bytes. ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      file . onSaved ( savedAt ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      return  ret ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    } ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  file . saveLock . synchronized ( ( )  = >  _saveSynchronized ( file ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  Future < Uint8List >  _saveSynchronized ( KdbxFile  file )  async  {   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -505,7 +537,7 @@ class KdbxFormat {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      throw  UnsupportedError ( ' Unsupported version  ${ header . version } ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }  else  if  ( file . header . version  <  KdbxVersion . V4 )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  streamKey  =   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					          file . header . fields [ HeaderFields . ProtectedStreamKey ] ! . bytes ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					          file . header . fields [ HeaderFields . ProtectedStreamKey ] ! . bytes ! ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      final  gen  =  ProtectedSaltGenerator ( streamKey ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      body . meta . headerHash . set ( headerHash . buffer ) ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -521,6 +553,7 @@ class KdbxFormat {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }  else  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      throw  UnsupportedError ( ' Unsupported version  ${ header . version } ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    file . onSaved ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  output . toBytes ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -670,7 +703,7 @@ class KdbxFormat {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  Uint8List  transformContentV4ChaCha20 (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      KdbxHeader  header ,  Uint8List  encrypted ,  Uint8List  cipherKey )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  encryptionIv  =  header . fields [ HeaderFields . EncryptionIV ] ! . bytes ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  encryptionIv  =  header . fields [ HeaderFields . EncryptionIV ] ! . bytes ! ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  chaCha  =  ChaCha7539Engine ( )   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      . . init ( true ,  ParametersWithIV ( KeyParameter ( cipherKey ) ,  encryptionIv ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  chaCha . process ( encrypted ) ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -693,7 +726,7 @@ class KdbxFormat {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  Future < _KeysV4 >  _computeKeysV4 (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      KdbxHeader  header ,  Credentials  credentials )  async  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  masterSeed  =  header . fields [ HeaderFields . MasterSeed ] ! . bytes ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  masterSeed  =  header . fields [ HeaderFields . MasterSeed ] ! . bytes ! ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  kdfParameters  =  header . readKdfParameters ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( masterSeed . length  ! =  32 )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      throw  const  FormatException ( ' Master seed must be 32 bytes. ' ) ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -701,7 +734,7 @@ class KdbxFormat {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  credentialHash  =  credentials . getHash ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  key  =   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        await  KeyEncrypterKdf ( argon2 ) . encrypt ( credentialHash ,  kdfParameters ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        await  KeyEncrypterKdf ( argon2 ! ) . encrypt ( credentialHash ,  kdfParameters ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					/ /     final  keyWithSeed  =  Uint8List ( 65 ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					/ /     keyWithSeed . replaceRange ( 0 ,  masterSeed . length ,  masterSeed ) ;  
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -790,16 +823,14 @@ class KdbxFormat {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  Uint8List  _decryptContent (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      KdbxHeader  header ,  Uint8List  masterKey ,  Uint8List  encryptedPayload )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  encryptionIv  =  header . fields [ HeaderFields . EncryptionIV ] ! . bytes ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  decryptCipher  =  CBCBlockCipher ( AESEngine ( ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  encryptionIv  =  header . fields [ HeaderFields . EncryptionIV ] ! . bytes ! ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  decryptCipher  =  CBCBlockCipher ( AESFast Engine ( ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    decryptCipher . init (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        false ,  ParametersWithIV ( KeyParameter ( masterKey ) ,  encryptionIv ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    _logger . finer ( ' decrypting  ${ encryptedPayload . length }  with block size  '   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ' ${ decryptCipher . blockSize } ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  paddedDecrypted  =   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        AesHelper . processBlocks ( decryptCipher ,  encryptedPayload ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  streamStart  =  header . fields [ HeaderFields . StreamStartBytes ] ! . bytes ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  streamStart  =  header . fields [ HeaderFields . StreamStartBytes ] ! . bytes ! ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( paddedDecrypted . lengthInBytes  <  streamStart . lengthInBytes )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      _logger . warning (   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -821,9 +852,9 @@ class KdbxFormat {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  Uint8List  _decryptContentV4 (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      KdbxHeader  header ,  Uint8List  cipherKey ,  Uint8List  encryptedPayload )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  encryptionIv  =  header . fields [ HeaderFields . EncryptionIV ] ! . bytes ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  encryptionIv  =  header . fields [ HeaderFields . EncryptionIV ] ! . bytes ! ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  decryptCipher  =  CBCBlockCipher ( AESEngine ( ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  decryptCipher  =  CBCBlockCipher ( AESFast Engine ( ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    decryptCipher . init (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        false ,  ParametersWithIV ( KeyParameter ( cipherKey ) ,  encryptionIv ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  paddedDecrypted  =   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -836,8 +867,8 @@ class KdbxFormat {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  / / /  TODO  combine  this  with  [ _decryptContentV4 ]  ( or  [ _encryptDataAes ] ? )   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  Uint8List  _encryptContentV4Aes (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      KdbxHeader  header ,  Uint8List  cipherKey ,  Uint8List  bytes )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  encryptionIv  =  header . fields [ HeaderFields . EncryptionIV ] ! . bytes ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  encryptCypher  =  CBCBlockCipher ( AESEngine ( ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  encryptionIv  =  header . fields [ HeaderFields . EncryptionIV ] ! . bytes ! ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  encryptCypher  =  CBCBlockCipher ( AESFast Engine ( ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    encryptCypher . init (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        true ,  ParametersWithIV ( KeyParameter ( cipherKey ) ,  encryptionIv ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  paddedBytes  =  AesHelper . pad ( bytes ,  encryptCypher . blockSize ) ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -848,7 +879,7 @@ class KdbxFormat {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      KdbxHeader  header ,  Credentials  credentials )  async  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  rounds  =  header . v3KdfTransformRounds ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  seed  =  header . fields [ HeaderFields . TransformSeed ] ! . bytes ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  masterSeed  =  header . fields [ HeaderFields . MasterSeed ] ! . bytes ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  masterSeed  =  header . fields [ HeaderFields . MasterSeed ] ! . bytes ! ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    _logger . finer (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ' Rounds:  $ rounds  ( ${ ByteUtils . toHexList ( header . fields [ HeaderFields . TransformRounds ] ! . bytes ) } ) ' ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  transformedKey  =  await  KeyEncrypterKdf . encryptAesAsync (   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -862,7 +893,7 @@ class KdbxFormat {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  static  Uint8List  _encryptDataAes (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      Uint8List  masterKey ,  Uint8List  payload ,  Uint8List  encryptionIv )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  encryptCipher  =  CBCBlockCipher ( AESEngine ( ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    final  encryptCipher  =  CBCBlockCipher ( AESFast Engine ( ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    encryptCipher . init (   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        true ,  ParametersWithIV ( KeyParameter ( masterKey ) ,  encryptionIv ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  AesHelper . processBlocks (