This article is about using password managers, if you don't know why this is a good idea, read the article: The Real Life Risks Of Re Using The Same Passwords by Bill Hess.
I recently migrated from Password Safe to KeePass for storing my passwords.
I'm using a very long and complex master-password, which is kind of annoying to type in every time I open the program.
KeePass offers more than just a password for authentication. You can also specify a key file or use your Windows account. On my main workstation at home, my Windows account it pretty secure. However I don't want to use it as a key for my main KeePass database.
My solution was to make a copy for local read-only use and set the master key with a less-strong password and my Windows user account.
This way I only have to type a short password, but when I use KeePass on different devices I still only use the strong password.
However after I changed any data in my master database, I had to make a new copy and change the masterkey again.
That's only a few clicks, but I rather automate things. So I wrote a PowerShell script that makes a copy of the database and sets the new master key
Save the following into Copy-KeePassDB.ps1
param( [parameter(Mandatory=$true)][string]$SourceDB, [parameter(Mandatory=$true)][string]$TargetDB, [parameter(Mandatory=$true)][string]$KeePassFolder ) $pass = Read-Host 'Type the password for Master-KeePass database' -AsSecureString $PasswordForSource = [Runtime.InteropServices.Marshal]::PtrToStringAuto( [Runtime.InteropServices.Marshal]::SecureStringToBSTR($pass)) $pass2 = Read-Host 'Type the password for new Local-KeePass database' -AsSecureString $PasswordForTarget = [Runtime.InteropServices.Marshal]::PtrToStringAuto( [Runtime.InteropServices.Marshal]::SecureStringToBSTR($pass2)) #Load all .NET binaries in the folder (Get-ChildItem -recurse $KeePassFolder | Where-Object {($_.Extension -EQ ".dll") -or ($_.Extension -eq ".exe")} ` | ForEach-Object { $AssemblyName=$_.FullName; Try {[Reflection.Assembly]::LoadFile($AssemblyName) } Catch{ }} ) | out-null # remove an existing copy and copy the master If (Test-Path $TargetDB) { Remove-Item $TargetDB -force } Copy-Item $SourceDB -Destination $TargetDB # Open the new database $PwDatabase = new-object KeePassLib.PwDatabase $m_pKey = new-object KeePassLib.Keys.CompositeKey $m_pKey.AddUserKey((New-Object KeePassLib.Keys.KcpPassword($PasswordForSource))); $m_ioInfo = New-Object KeePassLib.Serialization.IOConnectionInfo $m_ioInfo.Path = $TargetDB $IStatusLogger = New-Object KeePassLib.Interfaces.NullStatusLogger $PwDatabase.Open($m_ioInfo,$m_pKey,$IStatusLogger) # Create a new key for the database $m_pKeyNew = new-object KeePassLib.Keys.CompositeKey $m_pKeyNew.AddUserKey((New-Object KeePassLib.Keys.KcpPassword($PasswordForTarget))); $m_pAccount = new-object KeePassLib.Keys.KcpUserAccount $m_pKeyNew.AddUserKey($m_pAccount); # Set the new key and save it $PwDatabase.MasterKey = $m_pKeyNew $PwDatabase.Save($null) $PwDatabase.Close() $PwDatabase = $null Write-Host "Database copied and new credentials set, only accessible to $env:USERDOMAIN\$env:UserName"Now you can use a helper-script to set your file paths:
Copy-KeePassDB.ps1 -SourceDB "C:\mymaster.kdbx" -TargetDB "C:\mylocal.kdbx" -KeePassFolder "C:\Program Files\KeepPass\"
You will be asked for two passwords, the old master one and the new weaker one.