Skip to content

Instantly share code, notes, and snippets.

@kolo
Created July 23, 2015 05:56
Show Gist options
  • Save kolo/88499534f4b461c40ec5 to your computer and use it in GitHub Desktop.
Save kolo/88499534f4b461c40ec5 to your computer and use it in GitHub Desktop.
digest implementation for http digest authentication
package main
import (
"crypto/md5"
"fmt"
"strings"
)
type digest struct {
username string
password string
realm string
uri string
method string
nonce string
nc int
cnonce string
qop string
opaque string
}
func (d *digest) ha1() string {
s := strings.Join([]string{d.username, d.realm, d.password}, ":")
return fmt.Sprintf("%x", md5.Sum([]byte(s)))
}
func (d *digest) ha2() string {
s := strings.Join([]string{d.method, d.uri}, ":")
return fmt.Sprintf("%x", md5.Sum([]byte(s)))
}
func (d *digest) response() string {
s := strings.Join([]string{d.ha1(), d.nonce, fmt.Sprintf("%08x", d.nc), d.cnonce, d.qop, d.ha2()}, ":")
return fmt.Sprintf("%x", md5.Sum([]byte(s)))
}
func (d *digest) String() string {
params := map[string]string{
"username": fmt.Sprintf("%q", d.username),
"realm": fmt.Sprintf("%q", d.realm),
"nonce": fmt.Sprintf("%q", d.nonce),
"uri": fmt.Sprintf("%q", d.uri),
"qop": d.qop,
"nc": fmt.Sprintf("%08x", d.nc),
"cnonce": fmt.Sprintf("%q", d.cnonce),
"response": fmt.Sprintf("%q", d.response()),
"opaque": fmt.Sprintf("%q", d.opaque),
}
values := []string{}
for k, v := range params {
values = append(values, fmt.Sprintf("%s=%s", k, v))
}
return strings.Join(values, ", ")
}
func (d *digest) Header() string {
return fmt.Sprintf("Digest %s", d.String())
}
func parseDigest(v string) map[string]string {
params := map[string]string{}
t := strings.SplitN(v, " ", 2)
if len(t) < 2 {
return params
}
for _, p := range strings.Split(t[1], ",") {
t := strings.SplitN(p, "=", 2)
if len(t) == 2 {
params[strings.TrimSpace(t[0])] = strings.Trim(t[1], "\" ")
}
}
return params
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment