keypairs/jws.go

64 lines
1.5 KiB
Go

package keypairs
import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"strings"
)
// JWS is a parsed JWT, representation as signable/verifiable and human-readable parts
type JWS struct {
Header Object `json:"header"` // JSON
Claims Object `json:"claims"` // JSON
Protected string `json:"protected"` // base64
Payload string `json:"payload"` // base64
Signature string `json:"signature"` // base64
}
// JWSToJWT joins JWS parts into a JWT as {ProtectedHeader}.{SerializedPayload}.{Signature}.
func JWSToJWT(jwt *JWS) string {
return fmt.Sprintf(
"%s.%s.%s",
jwt.Protected,
jwt.Payload,
jwt.Signature,
)
}
// JWTToJWS splits the JWT into its JWS segments
func JWTToJWS(jwt string) (jws *JWS) {
jwt = strings.TrimSpace(jwt)
parts := strings.Split(jwt, ".")
if 3 != len(parts) {
return nil
}
return &JWS{
Protected: parts[0],
Payload: parts[1],
Signature: parts[2],
}
}
// DecodeComponents decodes JWS Header and Claims
func (jws *JWS) DecodeComponents() error {
protected, err := base64.RawURLEncoding.DecodeString(jws.Protected)
if nil != err {
return errors.New("invalid JWS header base64Url encoding")
}
if err := json.Unmarshal([]byte(protected), &jws.Header); nil != err {
return errors.New("invalid JWS header")
}
payload, err := base64.RawURLEncoding.DecodeString(jws.Payload)
if nil != err {
return errors.New("invalid JWS payload base64Url encoding")
}
if err := json.Unmarshal([]byte(payload), &jws.Claims); nil != err {
return errors.New("invalid JWS claims")
}
return nil
}