Search code examples
.netpowershellencryptionkeepass

How to encrypt using credentials of the current Windows user in powershell for KeePass?


I need to write a script that encrypts a string the same way that the {PASSWORD_ENC}placeholder is encrypted in KeePass:

{PASSWORD_ENC} – Encrypting Passwords:

The {PASSWORD_ENC} placeholder is replaced by the password of the current entry in encrypted form. The password is encrypted using credentials of the current Windows user. The encrypted password should not be stored and only works for the current user.

(emphasis mine)

How can I encrypt a string programmatically to get the same encrypted password as the one I would get in KeePass?


Solution

  • From the KeePass source code (\KeePassLib\Utility\StrUtil.cs)

    private static readonly byte[] m_pbOptEnt = { 0xA5, 0x74, 0x2E, 0xEC };
    
    public static string EncryptString(string strPlainText)
    {
        if(string.IsNullOrEmpty(strPlainText)) return string.Empty;
    
        try
        {
            byte[] pbPlain = StrUtil.Utf8.GetBytes(strPlainText);
            byte[] pbEnc = ProtectedData.Protect(pbPlain, m_pbOptEnt,
                DataProtectionScope.CurrentUser);
    
    #if (!KeePassLibSD && !KeePassRT)
            return Convert.ToBase64String(pbEnc, Base64FormattingOptions.None);
    #else
            return Convert.ToBase64String(pbEnc);
    #endif
        }
        catch(Exception) { Debug.Assert(false); }
    
        return strPlainText;
    }
    

    Fortunately, we can use .NET members in PowerShell and do the same thing:

    [System.Reflection.Assembly]::LoadWithPartialName('System.Security') | Out-Null;
    [byte[]] $m_pbOptEnt = @(0xA5,0x74,0x2E,0xEC);
    $plainBytes = [System.Text.Encoding]::UTF8.GetBytes( "my super strong password is 123456" );
    $cipherBytes = [System.Security.Cryptography.ProtectedData]::Protect($plainBytes, $m_pbOptEnt, [System.Security.Cryptography.DataProtectionScope]::CurrentUser);
    $cipherPw = [System.Convert]::ToBase64String($cipherBytes);