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