mirror of
https://github.com/containers/skopeo.git
synced 2025-09-10 11:09:47 +00:00
Add support for Fulcio and Rekor, and --sign-by-sigstore=param-file
(skopeo copy) and (skopeo sync) now support --sign-by-sigstore=param-file, using the containers-sigstore-signing-params.yaml(5) file format. That notably adds support for Fulcio and Rekor signing. Signed-off-by: Miloslav Trmač <mitr@redhat.com>
This commit is contained in:
352
vendor/github.com/segmentio/ksuid/ksuid.go
generated
vendored
Normal file
352
vendor/github.com/segmentio/ksuid/ksuid.go
generated
vendored
Normal file
@@ -0,0 +1,352 @@
|
||||
package ksuid
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"database/sql/driver"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// KSUID's epoch starts more recently so that the 32-bit number space gives a
|
||||
// significantly higher useful lifetime of around 136 years from March 2017.
|
||||
// This number (14e8) was picked to be easy to remember.
|
||||
epochStamp int64 = 1400000000
|
||||
|
||||
// Timestamp is a uint32
|
||||
timestampLengthInBytes = 4
|
||||
|
||||
// Payload is 16-bytes
|
||||
payloadLengthInBytes = 16
|
||||
|
||||
// KSUIDs are 20 bytes when binary encoded
|
||||
byteLength = timestampLengthInBytes + payloadLengthInBytes
|
||||
|
||||
// The length of a KSUID when string (base62) encoded
|
||||
stringEncodedLength = 27
|
||||
|
||||
// A string-encoded minimum value for a KSUID
|
||||
minStringEncoded = "000000000000000000000000000"
|
||||
|
||||
// A string-encoded maximum value for a KSUID
|
||||
maxStringEncoded = "aWgEPTl1tmebfsQzFP4bxwgy80V"
|
||||
)
|
||||
|
||||
// KSUIDs are 20 bytes:
|
||||
// 00-03 byte: uint32 BE UTC timestamp with custom epoch
|
||||
// 04-19 byte: random "payload"
|
||||
type KSUID [byteLength]byte
|
||||
|
||||
var (
|
||||
rander = rand.Reader
|
||||
randMutex = sync.Mutex{}
|
||||
randBuffer = [payloadLengthInBytes]byte{}
|
||||
|
||||
errSize = fmt.Errorf("Valid KSUIDs are %v bytes", byteLength)
|
||||
errStrSize = fmt.Errorf("Valid encoded KSUIDs are %v characters", stringEncodedLength)
|
||||
errStrValue = fmt.Errorf("Valid encoded KSUIDs are bounded by %s and %s", minStringEncoded, maxStringEncoded)
|
||||
errPayloadSize = fmt.Errorf("Valid KSUID payloads are %v bytes", payloadLengthInBytes)
|
||||
|
||||
// Represents a completely empty (invalid) KSUID
|
||||
Nil KSUID
|
||||
// Represents the highest value a KSUID can have
|
||||
Max = KSUID{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
|
||||
)
|
||||
|
||||
// Append appends the string representation of i to b, returning a slice to a
|
||||
// potentially larger memory area.
|
||||
func (i KSUID) Append(b []byte) []byte {
|
||||
return fastAppendEncodeBase62(b, i[:])
|
||||
}
|
||||
|
||||
// The timestamp portion of the ID as a Time object
|
||||
func (i KSUID) Time() time.Time {
|
||||
return correctedUTCTimestampToTime(i.Timestamp())
|
||||
}
|
||||
|
||||
// The timestamp portion of the ID as a bare integer which is uncorrected
|
||||
// for KSUID's special epoch.
|
||||
func (i KSUID) Timestamp() uint32 {
|
||||
return binary.BigEndian.Uint32(i[:timestampLengthInBytes])
|
||||
}
|
||||
|
||||
// The 16-byte random payload without the timestamp
|
||||
func (i KSUID) Payload() []byte {
|
||||
return i[timestampLengthInBytes:]
|
||||
}
|
||||
|
||||
// String-encoded representation that can be passed through Parse()
|
||||
func (i KSUID) String() string {
|
||||
return string(i.Append(make([]byte, 0, stringEncodedLength)))
|
||||
}
|
||||
|
||||
// Raw byte representation of KSUID
|
||||
func (i KSUID) Bytes() []byte {
|
||||
// Safe because this is by-value
|
||||
return i[:]
|
||||
}
|
||||
|
||||
// IsNil returns true if this is a "nil" KSUID
|
||||
func (i KSUID) IsNil() bool {
|
||||
return i == Nil
|
||||
}
|
||||
|
||||
// Get satisfies the flag.Getter interface, making it possible to use KSUIDs as
|
||||
// part of of the command line options of a program.
|
||||
func (i KSUID) Get() interface{} {
|
||||
return i
|
||||
}
|
||||
|
||||
// Set satisfies the flag.Value interface, making it possible to use KSUIDs as
|
||||
// part of of the command line options of a program.
|
||||
func (i *KSUID) Set(s string) error {
|
||||
return i.UnmarshalText([]byte(s))
|
||||
}
|
||||
|
||||
func (i KSUID) MarshalText() ([]byte, error) {
|
||||
return []byte(i.String()), nil
|
||||
}
|
||||
|
||||
func (i KSUID) MarshalBinary() ([]byte, error) {
|
||||
return i.Bytes(), nil
|
||||
}
|
||||
|
||||
func (i *KSUID) UnmarshalText(b []byte) error {
|
||||
id, err := Parse(string(b))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*i = id
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *KSUID) UnmarshalBinary(b []byte) error {
|
||||
id, err := FromBytes(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*i = id
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value converts the KSUID into a SQL driver value which can be used to
|
||||
// directly use the KSUID as parameter to a SQL query.
|
||||
func (i KSUID) Value() (driver.Value, error) {
|
||||
if i.IsNil() {
|
||||
return nil, nil
|
||||
}
|
||||
return i.String(), nil
|
||||
}
|
||||
|
||||
// Scan implements the sql.Scanner interface. It supports converting from
|
||||
// string, []byte, or nil into a KSUID value. Attempting to convert from
|
||||
// another type will return an error.
|
||||
func (i *KSUID) Scan(src interface{}) error {
|
||||
switch v := src.(type) {
|
||||
case nil:
|
||||
return i.scan(nil)
|
||||
case []byte:
|
||||
return i.scan(v)
|
||||
case string:
|
||||
return i.scan([]byte(v))
|
||||
default:
|
||||
return fmt.Errorf("Scan: unable to scan type %T into KSUID", v)
|
||||
}
|
||||
}
|
||||
|
||||
func (i *KSUID) scan(b []byte) error {
|
||||
switch len(b) {
|
||||
case 0:
|
||||
*i = Nil
|
||||
return nil
|
||||
case byteLength:
|
||||
return i.UnmarshalBinary(b)
|
||||
case stringEncodedLength:
|
||||
return i.UnmarshalText(b)
|
||||
default:
|
||||
return errSize
|
||||
}
|
||||
}
|
||||
|
||||
// Parse decodes a string-encoded representation of a KSUID object
|
||||
func Parse(s string) (KSUID, error) {
|
||||
if len(s) != stringEncodedLength {
|
||||
return Nil, errStrSize
|
||||
}
|
||||
|
||||
src := [stringEncodedLength]byte{}
|
||||
dst := [byteLength]byte{}
|
||||
|
||||
copy(src[:], s[:])
|
||||
|
||||
if err := fastDecodeBase62(dst[:], src[:]); err != nil {
|
||||
return Nil, errStrValue
|
||||
}
|
||||
|
||||
return FromBytes(dst[:])
|
||||
}
|
||||
|
||||
func timeToCorrectedUTCTimestamp(t time.Time) uint32 {
|
||||
return uint32(t.Unix() - epochStamp)
|
||||
}
|
||||
|
||||
func correctedUTCTimestampToTime(ts uint32) time.Time {
|
||||
return time.Unix(int64(ts)+epochStamp, 0)
|
||||
}
|
||||
|
||||
// Generates a new KSUID. In the strange case that random bytes
|
||||
// can't be read, it will panic.
|
||||
func New() KSUID {
|
||||
ksuid, err := NewRandom()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Couldn't generate KSUID, inconceivable! error: %v", err))
|
||||
}
|
||||
return ksuid
|
||||
}
|
||||
|
||||
// Generates a new KSUID
|
||||
func NewRandom() (ksuid KSUID, err error) {
|
||||
return NewRandomWithTime(time.Now())
|
||||
}
|
||||
|
||||
func NewRandomWithTime(t time.Time) (ksuid KSUID, err error) {
|
||||
// Go's default random number generators are not safe for concurrent use by
|
||||
// multiple goroutines, the use of the rander and randBuffer are explicitly
|
||||
// synchronized here.
|
||||
randMutex.Lock()
|
||||
|
||||
_, err = io.ReadAtLeast(rander, randBuffer[:], len(randBuffer))
|
||||
copy(ksuid[timestampLengthInBytes:], randBuffer[:])
|
||||
|
||||
randMutex.Unlock()
|
||||
|
||||
if err != nil {
|
||||
ksuid = Nil // don't leak random bytes on error
|
||||
return
|
||||
}
|
||||
|
||||
ts := timeToCorrectedUTCTimestamp(t)
|
||||
binary.BigEndian.PutUint32(ksuid[:timestampLengthInBytes], ts)
|
||||
return
|
||||
}
|
||||
|
||||
// Constructs a KSUID from constituent parts
|
||||
func FromParts(t time.Time, payload []byte) (KSUID, error) {
|
||||
if len(payload) != payloadLengthInBytes {
|
||||
return Nil, errPayloadSize
|
||||
}
|
||||
|
||||
var ksuid KSUID
|
||||
|
||||
ts := timeToCorrectedUTCTimestamp(t)
|
||||
binary.BigEndian.PutUint32(ksuid[:timestampLengthInBytes], ts)
|
||||
|
||||
copy(ksuid[timestampLengthInBytes:], payload)
|
||||
|
||||
return ksuid, nil
|
||||
}
|
||||
|
||||
// Constructs a KSUID from a 20-byte binary representation
|
||||
func FromBytes(b []byte) (KSUID, error) {
|
||||
var ksuid KSUID
|
||||
|
||||
if len(b) != byteLength {
|
||||
return Nil, errSize
|
||||
}
|
||||
|
||||
copy(ksuid[:], b)
|
||||
return ksuid, nil
|
||||
}
|
||||
|
||||
// Sets the global source of random bytes for KSUID generation. This
|
||||
// should probably only be set once globally. While this is technically
|
||||
// thread-safe as in it won't cause corruption, there's no guarantee
|
||||
// on ordering.
|
||||
func SetRand(r io.Reader) {
|
||||
if r == nil {
|
||||
rander = rand.Reader
|
||||
return
|
||||
}
|
||||
rander = r
|
||||
}
|
||||
|
||||
// Implements comparison for KSUID type
|
||||
func Compare(a, b KSUID) int {
|
||||
return bytes.Compare(a[:], b[:])
|
||||
}
|
||||
|
||||
// Sorts the given slice of KSUIDs
|
||||
func Sort(ids []KSUID) {
|
||||
quickSort(ids, 0, len(ids)-1)
|
||||
}
|
||||
|
||||
// IsSorted checks whether a slice of KSUIDs is sorted
|
||||
func IsSorted(ids []KSUID) bool {
|
||||
if len(ids) != 0 {
|
||||
min := ids[0]
|
||||
for _, id := range ids[1:] {
|
||||
if bytes.Compare(min[:], id[:]) > 0 {
|
||||
return false
|
||||
}
|
||||
min = id
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func quickSort(a []KSUID, lo int, hi int) {
|
||||
if lo < hi {
|
||||
pivot := a[hi]
|
||||
i := lo - 1
|
||||
|
||||
for j, n := lo, hi; j != n; j++ {
|
||||
if bytes.Compare(a[j][:], pivot[:]) < 0 {
|
||||
i++
|
||||
a[i], a[j] = a[j], a[i]
|
||||
}
|
||||
}
|
||||
|
||||
i++
|
||||
if bytes.Compare(a[hi][:], a[i][:]) < 0 {
|
||||
a[i], a[hi] = a[hi], a[i]
|
||||
}
|
||||
|
||||
quickSort(a, lo, i-1)
|
||||
quickSort(a, i+1, hi)
|
||||
}
|
||||
}
|
||||
|
||||
// Next returns the next KSUID after id.
|
||||
func (id KSUID) Next() KSUID {
|
||||
zero := makeUint128(0, 0)
|
||||
|
||||
t := id.Timestamp()
|
||||
u := uint128Payload(id)
|
||||
v := add128(u, makeUint128(0, 1))
|
||||
|
||||
if v == zero { // overflow
|
||||
t++
|
||||
}
|
||||
|
||||
return v.ksuid(t)
|
||||
}
|
||||
|
||||
// Prev returns the previoud KSUID before id.
|
||||
func (id KSUID) Prev() KSUID {
|
||||
max := makeUint128(math.MaxUint64, math.MaxUint64)
|
||||
|
||||
t := id.Timestamp()
|
||||
u := uint128Payload(id)
|
||||
v := sub128(u, makeUint128(0, 1))
|
||||
|
||||
if v == max { // overflow
|
||||
t--
|
||||
}
|
||||
|
||||
return v.ksuid(t)
|
||||
}
|
Reference in New Issue
Block a user