blob: fe470350652f515f8b4ea165e98213e326222870 [file] [log] [blame]
package digest_auth_client
import (
"crypto/md5"
"crypto/sha256"
"fmt"
"hash"
"io"
"regexp"
"time"
)
type authorization struct {
Algorithm string // unquoted
Cnonce string // quoted
Nc int // unquoted
Nonce string // quoted
Opaque string // quoted
Qop string // unquoted
Realm string // quoted
Response string // quoted
Uri string // quoted
Userhash bool // quoted
Username string // quoted
Username_ string // quoted
}
func newAuthorization(wa *wwwAuthenticate, dr *DigestRequest) (*authorization, error) {
auth := authorization{
Algorithm: wa.Algorithm,
Cnonce: "",
Nc: 1, // TODO
Nonce: wa.Nonce,
Opaque: wa.Opaque,
Qop: "",
Realm: wa.Realm,
Response: "",
Uri: dr.Uri,
Userhash: wa.Userhash,
Username: dr.Username,
Username_: "", // TODO
}
auth.Cnonce = auth.hash(fmt.Sprintf("%d:%s:dfjosbn3kjd01", time.Now().UnixNano(), dr.Username))
if auth.Userhash {
auth.Username = auth.hash(fmt.Sprintf("%s:%s", auth.Username, auth.Realm))
}
auth.Response = auth.computeResponse(wa, dr)
return &auth, nil
}
func (ah *authorization) computeResponse(wa *wwwAuthenticate, dr *DigestRequest) (s string) {
kdSecret := ah.hash(ah.computeA1(wa, dr))
kdData := fmt.Sprintf("%s:%s:%s:%s:%s", ah.Nonce, ah.Nc, ah.Cnonce, ah.Qop, ah.hash(ah.computeA2(wa, dr)))
return ah.hash(fmt.Sprintf("%s:%s", kdSecret, kdData))
}
func (ah *authorization) computeA1(wa *wwwAuthenticate, dr *DigestRequest) string {
if ah.Algorithm == "" || ah.Algorithm == "MD5" || ah.Algorithm == "SHA-256" {
return fmt.Sprintf("%s:%s:%s", ah.Username, ah.Realm, dr.Password)
}
if ah.Algorithm == "MD5-sess" || ah.Algorithm == "SHA-256-sess" {
upHash := ah.hash(fmt.Sprintf("%s:%s:%s", ah.Username, ah.Realm, dr.Password))
return fmt.Sprintf("%s:%s:%s", upHash, ah.Nc)
}
return ""
}
func (ah *authorization) computeA2(wa *wwwAuthenticate, dr *DigestRequest) string {
if matched, _ := regexp.MatchString("auth-int", wa.Qop); matched {
ah.Qop = "auth-int"
return fmt.Sprintf("%s:%s:%s", dr.Method, ah.Uri, ah.hash(dr.Body))
}
if ah.Qop == "auth" || ah.Qop == "" {
ah.Qop = "auth"
return fmt.Sprintf("%s:%s", dr.Method, ah.Uri)
}
return ""
}
func (ah *authorization) hash(a string) (s string) {
var h hash.Hash
if ah.Algorithm == "MD5" || ah.Algorithm == "MD5-sess" {
h = md5.New()
} else if ah.Algorithm == "SHA-256" || ah.Algorithm == "SHA-256-sess" {
h = sha256.New()
}
io.WriteString(h, a)
s = string(h.Sum(nil))
return
}
func (ah *authorization) toString() string {
return ""
}