| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -97,8 +97,23 @@ const _headerFieldsByVersion = { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  HeaderFields.ProtectedStreamKey: [KdbxVersion.V3], | 
					 | 
					 | 
					 | 
					  HeaderFields.ProtectedStreamKey: [KdbxVersion.V3], | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  HeaderFields.StreamStartBytes: [KdbxVersion.V3], | 
					 | 
					 | 
					 | 
					  HeaderFields.StreamStartBytes: [KdbxVersion.V3], | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  HeaderFields.InnerRandomStreamID: [KdbxVersion.V3], | 
					 | 
					 | 
					 | 
					  HeaderFields.InnerRandomStreamID: [KdbxVersion.V3], | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  HeaderFields.KdfParameters: [KdbxVersion.V4], | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  HeaderFields.PublicCustomData: [KdbxVersion.V4], | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}; | 
					 | 
					 | 
					 | 
					}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					bool _isHeaderFieldInVersion(HeaderFields field, KdbxVersion version) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  final f = _headerFieldsByVersion[field]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if (f == null || f.isEmpty) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    return true; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  for (final v in f) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if (v.major == version.major) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      return true; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					enum InnerHeaderFields { | 
					 | 
					 | 
					 | 
					enum InnerHeaderFields { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  EndOfHeader, | 
					 | 
					 | 
					 | 
					  EndOfHeader, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  InnerRandomStreamID, | 
					 | 
					 | 
					 | 
					  InnerRandomStreamID, | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -229,6 +244,10 @@ class KdbxHeader { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // TODO make sure default algorithm is "secure" engouh. Or whether we should | 
					 | 
					 | 
					 | 
					    // TODO make sure default algorithm is "secure" engouh. Or whether we should | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //      use like [SecureRandom] from PointyCastle? | 
					 | 
					 | 
					 | 
					    //      use like [SecureRandom] from PointyCastle? | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    _setHeaderField(HeaderFields.MasterSeed, ByteUtils.randomBytes(32)); | 
					 | 
					 | 
					 | 
					    _setHeaderField(HeaderFields.MasterSeed, ByteUtils.randomBytes(32)); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    fields.remove(HeaderFields.TransformSeed); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    fields.remove(HeaderFields.StreamStartBytes); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    fields.remove(HeaderFields.ProtectedStreamKey); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    fields.remove(HeaderFields.EncryptionIV); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (version.major == KdbxVersion.V3.major) { | 
					 | 
					 | 
					 | 
					    if (version.major == KdbxVersion.V3.major) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      _setHeaderField(HeaderFields.TransformSeed, ByteUtils.randomBytes(32)); | 
					 | 
					 | 
					 | 
					      _setHeaderField(HeaderFields.TransformSeed, ByteUtils.randomBytes(32)); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      _setHeaderField(HeaderFields.StreamStartBytes, ByteUtils.randomBytes(32)); | 
					 | 
					 | 
					 | 
					      _setHeaderField(HeaderFields.StreamStartBytes, ByteUtils.randomBytes(32)); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -264,6 +283,9 @@ class KdbxHeader { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    writer.writeUint16(version.major); | 
					 | 
					 | 
					 | 
					    writer.writeUint16(version.major); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    for (final field | 
					 | 
					 | 
					 | 
					    for (final field | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        in HeaderFields.values.where((f) => f != HeaderFields.EndOfHeader)) { | 
					 | 
					 | 
					 | 
					        in HeaderFields.values.where((f) => f != HeaderFields.EndOfHeader)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (!_isHeaderFieldInVersion(field, version) && fields[field] != null) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        _logger.warning('Did not expect header field $field in $version'); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      _writeField(writer, field); | 
					 | 
					 | 
					 | 
					      _writeField(writer, field); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    fields[HeaderFields.EndOfHeader] = | 
					 | 
					 | 
					 | 
					    fields[HeaderFields.EndOfHeader] = | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -338,9 +360,9 @@ class KdbxHeader { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        HeaderFields.CompressionFlags: | 
					 | 
					 | 
					 | 
					        HeaderFields.CompressionFlags: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            WriterHelper.singleUint32Bytes(Compression.gzip.id), | 
					 | 
					 | 
					 | 
					            WriterHelper.singleUint32Bytes(Compression.gzip.id), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        HeaderFields.KdfParameters: _createKdfDefaultParameters().write(), | 
					 | 
					 | 
					 | 
					        HeaderFields.KdfParameters: _createKdfDefaultParameters().write(), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        HeaderFields.InnerRandomStreamID: WriterHelper.singleUint32Bytes( | 
					 | 
					 | 
					 | 
					//        HeaderFields.InnerRandomStreamID: WriterHelper.singleUint32Bytes( | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ProtectedValueEncryption.values | 
					 | 
					 | 
					 | 
					//            ProtectedValueEncryption.values | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                .indexOf(ProtectedValueEncryption.chaCha20)), | 
					 | 
					 | 
					 | 
					//                .indexOf(ProtectedValueEncryption.chaCha20)), | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }); | 
					 | 
					 | 
					 | 
					      }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  static Map<HeaderFields, HeaderField> _headerFields( | 
					 | 
					 | 
					 | 
					  static Map<HeaderFields, HeaderField> _headerFields( | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -483,8 +505,10 @@ class KdbxHeader { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      _logger.fine('Creating kdf parameters.'); | 
					 | 
					 | 
					 | 
					      _logger.fine('Creating kdf parameters.'); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      writeKdfParameters(_createKdfDefaultParameters()); | 
					 | 
					 | 
					 | 
					      writeKdfParameters(_createKdfDefaultParameters()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    _setHeaderField( | 
					 | 
					 | 
					 | 
					    fields.remove(HeaderFields.TransformRounds); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        HeaderFields.InnerRandomStreamID, | 
					 | 
					 | 
					 | 
					    fields.remove(HeaderFields.InnerRandomStreamID); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    _setInnerHeaderField( | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        InnerHeaderFields.InnerRandomStreamID, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        WriterHelper.singleUint32Bytes(ProtectedValueEncryption.values | 
					 | 
					 | 
					 | 
					        WriterHelper.singleUint32Bytes(ProtectedValueEncryption.values | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .indexOf(ProtectedValueEncryption.chaCha20))); | 
					 | 
					 | 
					 | 
					            .indexOf(ProtectedValueEncryption.chaCha20))); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |