Using htpasswd passwords with CryptoSys API
SHA1_StringHexHash
and base64 conversion functions from CryptoSys API.
A typical password file might contain entries of the form
sean:{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
susan:{SSHA}YNHKJFkkauc8jvY7Wur2cJ9bAgiTKs7N
The code below shows how to create the `htpasswd' strings that begin with "{SHA}" or "{SSHA}" and also
how to verify a given string with a password.
Just to be clear, the usual htpasswd algorithm uses the crypt3 algorithm,
which we don't currently support (but we might if you ask nicely).
There is also an Apache "modified" MD5 algorithm (whatever that is) which we don't support either.
This code just considers htpasswd strings that begin with "{SHA}" or "{SSHA}".
Public Function Make_htpasswd_sha1(strPassword As String) As String ' Given password, return the htpasswd string in the form "{SHA}" Dim nRet As Long Dim strDigestHex As String Dim strDigestB64 As String ' Compute hex-encoded SHA-1 digest of password string strDigestHex = String(API_MAX_SHA1_CHARS, " ") nRet = SHA1_StringHexHash(strDigestHex, strPassword) ' Now convert from hex to base64 strDigestB64 = cnvB64StrFromBytes(cnvBytesFromHexStr(strDigestHex)) ' Prepend "{SHA}" and return Make_htpasswd_sha1 = "{SHA}" & strDigestB64 End Function Public Function Make_htpasswd_salted_sha1(strPassword As String) As String ' Given password, return the htpasswd string in the form "{SSHA}" Dim nRet As Long Dim strDigestHex As String Dim strDigestB64 As String Dim strSaltHex As String Dim strSalt As String ' Generate a 4-byte random salt in hex format strSaltHex = rngNonceHex(4) ' Convert to a 4-byte string strSalt = cnvStringFromHexStr(strSaltHex) ' Compute hex-encoded SHA-1 digest of (password||salt) string strDigestHex = String(API_MAX_SHA1_CHARS, " ") nRet = SHA1_StringHexHash(strDigestHex, strPassword & strSalt) ' Now convert (digest||salt) from hex to base64 strDigestB64 = cnvB64StrFromBytes(cnvBytesFromHexStr(strDigestHex & strSaltHex)) ' Prepend "{SSHA}" and return Make_htpasswd_salted_sha1 = "{SSHA}" & strDigestB64 End Function Public Function Verify_htpasswd(strPassword As String, strHtpasswd As String) As Integer ' Returns 0 if OK, 1 if fails and -1 if an error occurred e.g. unsupported. ' Only supports {SHA} and {SSHA} htpasswds. Dim nRet As Long Dim strDigestHex As String Dim strDigestB64 As String Dim strPwdHex As String Dim strSaltHex As String Dim strSalt As String Verify_htpasswd = 1 ' Guilty until proven innocent If Left$(strHtpasswd, 5) = "{SHA}" Then ' Simple non-salted SHA-1 algorithm, so extract digest from htpasswd string strDigestB64 = Mid$(strHtpasswd, 6) strDigestHex = cnvHexStrFromBytes(cnvBytesFromB64Str(strDigestB64)) ' Recompute SHA-1 hash of given password strPwdHex = String(API_MAX_SHA1_CHARS, " ") nRet = SHA1_StringHexHash(strPwdHex, strPassword) If UCase(strPwdHex) = UCase(strDigestHex) Then Verify_htpasswd = 0 Else Verify_htpasswd = 1 End If ElseIf Left$(strHtpasswd, 6) = "{SSHA}" Then ' Salted SHA-1 algorithm, so extract (digest||salt) from htpasswd string strDigestB64 = Mid$(strHtpasswd, 7) strDigestHex = cnvHexStrFromBytes(cnvBytesFromB64Str(strDigestB64)) If Len(strDigestHex) < 42 Then Debug.Print "Invalid htpasswd string" Verify_htpasswd = -1 Exit Function End If ' Split (digest||salt) into separate hex strings strSaltHex = Mid$(strDigestHex, 41) strDigestHex = Left$(strDigestHex, 40) ' Convert salt from hex into a string strSalt = cnvStringFromHexStr(strSaltHex) ' Recompute SHA-1 hash of given password + salt strPwdHex = String(API_MAX_SHA1_CHARS, " ") nRet = SHA1_StringHexHash(strPwdHex, strPassword & strSalt) If UCase(strPwdHex) = UCase(strDigestHex) Then Verify_htpasswd = 0 Else Verify_htpasswd = 1 End If Else Debug.Print "Unsupported htpasswd algorithm" Verify_htpasswd = -1 Exit Function End If End FunctionThe code can be downloaded separately as a text file.
Examples of newly created {SHA} htpasswd strings are
? make_htpasswd_sha1("abc")
{SHA}qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
and
? make_htpasswd_sha1("password")
{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
These values will always be the same for a given password. For that reason,
we do not recommend the use of the un-salted SHA-1 password strings. Use the salted ones if you can.
Examples of {SSHA} htpasswd strings with a salt are
? Make_htpasswd_salted_sha1("abc")
{SSHA}i2IK8fsdsFRq6oAg3dU4pVrpM3so3rqD
and
? Make_htpasswd_salted_sha1("password")
{SSHA}y/6RK6tWKwyW3Z+kz1u9uwAGjscz/XRD
Unlike the unsalted variety, these values will always be different, even for the same password.
This is more secure. For example:
? Make_htpasswd_salted_sha1("password")
{SSHA}Hnww+GuzW9ySa4HCJm2lqzYucUHlhm9o
? Make_htpasswd_salted_sha1("password")
{SSHA}PF3cjsK6WyPpcD9mA6JSBhQ3+4jUxQwp
? Make_htpasswd_salted_sha1("password")
{SSHA}CAHTDisW6rEHgWDR0bVjcbNlWylbWOBJ
To verify a user password, specify both the password string, as typed by the user, and the htpasswd string. A valid password/htpasswd string combination returns zero.
? Verify_htpasswd("password", "{SSHA}CAHTDisW6rEHgWDR0bVjcbNlWylbWOBJ")
0
An incorrect password will return +1
? Verify_htpasswd("bad-password", "{SSHA}CAHTDisW6rEHgWDR0bVjcbNlWylbWOBJ")
1
And an unsupported algorithm will return -1
? Verify_htpasswd("password", "YLZzy24Wj6.TU")
Unsupported htpasswd algorithm
-1
This page last updated 1 May 2007
Home |
Blowfish |
Rijndael AES |
DES |
Triple DES |
SHA-1 |
SHA-256 |
Random numbers |
Compression |
CryptoSys Manual |
Purchase |
CryptoSys PKI |
Search |
Cryptography Software Code |
Contact us
Copyright © 2007 D.I. Management Services Pty Limited ABN 78 083 210 584,
Sydney, Australia. All rights reserved.
<www.di-mgt.com.au>
<www.cryptosys.net>