1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
package data
import (
"crypto/sha256"
"crypto/sha512"
"fmt"
"hash"
"io"
"io/ioutil"
"strings"
"time"
"github.com/Sirupsen/logrus"
"github.com/jfrazelle/go/canonical/json"
)
type KeyAlgorithm string
func (k KeyAlgorithm) String() string {
return string(k)
}
type SigAlgorithm string
func (k SigAlgorithm) String() string {
return string(k)
}
const (
defaultHashAlgorithm = "sha256"
EDDSASignature SigAlgorithm = "eddsa"
RSAPSSSignature SigAlgorithm = "rsapss"
RSAPKCS1v15Signature SigAlgorithm = "rsapkcs1v15"
ECDSASignature SigAlgorithm = "ecdsa"
PyCryptoSignature SigAlgorithm = "pycrypto-pkcs#1 pss"
ED25519Key KeyAlgorithm = "ed25519"
RSAKey KeyAlgorithm = "rsa"
RSAx509Key KeyAlgorithm = "rsa-x509"
ECDSAKey KeyAlgorithm = "ecdsa"
ECDSAx509Key KeyAlgorithm = "ecdsa-x509"
)
var TUFTypes = map[string]string{
CanonicalRootRole: "Root",
CanonicalTargetsRole: "Targets",
CanonicalSnapshotRole: "Snapshot",
CanonicalTimestampRole: "Timestamp",
}
// SetTUFTypes allows one to override some or all of the default
// type names in TUF.
func SetTUFTypes(ts map[string]string) {
for k, v := range ts {
TUFTypes[k] = v
}
}
func ValidTUFType(typ, role string) bool {
if ValidRole(role) {
// All targets delegation roles must have
// the valid type is for targets.
role = CanonicalRole(role)
if role == "" {
// role is unknown and does not map to
// a type
return false
}
if strings.HasPrefix(role, CanonicalTargetsRole+"/") {
role = CanonicalTargetsRole
}
}
// most people will just use the defaults so have this optimal check
// first. Do comparison just in case there is some unknown vulnerability
// if a key and value in the map differ.
if v, ok := TUFTypes[role]; ok {
return typ == v
}
return false
}
type Signed struct {
Signed json.RawMessage `json:"signed"`
Signatures []Signature `json:"signatures"`
}
type SignedCommon struct {
Type string `json:"_type"`
Expires time.Time `json:"expires"`
Version int `json:"version"`
}
type SignedMeta struct {
Signed SignedCommon `json:"signed"`
Signatures []Signature `json:"signatures"`
}
type Signature struct {
KeyID string `json:"keyid"`
Method SigAlgorithm `json:"method"`
Signature []byte `json:"sig"`
}
type Files map[string]FileMeta
type Hashes map[string][]byte
type FileMeta struct {
Length int64 `json:"length"`
Hashes Hashes `json:"hashes"`
Custom json.RawMessage `json:"custom,omitempty"`
}
func NewFileMeta(r io.Reader, hashAlgorithms ...string) (FileMeta, error) {
if len(hashAlgorithms) == 0 {
hashAlgorithms = []string{defaultHashAlgorithm}
}
hashes := make(map[string]hash.Hash, len(hashAlgorithms))
for _, hashAlgorithm := range hashAlgorithms {
var h hash.Hash
switch hashAlgorithm {
case "sha256":
h = sha256.New()
case "sha512":
h = sha512.New()
default:
return FileMeta{}, fmt.Errorf("Unknown Hash Algorithm: %s", hashAlgorithm)
}
hashes[hashAlgorithm] = h
r = io.TeeReader(r, h)
}
n, err := io.Copy(ioutil.Discard, r)
if err != nil {
return FileMeta{}, err
}
m := FileMeta{Length: n, Hashes: make(Hashes, len(hashes))}
for hashAlgorithm, h := range hashes {
m.Hashes[hashAlgorithm] = h.Sum(nil)
}
return m, nil
}
type Delegations struct {
Keys map[string]PublicKey `json:"keys"`
Roles []*Role `json:"roles"`
}
func NewDelegations() *Delegations {
return &Delegations{
Keys: make(map[string]PublicKey),
Roles: make([]*Role, 0),
}
}
// defines number of days in which something should expire
var defaultExpiryTimes = map[string]int{
CanonicalRootRole: 365,
CanonicalTargetsRole: 90,
CanonicalSnapshotRole: 7,
CanonicalTimestampRole: 1,
}
// SetDefaultExpiryTimes allows one to change the default expiries.
func SetDefaultExpiryTimes(times map[string]int) {
for key, value := range times {
if _, ok := defaultExpiryTimes[key]; !ok {
logrus.Errorf("Attempted to set default expiry for an unknown role: %s", key)
continue
}
defaultExpiryTimes[key] = value
}
}
func DefaultExpires(role string) time.Time {
var t time.Time
if t, ok := defaultExpiryTimes[role]; ok {
return time.Now().AddDate(0, 0, t)
}
return t.UTC().Round(time.Second)
}
type unmarshalledSignature Signature
func (s *Signature) UnmarshalJSON(data []byte) error {
uSignature := unmarshalledSignature{}
err := json.Unmarshal(data, &uSignature)
if err != nil {
return err
}
uSignature.Method = SigAlgorithm(strings.ToLower(string(uSignature.Method)))
*s = Signature(uSignature)
return nil
}
|