79 lines
1.9 KiB
Go
79 lines
1.9 KiB
Go
package auth
|
|
|
|
import (
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Claims struct {
|
|
Sub string `json:"sub"` // account ID (acc_…)
|
|
Exp int64 `json:"exp"` // unix seconds
|
|
Nbf int64 `json:"nbf,omitempty"` // not before
|
|
Iss string `json:"iss,omitempty"` // greencoast
|
|
Aud string `json:"aud,omitempty"` // api
|
|
Jti string `json:"jti,omitempty"` // token id (optional)
|
|
CNF string `json:"cnf,omitempty"` // key binding: "p256:<b64raw>" or "ed25519:<b64raw>"
|
|
}
|
|
|
|
func MintGC2(signKey []byte, c Claims) (string, error) {
|
|
if len(signKey) == 0 {
|
|
return "", errors.New("sign key missing")
|
|
}
|
|
if c.Sub == "" || c.Exp == 0 {
|
|
return "", errors.New("claims incomplete")
|
|
}
|
|
body, _ := json.Marshal(c)
|
|
mac := hmac.New(sha256.New, signKey)
|
|
mac.Write(body)
|
|
sig := mac.Sum(nil)
|
|
return "gc2." + base64.RawURLEncoding.EncodeToString(body) + "." + base64.RawURLEncoding.EncodeToString(sig), nil
|
|
}
|
|
|
|
func VerifyGC2(signKey []byte, tok string, now time.Time) (Claims, error) {
|
|
var zero Claims
|
|
if !strings.HasPrefix(tok, "gc2.") {
|
|
return zero, errors.New("bad prefix")
|
|
}
|
|
parts := strings.Split(tok, ".")
|
|
if len(parts) != 3 {
|
|
return zero, errors.New("bad parts")
|
|
}
|
|
body, err := base64.RawURLEncoding.DecodeString(parts[1])
|
|
if err != nil {
|
|
return zero, err
|
|
}
|
|
want, err := base64.RawURLEncoding.DecodeString(parts[2])
|
|
if err != nil {
|
|
return zero, err
|
|
}
|
|
mac := hmac.New(sha256.New, signKey)
|
|
mac.Write(body)
|
|
if !hmac.Equal(want, mac.Sum(nil)) {
|
|
return zero, errors.New("bad sig")
|
|
}
|
|
var c Claims
|
|
if err := json.Unmarshal(body, &c); err != nil {
|
|
return zero, err
|
|
}
|
|
t := now.Unix()
|
|
if c.Nbf != 0 && t < c.Nbf {
|
|
return zero, errors.New("nbf")
|
|
}
|
|
if t > c.Exp {
|
|
return zero, errors.New("expired")
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
func AccountIDFromPub(raw []byte) string {
|
|
// acc_<first32 hex of sha256(pub)>
|
|
sum := sha256.Sum256(raw)
|
|
return "acc_" + hex.EncodeToString(sum[:16])
|
|
}
|