Add auth/token.go & support code in crypto.go

This commit is contained in:
Drew DeVault 2020-09-12 14:36:55 -04:00
parent f5f498ec5a
commit 6d5b4f7606
2 changed files with 87 additions and 0 deletions

68
auth/token.go Normal file
View File

@ -0,0 +1,68 @@
package auth
import (
"encoding/base64"
"time"
"git.sr.ht/~sircmpwn/go-bare"
"git.sr.ht/~sircmpwn/gql.sr.ht/crypto"
)
const TokenVersion uint = 0
type Timestamp int64
func (t Timestamp) Time() time.Time {
return time.Unix(int64(t), 0)
}
func ToTimestamp(t time.Time) Timestamp {
return Timestamp(t.Unix())
}
type OAuth2Token struct {
Version uint
Expires Timestamp
Scopes string
ClientID string
Username string
}
func (ot *OAuth2Token) Encode() string {
plain, err := bare.Marshal(ot)
if err != nil {
panic(err)
}
mac := crypto.HMAC(plain)
return base64.RawStdEncoding.EncodeToString(append(plain, mac...))
}
func DecodeToken(token string) *OAuth2Token {
payload, err := base64.RawStdEncoding.DecodeString(token)
if err != nil {
return nil
}
if len(payload) <= 32 {
return nil
}
mac := payload[32:]
payload = payload[:32]
if crypto.HMACVerify(payload, mac) == false {
return nil
}
ot := &OAuth2Token{}
err = bare.Unmarshal(payload, &ot)
if err != nil {
return nil
}
if ot.Version != TokenVersion {
return nil
}
if time.Now().UTC().After(ot.Expires.Time()) {
return nil
}
return ot
}

View File

@ -2,6 +2,8 @@ package crypto
import (
"crypto/ed25519"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"log"
"time"
@ -13,6 +15,7 @@ import (
var (
privateKey ed25519.PrivateKey
publicKey ed25519.PublicKey
macKey []byte
fernetKey *fernet.Key
)
@ -36,6 +39,9 @@ func InitCrypto(config ini.File) {
if err != nil {
log.Fatalf("Load Fernet network encryption key: %v", err)
}
mac := hmac.New(sha256.New, privateKey)
mac.Write([]byte("sr.ht HMAC key"))
macKey = mac.Sum(nil)
}
func Sign(payload []byte) []byte {
@ -62,3 +68,16 @@ func Decrypt(payload []byte) []byte {
func DecryptWithExpiration(payload []byte, expiry time.Duration) []byte {
return fernet.VerifyAndDecrypt(payload, expiry, []*fernet.Key{fernetKey})
}
func HMAC(payload []byte) []byte {
mac := hmac.New(sha256.New, macKey)
mac.Write(payload)
return mac.Sum(nil)
}
func HMACVerify(payload []byte, signature []byte) bool {
mac := hmac.New(sha256.New, macKey)
mac.Write(payload)
expected := mac.Sum(nil)
return hmac.Equal(expected, signature)
}