commit
e5c2e378a2
@ -1,49 +0,0 @@
|
||||
// Copyright 2017 clair 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 token implements encryption/decryption for json encoded interfaces
|
||||
package token
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/fernet/fernet-go"
|
||||
)
|
||||
|
||||
// Unmarshal decrypts a token using provided key
|
||||
// and decode the result into interface.
|
||||
func Unmarshal(token string, key string, v interface{}) error {
|
||||
k, _ := fernet.DecodeKey(key)
|
||||
msg := fernet.VerifyAndDecrypt([]byte(token), time.Hour, []*fernet.Key{k})
|
||||
if msg == nil {
|
||||
return errors.New("invalid or expired pagination token")
|
||||
}
|
||||
|
||||
return json.NewDecoder(bytes.NewBuffer(msg)).Decode(&v)
|
||||
}
|
||||
|
||||
// Marshal encodes an interface into json bytes and encrypts it.
|
||||
func Marshal(v interface{}, key string) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
err := json.NewEncoder(&buf).Encode(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
k, _ := fernet.DecodeKey(key)
|
||||
return fernet.EncryptAndSign(buf.Bytes(), k)
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
// Copyright 2018 clair 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 pagination implements a series of utilities for dealing with
|
||||
// paginating lists of objects for an API.
|
||||
package pagination
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/fernet/fernet-go"
|
||||
)
|
||||
|
||||
// ErrInvalidToken is returned when a token fails to Unmarshal because it was
|
||||
// invalid or expired.
|
||||
var ErrInvalidToken = errors.New("invalid or expired pagination token")
|
||||
|
||||
// ErrInvalidKeyString is returned when the string representing a key is malformed.
|
||||
var ErrInvalidKeyString = errors.New("invalid pagination key string: must be 32-byte URL-safe base64")
|
||||
|
||||
// Key represents the key used to cryptographically secure the token
|
||||
// being used to keep track of pages.
|
||||
type Key struct {
|
||||
fkey *fernet.Key
|
||||
}
|
||||
|
||||
// Token represents an opaque pagination token keeping track of a user's
|
||||
// progress iterating through a list of results.
|
||||
type Token string
|
||||
|
||||
// FirstPageToken is used to represent the first page of content.
|
||||
var FirstPageToken = Token("")
|
||||
|
||||
// NewKey generates a new random pagination key.
|
||||
func NewKey() (k Key, err error) {
|
||||
k.fkey = new(fernet.Key)
|
||||
err = k.fkey.Generate()
|
||||
return k, err
|
||||
}
|
||||
|
||||
// KeyFromString creates the key for a given string.
|
||||
//
|
||||
// Strings must be 32-byte URL-safe base64 representations of the key bytes.
|
||||
func KeyFromString(keyString string) (k Key, err error) {
|
||||
var fkey *fernet.Key
|
||||
fkey, err = fernet.DecodeKey(keyString)
|
||||
if err != nil {
|
||||
return Key{}, ErrInvalidKeyString
|
||||
}
|
||||
return Key{fkey}, err
|
||||
}
|
||||
|
||||
// Must is a helper that wraps calls returning a Key and and error and panics
|
||||
// if the error is non-nil.
|
||||
func Must(k Key, err error) Key {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return k
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer interface for Key.
|
||||
func (k Key) String() string {
|
||||
return k.fkey.Encode()
|
||||
}
|
||||
|
||||
// MarshalToken encodes an interface into JSON bytes and produces a Token.
|
||||
func (k Key) MarshalToken(v interface{}) (Token, error) {
|
||||
var buf bytes.Buffer
|
||||
err := json.NewEncoder(&buf).Encode(v)
|
||||
if err != nil {
|
||||
return Token(""), err
|
||||
}
|
||||
|
||||
tokenBytes, err := fernet.EncryptAndSign(buf.Bytes(), k.fkey)
|
||||
return Token(tokenBytes), err
|
||||
}
|
||||
|
||||
// UnmarshalToken decrypts a Token using provided key and decodes the result
|
||||
// into the provided interface.
|
||||
func (k Key) UnmarshalToken(t Token, v interface{}) error {
|
||||
msg := fernet.VerifyAndDecrypt([]byte(t), time.Hour, []*fernet.Key{k.fkey})
|
||||
if msg == nil {
|
||||
return ErrInvalidToken
|
||||
}
|
||||
|
||||
return json.NewDecoder(bytes.NewBuffer(msg)).Decode(&v)
|
||||
}
|
Loading…
Reference in new issue