Browse DevX
Sign up for e-mail newsletters from DevX


Storing Your Secret Data in Windows

Although it is generally deemed bad practice, sometimes secrets simply have to be stored somewhere that is accessible to users and/or applications. This article outlines some of the best practices for storing secrets on various Windows platforms.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Developers often ask me how they can safely store secret information when building secure systems. A secret is any data known only to one or more valid computers, users, or applications. Examples include passwords, keys to decrypt other data, and so on. The short answer to their question is they can't; the long answer is the subject of this article.

Sometimes You Don't Need to Store the Secret
If you store a secret only to verify that another entity also knows the secret, then you probably don't need to store the secret itself. Instead, you can store a "verifier," which often is the hash value of the secret. For example, if an application needs to verify that a user knows a password, you can compare the hash value of the secret the user entered with the hash value of the stored secret. In this case, the secret itself is not stored by the application and thus presents less risk—if attackers break into the system, they cannot retrieve the secret itself.

To make things a little more difficult for an attacker, you can also "salt" the hash value. A salt is a random number that is added to the hash value to stop pre-computed dictionary attacks, making an attempt to recover the original secret extremely expensive. The salt is stored with the hash value. Choosing a hash function is an important decision. Always use a cryptographically strong hash function, one that has been demonstrated to have no—or extremely low—collision chances. In other words, creating two data that compute the same hash value should be infeasible. The hash function de jour is SHA-1. MD5 has fallen somewhat out of favor as subtle vulnerabilities have been discovered in the algorithm.

Let's look at the steps required to store the hash value of the secret and validate the secret.

  1. Store the salted hash value.
    • Get the secret you wish to protect (for example, a user's password).
    • Derive a random 128-bit number [use CryptGenRandom()], this is the salt.
    • Run a hash function on the secret [use CryptCreateHash() and CryptHashData()].
    • Add the salt to your hash value [use CryptHashData()].
    • Store the salt and the hash value.
  2. Verify that the user knows the secret.
    • Get the secret from the user.
    • Run a hash function on the secret [use CryptCreateHash() and CryptHashData()].
    • Get the hash value and the salt from storage.
    • Add the salt to hash value [use CryptHashData()].
    • Compare the two salted hash values. If they are the same, then chances are the user knows the secret.
As you can see, you may be able to get away with not storing a secret, which is always preferable to storing one. But sometimes you must store the secret. So let's look at secure ways of doing so.

The Safest Way to Store Secrets
The most secure way to store and protect secrets is to get input from a user. This input can be used as the key to encrypt and decrypt the protected data. In other words, the secrets are protected with data held in a user's head; they are not persisted.

However, storing secrets this way can often become unusable for most users. The more items of information (number of passwords) you make them remember, the more likely they are to use the same password over and over, which reduces the system's security and usability, and increases complexity.

Now let's turn our attention to the more complex issues of the error-prone method: storing secrets without prompting for user-defined keys.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date