diff --git a/httpbin/digest/digest.go b/httpbin/digest/digest.go
index 13c09e1306333184a1049955cafe4c2ef82cb8d7..f679382277a7c7db1eec2ad918c87dca3ca0b6c1 100644
--- a/httpbin/digest/digest.go
+++ b/httpbin/digest/digest.go
@@ -11,7 +11,6 @@
 package digest
 
 import (
-	"crypto"
 	"crypto/md5"
 	"crypto/sha256"
 	"crypto/subtle"
@@ -22,6 +21,25 @@ import (
 	"time"
 )
 
+// digestAlgorithm is an algorithm used to hash digest payloads
+type digestAlgorithm int
+
+// Digest algorithms supported by this package
+const (
+	MD5 digestAlgorithm = iota
+	SHA256
+)
+
+func (a digestAlgorithm) String() string {
+	switch a {
+	case MD5:
+		return "MD5"
+	case SHA256:
+		return "SHA-256"
+	}
+	return "UNKNOWN"
+}
+
 // Check returns a bool indicating whether the request is correctly
 // authenticated for the given username and password.
 func Check(req *http.Request, username, password string) bool {
@@ -34,23 +52,32 @@ func Check(req *http.Request, username, password string) bool {
 }
 
 // Challenge returns a WWW-Authenticate header value for the given realm and
-// algorithm.
-func Challenge(realm, algorithm string) string {
+// algorithm. If an invalid realm or an unsupported algorithm is given
+func Challenge(realm string, algorithm digestAlgorithm) string {
 	entropy := make([]byte, 32)
 	rand.Read(entropy)
 
 	opaqueVal := entropy[:16]
 	nonceVal := fmt.Sprintf("%s:%x", time.Now(), entropy[16:31])
 
-	opaque := hash(opaqueVal, crypto.MD5)
-	nonce := hash([]byte(nonceVal), crypto.MD5)
+	// we use MD5 to hash nonces regardless of hash used for authentication
+	opaque := hash(opaqueVal, MD5)
+	nonce := hash([]byte(nonceVal), MD5)
+
+	return fmt.Sprintf("Digest qop=auth, realm=%#v, algorithm=%s, nonce=%s, opaque=%s", sanitizeRealm(realm), algorithm, nonce, opaque)
+}
 
-	return fmt.Sprintf("Digest qop=auth, realm=%s, algorithm=%s, nonce=%s, opaque=%s", realm, algorithm, nonce, opaque)
+// sanitizeRealm tries to ensure that a given realm does not include any
+// characters that will trip up our extremely simplistic header parser.
+func sanitizeRealm(realm string) string {
+	realm = strings.Replace(realm, `"`, "", -1)
+	realm = strings.Replace(realm, ",", "", -1)
+	return realm
 }
 
 // authorization is the result of parsing an Authorization header
 type authorization struct {
-	algorithm crypto.Hash
+	algorithm digestAlgorithm
 	cnonce    string
 	nc        string
 	nonce     string
@@ -92,9 +119,9 @@ func parseAuthorizationHeader(value string) *authorization {
 	authInfo := parts[1]
 	auth := parseDictHeader(authInfo)
 
-	algo := crypto.MD5
+	algo := MD5
 	if strings.ToLower(auth["algorithm"]) == "sha-256" {
-		algo = crypto.SHA256
+		algo = SHA256
 	}
 
 	return &authorization{
@@ -136,9 +163,9 @@ func parseDictHeader(value string) map[string]string {
 
 // hash generates the hex digest of the given data using the given hashing
 // algorithm, which must be one of MD5 or SHA256.
-func hash(data []byte, algorithm crypto.Hash) string {
+func hash(data []byte, algorithm digestAlgorithm) string {
 	switch algorithm {
-	case crypto.SHA256:
+	case SHA256:
 		return fmt.Sprintf("%x", sha256.Sum256(data))
 	default:
 		return fmt.Sprintf("%x", md5.Sum(data))
@@ -150,7 +177,7 @@ func hash(data []byte, algorithm crypto.Hash) string {
 //     HA1 = H(A1) = H(username:realm:password)
 //
 // and H is one of MD5 or SHA256.
-func makeHA1(realm, username, password string, algorithm crypto.Hash) string {
+func makeHA1(realm, username, password string, algorithm digestAlgorithm) string {
 	A1 := fmt.Sprintf("%s:%s:%s", username, realm, password)
 	return hash([]byte(A1), algorithm)
 }
diff --git a/httpbin/digest/digest_test.go b/httpbin/digest/digest_test.go
index a359f1ac0fd4e34455a8bd72470bf62853ea3e14..dc25086eee65468dc544bae1effe0328a41496cf 100644
--- a/httpbin/digest/digest_test.go
+++ b/httpbin/digest/digest_test.go
@@ -1,7 +1,6 @@
 package digest
 
 import (
-	"crypto"
 	"fmt"
 	"net/http"
 	"reflect"
@@ -75,6 +74,27 @@ func TestCheck(t *testing.T) {
 	})
 }
 
+func TestChallenge(t *testing.T) {
+	var tests = []struct {
+		realm             string
+		expectedRealm     string
+		algorithm         digestAlgorithm
+		expectedAlgorithm string
+	}{
+		{"realm", "realm", MD5, "MD5"},
+		{"realm", "realm", SHA256, "SHA-256"},
+		{"realm with spaces", "realm with spaces", SHA256, "SHA-256"},
+		{`realm "with" "quotes"`, "realm with quotes", MD5, "MD5"},
+		{`spaces, "quotes," and commas`, "spaces quotes and commas", MD5, "MD5"},
+	}
+	for _, test := range tests {
+		challenge := Challenge(test.realm, test.algorithm)
+		result := parseDictHeader(challenge)
+		assertStringEquals(t, test.expectedRealm, result["realm"])
+		assertStringEquals(t, test.expectedAlgorithm, result["algorithm"])
+	}
+}
+
 func TestResponse(t *testing.T) {
 	auth := parseAuthorizationHeader(exampleAuthorization)
 	expected := auth.response
@@ -84,16 +104,15 @@ func TestResponse(t *testing.T) {
 
 func TestHash(t *testing.T) {
 	var tests = []struct {
-		algorithm crypto.Hash
+		algorithm digestAlgorithm
 		data      []byte
 		expected  string
 	}{
-		{crypto.SHA256, []byte("hello, world!\n"), "4dca0fd5f424a31b03ab807cbae77eb32bf2d089eed1cee154b3afed458de0dc"},
-		{crypto.MD5, []byte("hello, world!\n"), "910c8bc73110b0cd1bc5d2bcae782511"},
+		{SHA256, []byte("hello, world!\n"), "4dca0fd5f424a31b03ab807cbae77eb32bf2d089eed1cee154b3afed458de0dc"},
+		{MD5, []byte("hello, world!\n"), "910c8bc73110b0cd1bc5d2bcae782511"},
 
 		// Any unhandled hash results in MD5 being used
-		{crypto.MD4, []byte("hello, world!\n"), "910c8bc73110b0cd1bc5d2bcae782511"},
-		{crypto.SHA512, []byte("hello, world!\n"), "910c8bc73110b0cd1bc5d2bcae782511"},
+		{digestAlgorithm(10), []byte("hello, world!\n"), "910c8bc73110b0cd1bc5d2bcae782511"},
 	}
 	for _, test := range tests {
 		t.Run(fmt.Sprintf("hash/%v", test.algorithm), func(t *testing.T) {
@@ -177,7 +196,7 @@ func TestParseAuthorizationHeader(t *testing.T) {
 
 		// incomplete headers are fine
 		{"Digest username=u, realm=r, nonce=n", &authorization{
-			algorithm: crypto.MD5,
+			algorithm: MD5,
 			username:  "u",
 			realm:     "r",
 			nonce:     "n",
@@ -185,51 +204,51 @@ func TestParseAuthorizationHeader(t *testing.T) {
 
 		// algorithm can be either MD5 or SHA-256, with MD5 as default
 		{"Digest username=u", &authorization{
-			algorithm: crypto.MD5,
+			algorithm: MD5,
 			username:  "u",
 		}},
 		{"Digest algorithm=MD5, username=u", &authorization{
-			algorithm: crypto.MD5,
+			algorithm: MD5,
 			username:  "u",
 		}},
 		{"Digest algorithm=md5, username=u", &authorization{
-			algorithm: crypto.MD5,
+			algorithm: MD5,
 			username:  "u",
 		}},
 		{"Digest algorithm=SHA-256, username=u", &authorization{
-			algorithm: crypto.SHA256,
+			algorithm: SHA256,
 			username:  "u",
 		}},
 		{"Digest algorithm=foo, username=u", &authorization{
-			algorithm: crypto.MD5,
+			algorithm: MD5,
 			username:  "u",
 		}},
 		{"Digest algorithm=SHA-512, username=u", &authorization{
-			algorithm: crypto.MD5,
+			algorithm: MD5,
 			username:  "u",
 		}},
 		// algorithm not case sensitive
 		{"Digest algorithm=sha-256, username=u", &authorization{
-			algorithm: crypto.SHA256,
+			algorithm: SHA256,
 			username:  "u",
 		}},
 		// but dash is required in SHA-256 is not recognized
 		{"Digest algorithm=SHA256, username=u", &authorization{
-			algorithm: crypto.MD5,
+			algorithm: MD5,
 			username:  "u",
 		}},
 		// session variants not recognized
 		{"Digest algorithm=SHA-256-sess, username=u", &authorization{
-			algorithm: crypto.MD5,
+			algorithm: MD5,
 			username:  "u",
 		}},
 		{"Digest algorithm=MD5-sess, username=u", &authorization{
-			algorithm: crypto.MD5,
+			algorithm: MD5,
 			username:  "u",
 		}},
 
 		{exampleAuthorization, &authorization{
-			algorithm: crypto.MD5,
+			algorithm: MD5,
 			cnonce:    "0a4f113b",
 			nc:        "00000001",
 			nonce:     "dcd98b7102dd2f0e8b11d0f600bfb0c093",
diff --git a/httpbin/handlers.go b/httpbin/handlers.go
index 64bed3f8cf29e1e06099726c28c4fe4ddf197f8b..58f0579d43f19c3e4bf95db95df145b1193647a9 100644
--- a/httpbin/handlers.go
+++ b/httpbin/handlers.go
@@ -861,20 +861,25 @@ func (h *HTTPBin) DigestAuth(w http.ResponseWriter, r *http.Request) {
 	user := parts[3]
 	password := parts[4]
 
-	algorithm := "MD5"
+	algoName := "MD5"
 	if count == 6 {
-		algorithm = strings.ToUpper(parts[5])
+		algoName = strings.ToUpper(parts[5])
 	}
 
 	if qop != "auth" {
 		http.Error(w, "Invalid QOP directive", http.StatusBadRequest)
 		return
 	}
-	if algorithm != "MD5" && algorithm != "SHA-256" {
+	if algoName != "MD5" && algoName != "SHA-256" {
 		http.Error(w, "Invalid algorithm", http.StatusBadRequest)
 		return
 	}
 
+	algorithm := digest.MD5
+	if algoName == "SHA-256" {
+		algorithm = digest.SHA256
+	}
+
 	if !digest.Check(r, user, password) {
 		w.Header().Set("WWW-Authenticate", digest.Challenge("go-httpbin", algorithm))
 		w.WriteHeader(http.StatusUnauthorized)
diff --git a/httpbin/handlers_test.go b/httpbin/handlers_test.go
index eabffbd528c868a409f321405ec7ca677c299112..46cb62f664ccd127896c2ebef5d1b64456940a06 100644
--- a/httpbin/handlers_test.go
+++ b/httpbin/handlers_test.go
@@ -1123,9 +1123,16 @@ func TestDigestAuth(t *testing.T) {
 		{"/digest-auth", http.StatusNotFound},
 		{"/digest-auth/user", http.StatusNotFound},
 		{"/digest-auth/user/pass", http.StatusNotFound},
+		{"/digest-auth/auth/user/pass/MD5/foo", http.StatusNotFound},
 
+		// valid but unauthenticated requests
 		{"/digest-auth/auth/user/pass", http.StatusUnauthorized},
 		{"/digest-auth/auth/user/pass/MD5", http.StatusUnauthorized},
+		{"/digest-auth/auth/user/pass/SHA-256", http.StatusUnauthorized},
+
+		// invalid requests
+		{"/digest-auth/bad-qop/user/pass/MD5", http.StatusBadRequest},
+		{"/digest-auth/auth/user/pass/SHA-512", http.StatusBadRequest},
 	}
 	for _, test := range tests {
 		t.Run("ok"+test.url, func(t *testing.T) {
@@ -1135,6 +1142,40 @@ func TestDigestAuth(t *testing.T) {
 			assertStatusCode(t, w, test.status)
 		})
 	}
+
+	t.Run("ok", func(t *testing.T) {
+		// Example captured from a successful login in a browser
+		authorization := `Digest username="user",
+			realm="go-httpbin",
+			nonce="6fb213c6593975c877bb1247370527ad",
+			uri="/digest-auth/auth/user/pass/MD5",
+			algorithm=MD5,
+			response="9b7a05d78051b4f668356eedf32f55d6",
+			opaque="fd1c386a015a2bb7c41585f54329ce91",
+			qop=auth,
+			nc=00000001,
+			cnonce="aaab705226af5bd4"`
+
+		url := "/digest-auth/auth/user/pass/MD5"
+		r, _ := http.NewRequest("GET", url, nil)
+		r.RequestURI = url
+		r.Header.Set("Authorization", authorization)
+		w := httptest.NewRecorder()
+		handler.ServeHTTP(w, r)
+
+		assertStatusCode(t, w, http.StatusOK)
+
+		resp := &authResponse{}
+		json.Unmarshal(w.Body.Bytes(), resp)
+
+		expectedResp := &authResponse{
+			Authorized: true,
+			User:       "user",
+		}
+		if !reflect.DeepEqual(resp, expectedResp) {
+			t.Fatalf("expected response %#v, got %#v", expectedResp, resp)
+		}
+	})
 }
 
 func TestGzip(t *testing.T) {