1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- /*
- Copyright 2016 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package bootstrap
- import (
- "fmt"
- "strings"
- jose "gopkg.in/square/go-jose.v2"
- )
- // computeDetachedSig takes content and token details and computes a detached
- // JWS signature. This is described in Appendix F of RFC 7515. Basically, this
- // is a regular JWS with the content part of the signature elided.
- func computeDetachedSig(content, tokenID, tokenSecret string) (string, error) {
- jwk := &jose.JSONWebKey{
- Key: []byte(tokenSecret),
- KeyID: tokenID,
- }
- opts := &jose.SignerOptions{
- // Since this is a symmetric key, go-jose doesn't automatically include
- // the KeyID as part of the protected header. We have to pass it here
- // explicitly.
- ExtraHeaders: map[jose.HeaderKey]interface{}{
- "kid": tokenID,
- },
- }
- signer, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: jwk}, opts)
- if err != nil {
- return "", fmt.Errorf("can't make a HS256 signer from the given token: %v", err)
- }
- jws, err := signer.Sign([]byte(content))
- if err != nil {
- return "", fmt.Errorf("can't HS256-sign the given token: %v", err)
- }
- fullSig, err := jws.CompactSerialize()
- if err != nil {
- return "", fmt.Errorf("can't serialize the given token: %v", err)
- }
- return stripContent(fullSig)
- }
- // stripContent will remove the content part of a compact JWS
- //
- // The `go-jose` library doesn't support generating signatures with "detached"
- // content. To make up for this we take the full compact signature, break it
- // apart and put it back together without the content section.
- func stripContent(fullSig string) (string, error) {
- parts := strings.Split(fullSig, ".")
- if len(parts) != 3 {
- return "", fmt.Errorf("compact JWS format must have three parts")
- }
- return parts[0] + ".." + parts[2], nil
- }
- // DetachedTokenIsValid checks whether a given detached JWS-encoded token matches JWS output of the given content and token
- func DetachedTokenIsValid(detachedToken, content, tokenID, tokenSecret string) bool {
- newToken, err := computeDetachedSig(content, tokenID, tokenSecret)
- if err != nil {
- return false
- }
- return detachedToken == newToken
- }
|