I wanted for some time to write a very simple password keeper for personal use. I'm posting it in case someone else finds it useful. I think it has some interesting ideas.
Once the username/password is inputted, it's kept encrypted. The way to use it: either by drag and drop (this is useful for HTML based forms) or
SendMessage(WM_SETTEXT,...) buttons. You can look at the tool tips for each button.
So the password is never seen in the program itself in plain text unless you use the password or import previous passwords. No copy/paste to/from clipboard.
The app minimizes to a system tray. It has a hotkey (CTRL+F12). During startup, it asks for a password. When used for the first time, it will use this password to encrypt the data. Once you add your passwords, it's a good idea to backup the file to a safe location.
- In most cases, the sensitive information is cleared right away (doesn't mean it's a 100% sure way) after it's not needed anymore through
Array.Clear. But when dragging/sending the info to another window or when importing from another file, user and password is decrypted into a
String and not cleared because
String is immutable. So it's left to the GC.
- Set the appropriate NTFS permissions on the application's directory, that's where the password file will be.
- It's a good idea to modify the code that derives the encryption keys (add different iteration counts for hash, etc.) so it will be different from the version included with this article.
- Use some .NET obfuscator. For example, at least the basic version that comes with Visual Studio 2003 (Dotfuscator community edition).
The hotkey is registered and used through P/Invoke:
private static extern bool RegisterHotKey(IntPtr hWnd, Int32 id,
UInt32 fsModifiers, UInt32 vk);
private static extern bool UnregisterHotKey(IntPtr hWnd, Int32 id);
WM_HOTKEY message is handled in
protected override void WndProc(ref Message m)
if (m.Msg == 0x0312)
Visible = true;
WindowState = FormWindowState.Normal;
The username and password use different encryption algorithms from whole file encryption. The keys and ivs are derived for two algorithms through
pdb = PasswordDeriveBytes(txtPass.Text, salt, "SHA512", 1000)
keyRij = pdb.GetBytes(32);
key3des = pdb.GetBytes(24);
ivRij = pdb.GetBytes(16);
iv3des = pdb.GetBytes(8);
In most cases, the sensitive information is cleared right away after it's not needed anymore through
Array.Clear. But when dragging/sending the info to another window, it's decrypted into a
String and not cleared because
String is immutable.
string val =
IntPtr ptr = Marshal.StringToCoTaskMemAuto(val);
SendMessage(hWnd, 0x000C, 0, ptr.ToInt32());
SendMessage case in mouse button down I've set
Capture = true. Then in mouse button up event the
Capture is set to
false. And actual target window is found through P/Invoke.
private static extern bool ScreenToClient(IntPtr hWnd, ref SeqPoint pt);
private static extern IntPtr GetParent(IntPtr hWnd);
private static extern IntPtr WindowFromPoint(SeqPoint pt);
private static extern IntPtr
RealChildWindowFromPoint(IntPtr hWndParent, SeqPoint Point);
The actual code to find the target window:
private IntPtr FindTargetWindow(Point pt)
SeqPoint seqpt = new SeqPoint();
seqpt.x = pt.X;
seqpt.y = pt.Y;
IntPtr hWnd = WindowFromPoint(seqpt);
if (hWnd.ToInt64() != 0)
IntPtr hParent = GetParent(hWnd);
if(hParent.ToInt64() != 0 &&
ScreenToClient(hParent, ref seqpt))
hParent = RealChildWindowFromPoint(hParent, seqpt);
if(hParent.ToInt64() != 0)
hWnd = hParent;
When selecting the target window, there is a selection frame drawn for the target window. This is accomplished as follows:
private static extern int GetBkColor(IntPtr hdc);
private static extern bool GetWindowRect(IntPtr hWnd, out SeqRect rect);
private void FrameTargetWnd()
Point pt = Cursor.Position;
IntPtr hWnd = FindTargetWindow(pt);
if(hWnd.ToInt64() != 0)
if(GetWindowRect(hWnd, out rc))
Rectangle rect = new Rectangle(rc.left,
rc.top, rc.right - rc.left, rc.bottom - rc.top);
if(rect != previousRect)
Graphics g = Graphics.FromHwnd(hWnd);
IntPtr hDC = g.GetHdc();
if(hDC.ToInt64() != 0)
if(previousRect.Height > 0
|| previousRect.Width > 0)
if(hWnd != this.Handle)
drawFrameBkColor = Color.FromArgb(GetBkColor(hDC));
previousRect = rect;
drawFrameBkColorPrev = drawFrameBkColor;
previousRect.Size = new Size(0,0);
Everything else is just standard .NET stuff.
THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
- 17th August, 2003: Initial post
- 18th October, 2008: Download file updated