1
2
3
4
5
6
7 package pkix
8
9 import (
10 "encoding/asn1"
11 "encoding/hex"
12 "fmt"
13 "math/big"
14 "strings"
15 "time"
16 )
17
18
19
20 type AlgorithmIdentifier struct {
21 Algorithm asn1.ObjectIdentifier
22 Parameters asn1.RawValue `asn1:"optional"`
23 }
24
25 type RDNSequence []RelativeDistinguishedNameSET
26
27 var attributeTypeNames = map[string]string{
28 "2.5.4.6": "C",
29 "2.5.4.10": "O",
30 "2.5.4.11": "OU",
31 "2.5.4.3": "CN",
32 "2.5.4.5": "SERIALNUMBER",
33 "2.5.4.7": "L",
34 "2.5.4.8": "ST",
35 "2.5.4.9": "STREET",
36 "2.5.4.17": "POSTALCODE",
37 }
38
39
40
41 func (r RDNSequence) String() string {
42 var buf strings.Builder
43 for i := 0; i < len(r); i++ {
44 rdn := r[len(r)-1-i]
45 if i > 0 {
46 buf.WriteByte(',')
47 }
48 for j, tv := range rdn {
49 if j > 0 {
50 buf.WriteByte('+')
51 }
52
53 oidString := tv.Type.String()
54 typeName, ok := attributeTypeNames[oidString]
55 if !ok {
56 derBytes, err := asn1.Marshal(tv.Value)
57 if err == nil {
58 buf.WriteString(oidString)
59 buf.WriteString("=#")
60 buf.WriteString(hex.EncodeToString(derBytes))
61 continue
62 }
63
64 typeName = oidString
65 }
66
67 valueString := fmt.Sprint(tv.Value)
68 escaped := make([]rune, 0, len(valueString))
69
70 for k, c := range valueString {
71 escape := false
72
73 switch c {
74 case ',', '+', '"', '\\', '<', '>', ';':
75 escape = true
76
77 case ' ':
78 escape = k == 0 || k == len(valueString)-1
79
80 case '#':
81 escape = k == 0
82 }
83
84 if escape {
85 escaped = append(escaped, '\\', c)
86 } else {
87 escaped = append(escaped, c)
88 }
89 }
90
91 buf.WriteString(typeName)
92 buf.WriteByte('=')
93 buf.WriteString(string(escaped))
94 }
95 }
96
97 return buf.String()
98 }
99
100 type RelativeDistinguishedNameSET []AttributeTypeAndValue
101
102
103
104 type AttributeTypeAndValue struct {
105 Type asn1.ObjectIdentifier
106 Value any
107 }
108
109
110
111 type AttributeTypeAndValueSET struct {
112 Type asn1.ObjectIdentifier
113 Value [][]AttributeTypeAndValue `asn1:"set"`
114 }
115
116
117
118 type Extension struct {
119 Id asn1.ObjectIdentifier
120 Critical bool `asn1:"optional"`
121 Value []byte
122 }
123
124
125
126
127
128 type Name struct {
129 Country, Organization, OrganizationalUnit []string
130 Locality, Province []string
131 StreetAddress, PostalCode []string
132 SerialNumber, CommonName string
133
134
135
136
137
138 Names []AttributeTypeAndValue
139
140
141
142
143 ExtraNames []AttributeTypeAndValue
144 }
145
146
147
148
149 func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
150 for _, rdn := range *rdns {
151 if len(rdn) == 0 {
152 continue
153 }
154
155 for _, atv := range rdn {
156 n.Names = append(n.Names, atv)
157 value, ok := atv.Value.(string)
158 if !ok {
159 continue
160 }
161
162 t := atv.Type
163 if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 {
164 switch t[3] {
165 case 3:
166 n.CommonName = value
167 case 5:
168 n.SerialNumber = value
169 case 6:
170 n.Country = append(n.Country, value)
171 case 7:
172 n.Locality = append(n.Locality, value)
173 case 8:
174 n.Province = append(n.Province, value)
175 case 9:
176 n.StreetAddress = append(n.StreetAddress, value)
177 case 10:
178 n.Organization = append(n.Organization, value)
179 case 11:
180 n.OrganizationalUnit = append(n.OrganizationalUnit, value)
181 case 17:
182 n.PostalCode = append(n.PostalCode, value)
183 }
184 }
185 }
186 }
187 }
188
189 var (
190 oidCountry = []int{2, 5, 4, 6}
191 oidOrganization = []int{2, 5, 4, 10}
192 oidOrganizationalUnit = []int{2, 5, 4, 11}
193 oidCommonName = []int{2, 5, 4, 3}
194 oidSerialNumber = []int{2, 5, 4, 5}
195 oidLocality = []int{2, 5, 4, 7}
196 oidProvince = []int{2, 5, 4, 8}
197 oidStreetAddress = []int{2, 5, 4, 9}
198 oidPostalCode = []int{2, 5, 4, 17}
199 )
200
201
202
203
204
205 func (n Name) appendRDNs(in RDNSequence, values []string, oid asn1.ObjectIdentifier) RDNSequence {
206 if len(values) == 0 || oidInAttributeTypeAndValue(oid, n.ExtraNames) {
207 return in
208 }
209
210 s := make([]AttributeTypeAndValue, len(values))
211 for i, value := range values {
212 s[i].Type = oid
213 s[i].Value = value
214 }
215
216 return append(in, s)
217 }
218
219
220
221
222
223
224
225
226
227
228
229
230
231 func (n Name) ToRDNSequence() (ret RDNSequence) {
232 ret = n.appendRDNs(ret, n.Country, oidCountry)
233 ret = n.appendRDNs(ret, n.Province, oidProvince)
234 ret = n.appendRDNs(ret, n.Locality, oidLocality)
235 ret = n.appendRDNs(ret, n.StreetAddress, oidStreetAddress)
236 ret = n.appendRDNs(ret, n.PostalCode, oidPostalCode)
237 ret = n.appendRDNs(ret, n.Organization, oidOrganization)
238 ret = n.appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit)
239 if len(n.CommonName) > 0 {
240 ret = n.appendRDNs(ret, []string{n.CommonName}, oidCommonName)
241 }
242 if len(n.SerialNumber) > 0 {
243 ret = n.appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber)
244 }
245 for _, atv := range n.ExtraNames {
246 ret = append(ret, []AttributeTypeAndValue{atv})
247 }
248
249 return ret
250 }
251
252
253
254 func (n Name) String() string {
255 var rdns RDNSequence
256
257
258 if n.ExtraNames == nil {
259 for _, atv := range n.Names {
260 t := atv.Type
261 if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 {
262 switch t[3] {
263 case 3, 5, 6, 7, 8, 9, 10, 11, 17:
264
265 continue
266 }
267 }
268
269
270 rdns = append(rdns, []AttributeTypeAndValue{atv})
271 }
272 }
273 rdns = append(rdns, n.ToRDNSequence()...)
274 return rdns.String()
275 }
276
277
278
279 func oidInAttributeTypeAndValue(oid asn1.ObjectIdentifier, atv []AttributeTypeAndValue) bool {
280 for _, a := range atv {
281 if a.Type.Equal(oid) {
282 return true
283 }
284 }
285 return false
286 }
287
288
289
290
291
292
293 type CertificateList struct {
294 TBSCertList TBSCertificateList
295 SignatureAlgorithm AlgorithmIdentifier
296 SignatureValue asn1.BitString
297 }
298
299
300 func (certList *CertificateList) HasExpired(now time.Time) bool {
301 return !now.Before(certList.TBSCertList.NextUpdate)
302 }
303
304
305
306
307
308 type TBSCertificateList struct {
309 Raw asn1.RawContent
310 Version int `asn1:"optional,default:0"`
311 Signature AlgorithmIdentifier
312 Issuer RDNSequence
313 ThisUpdate time.Time
314 NextUpdate time.Time `asn1:"optional"`
315 RevokedCertificates []RevokedCertificate `asn1:"optional"`
316 Extensions []Extension `asn1:"tag:0,optional,explicit"`
317 }
318
319
320
321 type RevokedCertificate struct {
322 SerialNumber *big.Int
323 RevocationTime time.Time
324 Extensions []Extension `asn1:"optional"`
325 }
326
View as plain text