-
Notifications
You must be signed in to change notification settings - Fork 0
/
Certificate.go
170 lines (124 loc) · 3.75 KB
/
Certificate.go
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
package hippo
import (
"encoding/base64"
"encoding/json"
"fmt"
)
// ErrNoDeclarations is returned when loading an empty certificate.
var ErrNoDeclarations = fmt.Errorf("No declarations in certificate")
// Subject associates a string identifier for some entity with its
// public key.
type Subject struct {
ID string
PublicKey PublicKey
}
// Testament captures an assertion about a given subject.
type Testament struct {
ID string // An optional identifier for this particular testament.
Subject Subject // The subject of this assertion.
Claims Claims // Arbitrary claims made about the subject, other than its identity.
Expires string // Timepoint after which this Testament is to be considered invalid.
}
// Claims capture arbitrary key/value data.
type Claims map[string]interface{}
// Declaration binds an encoded Testament to a signature.
type Declaration struct {
Claim string // Encoded Testament.
Signer string // Optional identifier of the signer.
Signature Signature // Cryptographic signature of the Claim.
}
// Chain is a list of Declarations
type Chain []*Declaration
// Certificate is simply a Chain. It is encapsulated in the struct to
// ease some handling for serialization and other tasks, as well as
// possible future expansion to include other data.
type Certificate struct {
Declarations Chain // All of the encoded and signed Testaments contained in this certificate.
}
// CertificateFromFile loads and parses a Certificate from the given
// file. It does not verify the certificate.
func CertificateFromFile(fn string) (*Certificate, error) {
var cert Certificate
err := fromFile(fn, &cert)
if err != nil {
return nil, err
}
if len(cert.Declarations) <= 0 {
return nil, ErrNoDeclarations
}
return &cert, nil
}
// CertificateFromBytes parses a Certificate from the given bytes. It
// does not verify the certificate.
func CertificateFromBytes(buf []byte) (*Certificate, error) {
var cert Certificate
err := fromBytes(buf, &cert)
if err != nil {
return nil, err
}
if len(cert.Declarations) <= 0 {
return nil, ErrNoDeclarations
}
return &cert, nil
}
// ToFile serializes the Certificate to the given file as JSON.
func (c *Certificate) ToFile(fn string) error {
return toFile(c, fn)
}
// ToBytes serializes the Certificate to bytes as JSON.
func (c *Certificate) ToBytes() ([]byte, error) {
return toBytes(c)
}
// NewTestament generates a Testament for the subject and claims.
func NewTestament(subjectID string, subjectkey PublicKey, claims Claims) *Testament {
x := new(Testament)
x.Subject.ID = subjectID
x.Subject.PublicKey = subjectkey
if claims == nil {
x.Claims = make(Claims)
} else {
x.Claims = claims
}
return x
}
// UnpackTestament parses a Testament from a JSON Base64-URL encoded
// string.
func UnpackTestament(b64 string) (*Testament, error) {
bytes, err := base64.URLEncoding.DecodeString(b64)
if err != nil {
return nil, err
}
var testament Testament
err = json.Unmarshal(bytes, &testament)
if err != nil {
return nil, err
}
return &testament, nil
}
// Sign uses the given credentials to generate a Declaration,
// encapsulating the signer identity and a JSON Base64-URL encoding of
// the Testament.
func (x *Testament) Sign(id string, signer Signer) (*Declaration, error) {
b64, err := x.Base64()
if err != nil {
return nil, err
}
signature, err := signer.Sign([]byte(b64))
if err != nil {
return nil, err
}
declaration := &Declaration{
Claim: b64,
Signer: id,
Signature: signature,
}
return declaration, nil
}
// Base64 encodes the Testament as a JSON Base64-URL encoded string.
func (x *Testament) Base64() (string, error) {
j, err := json.Marshal(x)
if err != nil {
return "", err
}
return base64.URLEncoding.EncodeToString(j), nil
}