Updated the README
Added new security layers
This commit is contained in:
78
internal/auth/gc2.go
Normal file
78
internal/auth/gc2.go
Normal file
@@ -0,0 +1,78 @@
|
||||
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])
|
||||
}
|
Reference in New Issue
Block a user