...

Source file src/github.com/docker/distribution/registry/handlers/hmac.go

Documentation: github.com/docker/distribution/registry/handlers

     1  package handlers
     2  
     3  import (
     4  	"crypto/hmac"
     5  	"crypto/sha256"
     6  	"encoding/base64"
     7  	"encoding/json"
     8  	"fmt"
     9  	"time"
    10  )
    11  
    12  // blobUploadState captures the state serializable state of the blob upload.
    13  type blobUploadState struct {
    14  	// name is the primary repository under which the blob will be linked.
    15  	Name string
    16  
    17  	// UUID identifies the upload.
    18  	UUID string
    19  
    20  	// offset contains the current progress of the upload.
    21  	Offset int64
    22  
    23  	// StartedAt is the original start time of the upload.
    24  	StartedAt time.Time
    25  }
    26  
    27  type hmacKey string
    28  
    29  var errInvalidSecret = fmt.Errorf("invalid secret")
    30  
    31  // unpackUploadState unpacks and validates the blob upload state from the
    32  // token, using the hmacKey secret.
    33  func (secret hmacKey) unpackUploadState(token string) (blobUploadState, error) {
    34  	var state blobUploadState
    35  
    36  	tokenBytes, err := base64.URLEncoding.DecodeString(token)
    37  	if err != nil {
    38  		return state, err
    39  	}
    40  	mac := hmac.New(sha256.New, []byte(secret))
    41  
    42  	if len(tokenBytes) < mac.Size() {
    43  		return state, errInvalidSecret
    44  	}
    45  
    46  	macBytes := tokenBytes[:mac.Size()]
    47  	messageBytes := tokenBytes[mac.Size():]
    48  
    49  	mac.Write(messageBytes)
    50  	if !hmac.Equal(mac.Sum(nil), macBytes) {
    51  		return state, errInvalidSecret
    52  	}
    53  
    54  	if err := json.Unmarshal(messageBytes, &state); err != nil {
    55  		return state, err
    56  	}
    57  
    58  	return state, nil
    59  }
    60  
    61  // packUploadState packs the upload state signed with and hmac digest using
    62  // the hmacKey secret, encoding to url safe base64. The resulting token can be
    63  // used to share data with minimized risk of external tampering.
    64  func (secret hmacKey) packUploadState(lus blobUploadState) (string, error) {
    65  	mac := hmac.New(sha256.New, []byte(secret))
    66  	p, err := json.Marshal(lus)
    67  	if err != nil {
    68  		return "", err
    69  	}
    70  
    71  	mac.Write(p)
    72  
    73  	return base64.URLEncoding.EncodeToString(append(mac.Sum(nil), p...)), nil
    74  }
    75  

View as plain text