Every time I make a program requiring the user to login, I end up designing the login system from scratch. So I decided to create a standardized system.
Objectives:
1. Require a UserID & Password to start a program.
2. Store them in the Registry.
3. Protect the Password from copying.
4. Do not store the Password in memory.
5. Allow some parts of the program to be accessed without login.
6. On first time use, automatically run setup.
7. Allow user to try again if password fails.
8. Allow user to change settings via a hot key.
To allow the UserID & Password to be stored in the Registry, the program needs to be named, and that name is stored in the variable "gAppName". It borrows the value of the App Product Name, which in the sample is stored in the project properties as "Login". Other values can be stored in the "Setup" routine at the same time.
The password is not stored in its raw form. It is first hashed, and then the hash is shuffled using the Windows logged in user SID (Secure ID) as a seed. The advantage of using the SID is that the program cannot be moved to another machine or another user and un-shuffle the hash. If you are using the Password to log into a remote server, the password must be recovered and unshuffled back to the hash, since the server has no idea what the SID is. Because the hash is now the actual password, a man-in-the-middle could intercept the password in transit. It is therefore advisable to send it encrypted.
The sample checks the value of the UserID, and if empty it is diverted to the "Setup" routine. A "Ctrl-s" can be used to access the "Setup" routine directly. If you forget the password, the only way to change it is to delete the password hash from the registry. Allowing the user to access Setup requires setting the form "KeyPreview" to true.
I have used a DLL (Dynamic Linked Library) prepared by using MakeDLL from DanSoft Australia to create jCrypt.dll. It provides the following function:
HashData
as outlined in the declarations section of the form. If you don't have access to this facility, you can comment out the declaration provided and add the mEncrypt.bas module provided to the project.
J.A. Coutts
Objectives:
1. Require a UserID & Password to start a program.
2. Store them in the Registry.
3. Protect the Password from copying.
4. Do not store the Password in memory.
5. Allow some parts of the program to be accessed without login.
6. On first time use, automatically run setup.
7. Allow user to try again if password fails.
8. Allow user to change settings via a hot key.
To allow the UserID & Password to be stored in the Registry, the program needs to be named, and that name is stored in the variable "gAppName". It borrows the value of the App Product Name, which in the sample is stored in the project properties as "Login". Other values can be stored in the "Setup" routine at the same time.
The password is not stored in its raw form. It is first hashed, and then the hash is shuffled using the Windows logged in user SID (Secure ID) as a seed. The advantage of using the SID is that the program cannot be moved to another machine or another user and un-shuffle the hash. If you are using the Password to log into a remote server, the password must be recovered and unshuffled back to the hash, since the server has no idea what the SID is. Because the hash is now the actual password, a man-in-the-middle could intercept the password in transit. It is therefore advisable to send it encrypted.
The sample checks the value of the UserID, and if empty it is diverted to the "Setup" routine. A "Ctrl-s" can be used to access the "Setup" routine directly. If you forget the password, the only way to change it is to delete the password hash from the registry. Allowing the user to access Setup requires setting the form "KeyPreview" to true.
I have used a DLL (Dynamic Linked Library) prepared by using MakeDLL from DanSoft Australia to create jCrypt.dll. It provides the following function:
HashData
as outlined in the declarations section of the form. If you don't have access to this facility, you can comment out the declaration provided and add the mEncrypt.bas module provided to the project.
J.A. Coutts