Attribute VB_Name = "basHtpasswd" Option Explicit 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 Function