github.com/code-to-go/safepool.lib@v0.0.0-20221205180519-ee25e63c226e/pool/token.go (about) 1 package pool 2 3 import ( 4 "bytes" 5 "encoding/base64" 6 "encoding/json" 7 "fmt" 8 "strings" 9 10 "github.com/code-to-go/safepool.lib/core" 11 "github.com/code-to-go/safepool.lib/security" 12 ) 13 14 type Token struct { 15 Config Config 16 Host security.Identity 17 } 18 19 func EncodeToken(t Token, guest *security.Identity) (string, error) { 20 tk, err := json.Marshal(Token{ 21 Config: t.Config, 22 Host: t.Host.Public(), 23 }) 24 if core.IsErr(err, "cannot marshal config to token: %v") { 25 return "", err 26 } 27 28 gk := "" 29 if guest != nil { 30 gk, err = guest.Public().Base64() 31 if core.IsErr(err, "invalid guest key: %v") { 32 return "", err 33 } 34 tk, err = security.EcEncrypt(*guest, tk) 35 if core.IsErr(err, "cannot encrypt with guest key: %v") { 36 return "", err 37 } 38 } 39 40 sig, err := security.Sign(t.Host, tk) 41 if core.IsErr(err, "cannot sign with host key: %v") { 42 return "", err 43 } 44 45 return fmt.Sprintf("%s:%s:%s", gk, 46 base64.StdEncoding.EncodeToString(tk), 47 base64.StdEncoding.EncodeToString(sig)), nil 48 49 } 50 51 func DecodeToken(guest *security.Identity, token string) (Token, error) { 52 var t Token 53 parts := strings.Split(token, ":") 54 if len(parts) != 3 { 55 return t, ErrInvalidToken 56 } 57 58 gk, tk64, sig64 := parts[0], parts[1], parts[2] 59 tk, _ := base64.StdEncoding.DecodeString(tk64) 60 sig, _ := base64.StdEncoding.DecodeString(sig64) 61 if gk != "" { 62 g, err := security.IdentityFromBase64(gk) 63 if core.IsErr(err, "cannot decode guest token from base64: %s") { 64 return t, ErrInvalidToken 65 } 66 67 if guest == nil || !bytes.Equal(g.EncryptionKey.Public, guest.EncryptionKey.Public) { 68 core.IsErr(ErrNotAuthorized, "mismatch between guests keys: %v") 69 return t, ErrNotAuthorized 70 } 71 72 tk, err = security.EcDecrypt(*guest, tk) 73 if core.IsErr(err, "cannot decrypt guest token with own key: %s") { 74 return t, ErrInvalidToken 75 } 76 } 77 78 err := json.Unmarshal(tk, &t) 79 if core.IsErr(err, "cannot unmarshal token: %s") { 80 return t, ErrInvalidToken 81 } 82 83 if !security.Verify(t.Host.Id(), tk, sig) { 84 core.IsErr(ErrInvalidSignature, "token has invalid signature: %v") 85 return t, ErrInvalidSignature 86 } 87 88 return t, nil 89 }