mirror of https://github.com/dirtbags/moth.git
52 lines
1.3 KiB
Go
52 lines
1.3 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"log"
|
|
"strings"
|
|
)
|
|
|
|
// HmacResolverSeparator is the string used to separater username from hmac
|
|
const HmacResolverSeparator = "::"
|
|
|
|
// HmacResolver resolves usernames using SHA256 HMAC
|
|
type HmacResolver struct {
|
|
key string
|
|
}
|
|
|
|
// Resolve resolves usernames using HMAC.
|
|
//
|
|
// User strings are expected to be the concatenation of:
|
|
// desired username, HmacResolverSeparator, MAC
|
|
//
|
|
// If there is no separator, the correct user string is computed and printed to the log.
|
|
// So you can use this to compute the correct usernames.
|
|
func (h *HmacResolver) Resolve(event string, user string) (string, error) {
|
|
userparts := strings.Split(user, HmacResolverSeparator)
|
|
username := userparts[0]
|
|
|
|
mac := hmac.New(sha256.New, []byte(h.key))
|
|
fmt.Fprint(mac, event)
|
|
fmt.Fprint(mac, user)
|
|
expectedMAC := mac.Sum(nil)
|
|
|
|
if len(userparts) == 1 {
|
|
expectedEnc := base64.URLEncoding.EncodeToString(expectedMAC)
|
|
log.Printf("Authenticated username: %s%s%s", username, HmacResolverSeparator, expectedEnc)
|
|
return "", fmt.Errorf("No authentication provided")
|
|
}
|
|
givenMAC, err := base64.URLEncoding.DecodeString(userparts[1])
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if hmac.Equal(givenMAC, expectedMAC) {
|
|
return username, nil
|
|
}
|
|
|
|
return "", fmt.Errorf("Authentication failed")
|
|
}
|