Repository navigation
Expand file tree
/
Copy pathdigests.go
More file actions
117 lines (98 loc) · 2.69 KB
/
Copy pathdigests.go
File metadata and controls
117 lines (98 loc) · 2.69 KB
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
// Copyright 2021-2026 Contributors to the Veraison project.
// SPDX-License-Identifier: Apache-2.0
package comid
import (
"bytes"
"fmt"
)
// Digests is an alias for an array of Digest
type Digests []Digest
// NewDigests instantiates an empty array of Digests
func NewDigests() *Digests {
return new(Digests)
}
// AddDigest create a new digest from the supplied arguments and appends it to
// the (already instantiated) Digests target. The method is a no-op if it is
// invoked on a nil target and will refuse to add inconsistent algo/value
// combinations.
func (o *Digests) AddDigest(algID int, value []byte) *Digests {
if o != nil {
*o = append(*o, *NewDigestIntAlg(algID, value))
}
return o
}
func (o Digests) Valid() error {
for i, m := range o {
if err := m.Valid(); err != nil {
return fmt.Errorf("digest at index %d: %w", i, err)
}
}
return nil
}
// Equal confirms if the Digests instances are equal
//
// Two digests are considered to be equal if they meet the following criteria:
// - They contain the same number of elements
// - All the elements that use the same algorithm have the same value,
// though the elements could be in any order
func (o Digests) Equal(r Digests) bool {
om := make(map[DigestAlgorithm][][]byte)
for _, oe := range o {
vs, ok := om[oe.Algorithm]
if ok {
om[oe.Algorithm] = append(vs, oe.Value)
} else {
om[oe.Algorithm] = [][]byte{oe.Value}
}
}
outer:
for _, re := range r {
ovs, ok := om[re.Algorithm]
if !ok {
return false
}
for _, ov := range ovs {
if bytes.Equal(ov, re.Value) {
continue outer
}
}
return false
}
return true
}
// CompareAgainstReference checks if digests object matches with a reference
//
// See the following CoRIM spec for rules to compare
// digests against a reference:
// https://ietf-rats-wg.github.io/draft-ietf-rats-corim/draft-ietf-rats-corim.html#section-8.5.6.1.3
func (o Digests) CompareAgainstReference(r Digests) bool {
result := false
if len(r) == 0 {
return false
}
// Insert the reference values into a map
ref := make(map[DigestAlgorithm][]byte)
for _, digest := range r {
val, ok := ref[digest.Algorithm]
if ok && !bytes.Equal(digest.Value, val) {
// If two entries with the same hashing algorithm have different
// values, that's an automatic false.
return false
}
ref[digest.Algorithm] = digest.Value
}
// Check the object against the reference value map
for _, digest := range o {
val, ok := ref[digest.Algorithm]
if !ok {
continue
}
if !bytes.Equal(digest.Value, val) {
// All hash values must be equal if a claim has the same
// digest represented using multiple algorithms.
return false
}
result = true
}
return result
}