wwEncryption::ComputeHash

Hashes are one-way encrypted values that can be used to store passwords and other secure data that needs to be verified, but does not need to be retrieved in its original format.

Hash output is returned as a base64 (default) or binHex string. Make sure you are using the correct format to match your requirements! Many third party services need you to provide hashes in binHex format.

Passwords can be hashed and you can validate a password by rehashing the data from which it is created. Whenever you can encrypt data in a completely repeatable way to verify it, a one-way hash is preferable over two-way encryption.

Hashes can never retrieve the original value from which the hash was created. You can only validate a hash by recreating it with the same input data.

The ComputeHash() method creates a one-way hash of an input string useful for passwords or authorization tokens using any of the following hashing algorithms:

  • MD5
  • SHA1
  • SHA256
  • SHA384
  • SHA512
  • HMACMD5
  • HMACSHA1
  • HMACSHA256
  • HMAC384
  • HMAC512.

The HMAC Versions require that you pass a hash salt value. For the others it is optional.

You can provide an optional salt to further randomize the hash. It's recommended you use a unique Salt Value for each hash you create, such as a user id when password hashing for example.

o.ComputeHash(lcText, lcAlgorithm, lvHashSalt, llUseBinHex)

Return Value

Base64 encoded string of the hash

Parameters

lcText
Text to hash

lcAlgorithm
The has algorith used. Valid values include: MD5, SHA1, SHA256, SHA384, SHA512, HMACSH1, HMACSHA256, HMAC384, HMAC512

lvHashSalt
A string or binary value that is used to salt the hash. For best security use a custom salt for each value generated. For example when generating a password, salt the hash with the user ID.

For HMAC providers the HashSalt is required.

For non-HMAC providers the HashSalt is optional. If not provided only the raw Hash algorithm is applied without any salting. If a HashValue is provided a simple multi-step salting process is applied.

llUseBinHex
If set returns the result in binHex format (binary number represented as two byte pairs. The default is base64. If not specified the value set globally by SetBinHexMode() is used instead.

Remarks

Typical password hashing workflow: Hash a password by hashing the password provided plus the user id as the salt, then store it in your data store. To verify, a user provides their password, which you then re-hash using the password and user id. You can then compare this hash to the hash you have stored in the data store for this user.


The HMAC versions require a HashSalt value while it's optional for the other providers.

HMAC uses a well-known multiple rehashing algorithm to hash a salt value and applies it to the value to hash. Generally this is the most verifiably secure way to go if HMAC is supported for hash encoding and verification. Recommended Hash Algorithm

If you provide a hash value for other providers, a much simpler, custom hash salting algorithm is used. Using this approach requires that you always use wwEncryption for hashing as it's a custom algorithm specific to wwEncryption.

If you use one of the non-HMAC providers without a HashSalt just the raw Hash algorithm without salt is applied. This can be verified by any client, that supports the hash algorithm, but hashing without salt is considered much less secure.

If at all possible use the HMAC versions. They provide best security and are universally supported by various languages and encryption tools. Use non-HMAC with custom salt for application specific hashing where both the hash creation and verification can use wwEncryption. For non-security critical hashing like verification and validation, you can use non-salted base hashes.

Example

*** Best Practice is to create Hashes with a reproducible UNIQUE Salt (like a PK or UserId):
lcPassword = "seeekrit"
loUser = GetUser("1233")
loUser.Password =  o.ComputeHash(lcPassword,"HMACSHA256",loUser.cUserId)
loUser.Save()

...

*** To check for a password
lcPassword = "seeekrit"

loUser.GetUserByUserName("1233")
if(loUser.cPassword == o.ComputeHash(lcPassword,"HMACSHA256",loUser.cUserId))
   ? "Password is valid!"
endif


*** Other Examples
?
? "Plain Hash without Salt:"
? o.ComputeHash(lcOriginal,"MD5")
? o.ComputeHash(lcOriginal,"SHA256")
? o.ComputeHash(lcOriginal,"SHA512")

?
? "Hash using explicit Salt:"
? o.ComputeHash(lcOriginal2,"MD5",lcSecretSalt)
? o.ComputeHash(lcOriginal2,"SHA256",lcSecretSalt)
? o.ComputeHash(lcOriginal2,"SHA512",lcSecretSalt)
? o.ComputeHash(lcOriginal2,"HMACSHA512",lcSecretSalt)


?
? "Hash using globally assigned salt:"
*** Set global secret key so you don't have to pass lcSecretHash
*** but still use your custom key
o.SetComputeHashSaltBytes("$$Different_Sekrit02!!")

*** Using a secret hash - you can pass string or byte[] data
? o.ComputeHash(lcOriginal2,"MD5")
? o.ComputeHash(lcOriginal2,"SHA256")
? o.ComputeHash(lcOriginal2,"SHA512")
? o.ComputeHash(lcOriginal2,"HMACSHA512")

See also:

Class wwEncryption

© West Wind Technologies, 1996-2021 • Updated: 08/13/21
Comment or report problem with topic