public void SetUpContainer( )
        {
            TestInjection.TestContainer( ).InjectProperties( this );

            PasswordRepository.PasswordData = new InMemoryPasswordData( );

            var masterPasswordId = Guid.NewGuid( );
            _abc = new PasswordDigestDocumentBuilder
                       {
                           Digest = PasswordDigest( "abc", "123", 1, PasswordGenerators.LegacyFull ),
                           MasterPasswordId = masterPasswordId
                       };

            _def = new PasswordDigestDocumentBuilder
                       {
                           Digest = PasswordDigest( "def", "123", 2, PasswordGenerators.LegacyAlphaNumeric ),
                           MasterPasswordId = masterPasswordId
                       };

            _ghi = new PasswordDigestDocumentBuilder
                       {
                           Digest = PasswordDigest( "ghi", "123", 1, PasswordGenerators.LegacyAlphaNumeric ),
                           MasterPasswordId = masterPasswordId
                       };

            PasswordRepository.SavePassword( _abc );
            PasswordRepository.SavePassword( _def );
            PasswordRepository.SavePassword( _ghi );

            PasswordList.UpdateList( );
            PasswordList.OpenNewEditor( PasswordList.VisibleItems[ 0 ] );
            PasswordList.OpenNewEditor( PasswordList.VisibleItems[ 1 ] );
            PasswordList.OpenNewEditor( PasswordList.VisibleItems[ 2 ] );
        }
 public PasswordListEntryViewModel( PasswordDigestDocument password, IGuidToColorConverter guidColorConverter,
                                    IFuzzyDateFormatter fuzzyDateFormatter )
 {
     _password = password;
     _guidColorConverter = guidColorConverter;
     _fuzzyDateFormatter = fuzzyDateFormatter;
 }
        public bool DeletePassword( PasswordDigestDocument password, DateTime deletedOn )
        {
            if ( password == null )
                throw new ArgumentNullException( "password" );

            return UpdatePassword( password, password.Delete( deletedOn ) );
        }
        public void SetUpModel( )
        {
            _engine = new PasswordDerivationEngine( PasswordGenerators.Generators );
            _passwordRepository = new PasswordRepository( new InMemoryPasswordData( ) );

            var digest = _engine.Derive( new PasswordRequest( "abij", "1234".ToSecureString( ), 3, PasswordGenerators.LegacyFull ) );

            _original = new PasswordDigestDocumentBuilder
                            {
                                Digest = digest.Digest,
                                CreatedOn = new DateTime( 2011, 11, 1 ),
                                ModifiedOn = new DateTime( 2011, 11, 3 ),
                                MasterPasswordId = Guid.NewGuid( ),
                                Note = "AB IJ"
                            };

            _passwordRepository.SavePassword( _original );

            _timeProvider = new StubTimeProvider { Now = new DateTime( 2011, 11, 16 ) };

            IMasterPasswordMatcher masterPasswordMatcher = new MasterPasswordMatcher( _engine, _passwordRepository );

            _model = new PasswordEditorModel( _passwordRepository, _engine, masterPasswordMatcher, _timeProvider,
                                              new BaselinePasswordDocument( _original ) );
        }
        public void FindMasterPasswordInStoreWhenDigestMatches( )
        {
            // Setup
            SecureString masterPassword = "******".ToSecureString( );

            IDerivedPassword match =
                _passwordDerivationEngine.Derive( new PasswordRequest( "key1", masterPassword, 10, PasswordGenerators.LegacyFull ) );

            PasswordDigestDocument matchingDocument =
                new PasswordDigestDocument( match.Digest, _masterPasswordId, new DateTime( 2011, 11, 1 ), new DateTime( 2011, 11, 1 ), string.Empty );

            _passwordRepository.SavePassword( matchingDocument );

            IDerivedPassword nonMatch =
                _passwordDerivationEngine.Derive( new PasswordRequest( "key2", "tata".ToSecureString( ), 1, PasswordGenerators.LegacyAlphaNumeric ) );

            PasswordDigestDocument nonMatchingDocument =
                new PasswordDigestDocument( nonMatch.Digest, Guid.NewGuid( ), new DateTime( 2011, 11, 1 ), new DateTime( 2011, 11, 1 ), string.Empty );

            _passwordRepository.SavePassword( nonMatchingDocument );

            // Exercise
            Guid? guid = _masterPasswordMatcher.IdentifyMasterPassword( masterPassword );
            // Verify
            Assert.That( guid.HasValue, Is.True );
            Assert.That( guid, Is.EqualTo( _masterPasswordId ) );
        }
        private bool MasterPasswordMatches( SecureString masterPassword, PasswordDigestDocument password )
        {
            PasswordRequest testRequest =
                new PasswordRequest( password.Key, masterPassword, password.Iteration, password.PasswordGenerator );
            var testDigest = _passwordDerivationEngine.Derive( testRequest ).Digest;

            return testDigest.Equals( password.Digest );
        }
        private void OpenNewEditorInternal( PasswordDigestDocument passwordDocument )
        {
            UpdateList( );

            PasswordEditorViewModel editor = passwordDocument == null
                                                 ? _editorFactory.NewPasswordEditor( )
                                                 : _editorFactory.PasswordEditorFor( passwordDocument );
            editor.CloseRequested += EditorRequestedClose;
            editor.StoreModified += StoreModified;

            Editors.Add( editor );

            CloseEditors( e => e == _forcedEditor && e.IsPristine );
        }
 private PasswordDigestDocument ClonePassword( PasswordDigestDocument source )
 {
     return new PasswordDigestDocumentBuilder
                {
                    Digest = new PasswordDigest( source.Digest.Key,
                                                 source.Digest.Hash.Clone( ) as byte[ ],
                                                 source.Digest.Iteration,
                                                 source.Digest.PasswordGenerator ),
                    MasterPasswordId = source.MasterPasswordId,
                    CreatedOn = source.CreatedOn,
                    ModifiedOn = source.ModifiedOn,
                    Note = source.Note
                };
 }
        public bool SavePassword( PasswordDigestDocument password )
        {
            if ( password == null )
                throw new ArgumentNullException( "password" );

            if ( password.IsDeleted )
                throw new ArgumentException( "A new password must have non-empty hash.", "password" );

            Load( );

            var mergedPasswords = Merge( new[ ] { password }, false );

            Save( );
            return mergedPasswords.Count( ) > 0;
        }
        public void CannotFindMasterPasswordInStoreWhenNoDigestMatches( )
        {
            // Setup
            IDerivedPassword nonMatch =
                _passwordDerivationEngine.Derive( new PasswordRequest( "key2", "tata".ToSecureString( ), 1, PasswordGenerators.LegacyAlphaNumeric ) );

            PasswordDigestDocument nonMatchingDocument =
                new PasswordDigestDocument( nonMatch.Digest, Guid.NewGuid( ), new DateTime( 2011, 11, 1 ), new DateTime( 2011, 11, 1 ), string.Empty );

            _passwordRepository.SavePassword( nonMatchingDocument );

            // Exercise
            Guid? guid = _masterPasswordMatcher.IdentifyMasterPassword( "toto".ToSecureString( ) );
            // Verify
            Assert.That( guid.HasValue, Is.False );
        }
        public bool UpdatePassword( PasswordDigestDocument original, PasswordDigestDocument password )
        {
            if ( original == null )
                throw new ArgumentNullException( "original" );
            if ( password == null )
                throw new ArgumentNullException( "password" );

            if ( original.Key != password.Key )
                throw new ArgumentException( "Replacement must have same key as original.", "password" );

            Load( );

            if ( !_passwordsCache.ContainsKey( original.Key ) )
                return false;
            var mergedPasswords = Merge( new[ ] { password }, false );

            Save( );
            return mergedPasswords.Count( ) > 0;
        }
 private PasswordDigestDocument WithMasterPasswordId( PasswordDigestDocument source, Guid masterPasswordId )
 {
     return new PasswordDigestDocument( source.Digest, masterPasswordId, source.CreatedOn, source.ModifiedOn, source.Note );
 }
 private PasswordDigestDocument Update( PasswordDigestDocument source, DateTime updatedOn )
 {
     return new PasswordDigestDocument( source.Digest, source.MasterPasswordId, source.CreatedOn, updatedOn, source.Note );
 }
 public BaselinePasswordDocument( PasswordDigestDocument baseline )
 {
     if ( baseline == null )
         throw new ArgumentNullException( "baseline" );
     _baseline = baseline;
 }
 public PasswordEditorViewModel PasswordEditorFor( PasswordDigestDocument document )
 {
     if ( document == null )
         throw new ArgumentNullException( "document" );
     return _factory( _editor.ModelFor( document ) );
 }
 public IPasswordEditorModel ModelFor( PasswordDigestDocument password )
 {
     return new PasswordEditorModel( _passwordRepository, _derivationEngine, _masterPasswordMatcher, _timeProvider,
                                     new BaselinePasswordDocument( password ) );
 }
 private bool SaveFullUpdate( )
 {
     if ( SelectedPassword == null )
         throw new InvalidOperationException( );
     DateTime createdOn = _original.CreatedOn ?? Now;
     Guid masterPasswordId = MasterPasswordId ?? Guid.NewGuid( );
     PasswordDigestDocument current =
         new PasswordDigestDocument( SelectedPassword.DerivedPassword.Digest, masterPasswordId, createdOn, Now, Note );
     return Save( current );
 }
        private bool SaveUpdatedNote( )
        {
            Guid? masterPasswordId = _original.MasterPasswordId;
            DateTime? createdOn = _original.CreatedOn;
            PasswordDigestDocument originalDocument = _original.Document;

            if ( !masterPasswordId.HasValue )
                throw new InvalidOperationException( );
            if ( !createdOn.HasValue )
                throw new InvalidOperationException( );
            if ( originalDocument == null )
                throw new InvalidOperationException( );

            PasswordDigestDocument current =
                new PasswordDigestDocument( originalDocument.Digest, masterPasswordId.Value, createdOn.Value, Now, Note );
            return Save( current );
        }
 private Func<PasswordDigestDocument, bool> ShouldMergeWith( PasswordDigestDocument document )
 {
     return d => d.Key == document.Key &&
                 d.Hash.SequenceEqual( document.Hash ) &&
                 d.MasterPasswordId != document.MasterPasswordId;
 }
        private IEnumerable<PasswordDigestDocument> Merge( IEnumerable<PasswordDigestDocument> newPasswords, IMasterPasswordIdMapper mapper )
        {
            IList<PasswordDigestDocument> result = new List<PasswordDigestDocument>( );
            foreach ( var newPassword in newPasswords )
            {
                DateTime creation;
                if ( _passwordsCache.ContainsKey( newPassword.Key ) )
                {
                    var oldPassword = _passwordsCache[ newPassword.Key ];
                    if ( oldPassword.ModifiedOn.CompareTo( newPassword.ModifiedOn ) > 0 )
                        continue;
                    creation = oldPassword.IsDeleted
                                   ? newPassword.CreatedOn
                                   : new[ ] { oldPassword.CreatedOn, newPassword.CreatedOn }.Min( );
                }
                else
                {
                    creation = newPassword.CreatedOn;
                }

                var mergedPassword = new PasswordDigestDocument( newPassword.Digest,
                                                                 mapper.MapMasterPassword( newPassword.MasterPasswordId ),
                                                                 creation,
                                                                 newPassword.ModifiedOn,
                                                                 newPassword.Note );
                _passwordsCache[ mergedPassword.Key ] = mergedPassword;
                result.Add( mergedPassword );
            }
            return result;
        }
 private bool Save( PasswordDigestDocument passwordDigestDocument )
 {
     if ( _original.Document != null )
         return _passwordRepository.UpdatePassword( _original.Document, passwordDigestDocument );
     return _passwordRepository.SavePassword( passwordDigestDocument );
 }