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 algorithm 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 .T.
returns the result in binHex
format. BinHex is binary represented as two byte pairs.
Example: 0A02EE292AB2
BinHex results are returned in UPPER CASE. If you're sending a hash to a third party, or you are using the hash for further encoding, make sure you know what case is expected and use
LOWER()
to force to lower case if necessary.
If not specified the value set globally by SetBinHexMode()
is used instead, which defaults to Base64.
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 towwEncryption
.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.UPPER/lower CASE If you're sharing hashes with third parties make sure you check for case of the hash value. This is particularily important for BinHex results which can be either upper or lower case and may not be accepted if in the wrong case. Know what is expected.
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, 2023 • Updated: 11/12/21
Comment or report problem with topic