This repository has been archived by the owner on Oct 18, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
/
X509Guide.txt
3051 lines (2518 loc) · 161 KB
/
X509Guide.txt
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
X.509 Style Guide
=================
Peter Gutmann, pgut001@cs.auckland.ac.nz
October 2000
[This file is frequently cited as a reference on PKI issues, when in fact it
was really intended as X.509 implementation notes meant mostly for
developers, to tell them all the things the standards leave out. If you're
looking for a general overview of PKI that includes most of what's in here
but presented in a more accessible manner, you should use "Everything you
never wanted to know about PKI but have been forced to find out",
http://www.cs.auckland.ac.nz/~pgut001/pubs/pkitutorial.pdf, a less technical
overview aimed at people charged with implementing and deploying the
technology. If you need to know what you're in for when you work with PKI,
this is definitely the one to read. Further PKI information and material can
be found on my home page, http://www.cs.auckland.ac.nz/~pgut001/].
There seems to be a lot of confusion about how to implement and work with X.509
certificates, either because of ASN.1 encoding issues, or because vagueness in
the relevant standards means people end up taking guesses at what some of the
fields are supposed to look like. For this reason I've put together these
guidelines to help in creating software to work with X.509 certificates, PKCS
#10 certification requests, CRLs, and other ASN.1-encoded data types.
I knew a guy who set up his own digital ID heirarchy, could
issue his own certificates, sign his own controls, ran SSL
on his servers, etc. I don't need to pay Verisign a
million bucks a year for keys that expire and expire. I
just need to turn off the friggen [browser warning]
messages.
-- Mark Bondurant, "Creating My Own Digital ID", in
alt.computer.security.
In addition, anyone who has had to work with X.509 has probably experienced
what can best be described as ISO water torture, which involves ploughing
through all sorts of ISO, ANSI, ITU, and IETF standards, amendments, meeting
notes, draft standards, committee drafts, working drafts, and other
work-in-progress documents, some of which are best understood when held
upside-down in front of a mirror (this has lead to people trading hard-to-find
object identifiers and ASN.1 definitions like baseball cards - "I'll swap you
the OID for triple DES in exchange for the latest CRL extensions"). This
document is an attempt at providing a cookbook for certificates which should
give you everything that you can't easily find anywhere else, as well as
comments on what you'd typically expect to find in certificates.
Given humanity's track record with languages, you wonder
why we bother with standards committies
-- Marcus Leech
Since the original X.509 spec is somewhat vague and open-ended, every
non-trivial group which has any reason to work with certificates has to produce
an X.509 profile which nails down many features which are left undefined in
X.509.
You can't be a real country unless you have a beer and an
airline. It helps if you have some kind of a football
team, or some nuclear weapons, but at the very least you
need a beer.
-- Frank Zappa
And an X.509 profile.
-- Me
The difference between a specification (X.509) and a profile is that a
specification doesn't generally set any limitations on combinations what can
and can't appear in various certificate types, while a profile sets various
limitations, for example by requiring that signing and confidentiality keys be
different (the Swedish profile requires this, and the German profile specifies
exclusive use of certificates for digital signatures). The major profiles in
use today are:
PKIX - Internet PKI profile.
FPKI - (US) Federal PKI profile.
MISSI - US DoD profile.
ISO 15782 - Banking - Certificate Management Part 1: Public Key
Certificates.
TeleTrust/MailTrusT - German MailTrusT profile for TeleTrusT (it really is
capitalised that way).
German SigG Profile - Profile to implement the German digital signature law
(the certificate profile SigI is particularly good, providing not just
the usual specification but also examples of each certificate field and
extension including the encoded forms).
ISIS Profile - Another German profile.
Australian Profile - Profile for the Australian PKAF (this may be the same
as DR 98410, which I haven't seen yet).
SS 61 43 31 Electronic ID Certificate - Swedish profile.
FINEID S3 - Finnish profile.
ANX Profile - Automotive Network Exchange profile.
Microsoft Profile - This isn't a real profile, but the software is
widespread enough and nonstandard enough that it constitutes a
significant de facto profile.
No standard or clause in a standard has a divine right of
existence
-- A Microsoft PKI architect explaining Microsoft's
position on standards compliance.
Unfortunately the official profiles tend to work like various monotheistic
religions where you either do what we say or burn in hell (that is, conforming
to one profile generally excludes you from claiming conformance with any others
unless they happen to match exactly). This means that you need to either
create a chameleon-like implementation which can change its behaviour at a
whim, or restrict yourself to a single profile which may not be accepted in
some locales. There is (currently) no way to mark a certificate to indicate
that it should be processed in a manner conformant to a particular profile,
which makes it difficult for a relying party to know how their certificate will
be processed by a particular implementation.
Interoperability Testing. Conclusion: It doesn't work
-- Richard Lampard, CESG, talking about UK government
PKI experiences
Although I've tried to take into account the various "Use of this feature will
result in the immediate demise of all small furry animals in an eight-block
radius"-type warnings contained in various standards documents to find a lowest
common denominator set of rules which should result in the least pain for all
concerned if they're adhered to, the existence of conflicting profiles makes
this a bit difficult. The idea behind the guide is to at least try to present
a "If you do this, you should be OK" set of guidelines, rather than a "You're
theoretically allowed to do this if you can find an implementation which
supports it" feature list.
Finally, the guide contains a (rather lengthy) list of implementation errors,
bugs, and problems to look out for with various certificates and the related
software in order to allow implementors to create workarounds.
The conventions used in the text are:
- All encodings follow the DER unless otherwise noted.
- Most of the formats are ASN.1, or close enough to it to be understandable
(the goal was to make it easily understandable, not perfectly grammatically
correct). Occasionally 15 levels of indirection are cut out to make things
easier to understand.
The resulting type and value of an instance of use of the
new value notation is determined by the value (and the type
of the value) finally assigned to the distinguished local
reference identified by the keyword VALUE, according to the
processing of the macrodefinition for the new type notation
followed by that for the new value notation.
-- ISO 8824:1988, Annex A
Certificate
-----------
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signature BIT STRING
}
The goal of a cert is to identify the holder of the
corresponding private key, in a fashion meaningful to
relying parties.
-- Stephen Kent
By the power vested in me, I now declare this text string
and this bit string 'name' and 'key'. What RSA has joined,
let no man put asunder.
-- Bob Blakley
The encoding of the Certificate may follow the BER rather than the DER. At
least one implementation uses the indefinite-length encoding form for the
SEQUENCE.
TBSCertificate
--------------
The default tagging for certificates varies depending on which standard you're
using. The original X.509v1 definition used the ASN.1 default of explicit
tags, with X.509v3 extensions in a separate module with implicit tags. The
PKIX definition is quite confusing because the ASN.1 definitions in the
appendices use TAGS IMPLICIT but mix in X.509v3 definitions which use explicit
tags. Appendix A has such a mixture of implied implicit and implied explicit
tags that it's not really possible to tell what tagging you're supposed to use.
Appendix B (which first appeared in draft 7, March 1998) is slightly better,
but still confusing in that it starts with TAGS IMPLICIT, but tries to
partially switch to TAGS EXPLICIT for some sections (for example the
TBSCertificate has an 'EXPLICIT' keyword in the definition which is probably
intended to signify that everything within it has explicit tagging, except that
it's not valid ASN.1). The definitions given in the body of the document use
implicit tags, and the definitions of TBSCertificate and and TBSCertList have
both EXPLICIT and IMPLICIT tags present. To resolve this, you can either rely
entirely on Appendix B with the X.509v1 sections moved into a separate section
declared without 'IMPLICIT TAGS', or use the X.509v3 definitions. The SET
definitions consistently use implicit tags.
Zaphod felt he was teetering on the edge of madness and
wondered whether he shouldn't just jump over and have done
with it.
-- Douglas Adams, "The Restaurant at the End of the
Universe"
TBSCertificate ::= SEQUENCE {
version [ 0 ] Version DEFAULT v1(0),
serialNumber CertificateSerialNumber,
signature AlgorithmIdentifier,
issuer Name,
validity Validity,
subject Name,
subjectPublicKeyInfo SubjectPublicKeyInfo,
issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
extensions [ 3 ] Extensions OPTIONAL
}
Version
-------
Version ::= INTEGER { v1(0), v2(1), v3(2) }
This field is used mainly for marketing purposes to claim that software is
X.509v3 compliant (even when it isn't). The default version is v1(0), if the
issuerUniqueID or subjectUniqueID are present than the version must be v2(1) or
v3(2). If extensions are present than the version must be v3(2). An
implementation should target v3 certificates, which is what everyone is moving
towards.
I was to learn later in life that we tend to meet any new
situation by reorganizing: and a wonderful method it can be
for creating the illusion of progress, while producing
confusion, inefficiency and demoralization
-- Petronius Arbiter, ~60 A.D
Note that the version numbers are one less than the actual X.509 version
because in the ASN.1 world you start counting from 0, not 1 (although it's not
necessary to use sequences of integers for version numbers. X.420, for
example, is under the impression that 2 is followed by 22 rather than the more
generally accepted 3).
If your software generates v1 certificates, it's a good idea to actually mark
them as such and not just mark everything as v3 whether it is or not. Although
no standard actually forbids marking a v1 certificate as v3, backwards-
compatibility (as well as truth-in-advertising) considerations would indicate
that a v1 certificate should be marked as such.
SerialNumber
------------
CertificateSerialNumber ::= INTEGER
This should be unique for each certificate issued by a CA (typically a CA will
keep a counter in persistent store somewhere, perhaps a config file under Unix
and in the registry under Windows). A better way is to take the current time
in seconds and subtract some base time like the first time you ran the
software, to keep the numbers manageable. This has the further advantage over
a simple sequential numbering scheme that it doesn't allow tracking of the
number of certificates which have been signed by a CA, which can have nasty
consequences both if various braindamaged government regulation attempts ever
come to fruition, and because by using sequential numbers a CA ends up
revealing just how few certs it's actually signing (at the cost of a cert per
week, the competition can find out exactly how many certs are being issued each
week).
Although this is never mentioned in any standards document, using negative
serial numbers is probably a bit silly (note the caveat about encoding INTEGER
values in the section on SubjectPublicKeyInfo).
Serial numbers aren't necessarily restricted to 32-bit quantitues. For example
the RSADSI Commercial Certification Authority serial number is 0x0241000016,
which is larger than 32 bits, and Verisign seem to like using 128 or 160-bit
hashes as serial numbers. If you're writing certificate-handling code, just
treat the serial number as a blob which happens to be an encoded integer (this
is particularly important for the case of the vendors who have forgotten that
the high bit of an integer is the sign bit, and generate negative serial
numbers for their certificates).
Signature
---------
This rather misnamed field contains the algorithm identifier for the signature
algorithm used by the CA to sign the certificate. There doesn't seem to be
much use for this field, although you should check that the algorithm
identifier matches the one of the signature on the cert (if someone can forge
the signature on the cert then they can also change the inner algorithm
identifier, it's possible that this was included because of some obscure attack
where someone who could convince (broken) signature algorithm A to produce the
same signature value as (secure) algorithm B could change the outer,
unprotected algorithm identifier from B to A, but couldn't change the inner
identifier without invalidating the signature. What this would achieve is
unclear).
Be very careful with your use of Object Identifiers. In many cases there are a
great many OIDs available for the same algorithm, but the exact OID you're
supposed to use varies somewhat.
You see, the conditional modifers depend on certain
variables like the day of the week, the number of players,
chair positions, things like that. [...] There can't be
more than a dozen or two that are pertinent.
-- Robert Asprin, "Little Myth Marker"
Your best bet is to copy the OIDs everyone else uses and/or use the RSADSI or
X9 OIDs (rather than the OSI or OIW or any other type of OID). OTOH if you
want to be proprietary while still pretending to follow a standard, use OSI
OID's which are often underspecified, so you can do pretty much whatever you
want with things like block formatting and padding.
Another pitfall to be aware of is that algorithms which have no parameters have
this specified as a NULL value rather than omitting the parameters field
entirely. The reason for this is that when the 1988 syntax for
AlgorithmIdentifier was translated into the 1997 syntax, the OPTIONAL
associated with the AlgorithmIdentifier parameters got lost. Later it was
recovered via a defect report, but by then everyone thought that algorithm
parameters were mandatory. Because of this the algorithm parameters should be
specified as NULL, regardless of what you read elsewhere.
The trouble is that things *never* get better, they just
stay the same, only more so
-- Terry Pratchett, "Eric"
Name
----
Name ::= SEQUENCE OF RelativeDistinguishedName
RelativeDistinguishedName ::= SET OF AttributeValueAssertion
AttributeValueAssertion ::= SEQUENCE {
attributeType OBJECT IDENTIFIER,
attributeValue ANY
}
This is used to encode that wonderful ISO creation, the Distinguished Name
(DN), a path through an X.500 directory information tree (DIT) which uniquely
identifies everything on earth. Although the RelativeDistinguishedName (RDN)
is given as a SET OF AttributeValueAssertion (AVA) each set should only contain
one element. However you may encounter other people's certs which could
contain more than one AVA per set, there has been a reported sighting of a
certificate which contained more than one element in the SET.
When the X.500 revolution comes, your name will be lined
up against the wall and shot
-- John Gilmore
They can't be read, written, assigned, or routed. Other
than that, they're perfect
-- Marshall Rose
When encoding sets with cardinality > 1, you need to take care to follow the
DER rules which say that they should be ordered by their encoded values
(although ASN.1 says a SET is unordered, the DER adds ordering rules to ensure
it can be encoded in an unambiguous manner). What you need to do is encode
each value in the set, then sort them by the encoded values, and output them
wrapped up in the SET OF encoding,
First things first, but not necessarily in that order.
-- Dr.Who
however your software really shouldn't be producing these sorts of RDN entries.
In theory you don't have to use a Name for the subject name if you don't want
to; there is a subjectAltName extension which allows use of email addresses or
URL's. In theory if you want to do this you can make the Name an empty
sequence and include a subjectAltName extension and mark it critical, but this
will break a lot of implementations. Because it is possible to do this, you
should be prepared to accept a zero-length sequence for the subject name in
version 3 certificates. Since the DN is supposed to encode the location of the
certificate in a DIT, having a null issuer name would mean you couldn't
actually locate the certificate, so CAs will need to use proper DNs. The
S/MIME certificate spec codifies this by requiring that all issuer DNs be non-
null (so only an end-user certificate can have a null DN, and even then it's
not really recommended), and this requirement was back-ported to the PKIX
profile shortly before it was finalised. The reason for requiring issuer DNs
is that S/MIME v2 and several related standards identify certificates by issuer
and serial number, so all CA certificates must contain an issuer DN (S/MIME v3
allows subjectKeyIdentifiers, but they're almost never used).
SET provides an eminently sensible definition for DNs:
Name ::= SEQUENCE SIZE(1..5) OF RelativeDistinguishedName
RelativeDistinguishedName ::= SET SIZE(1) OF AttributeTypeAndValue
AttributeTypeAndValue ::= { OID, C | O | OU | CN }
This means that when you see a SET DN it'll be in a fixed, consistent, and
easy-to-process format (note in particular the fixed maximum size, the
requirement for a single element per AVA, and the restriction to sensible
element types).
Note that the (issuer name, serialNumber (with a possible side order of
issuerUniqueID, issuerAltName, and keyUsage extension)) tuple uniquely
identifies a certificate and can be used as a key to retrieve certificates
from an information store. The subject name alone does not uniquely identify
a certificate because a subject can own multiple certificates.
You would normally expect to find the following types of AVAs in an X.509
certificate, starting from the top:
countryName ::= SEQUENCE { { 2 5 4 6 }, StringType( SIZE( 2 ) ) }
organization ::= SEQUENCE { { 2 5 4 10 }, StringType( SIZE( 1...64 ) ) }
organizationalUnitName
::= SEQUENCE { { 2 5 4 11 }, StringType( SIZE( 1...64 ) ) }
commonName ::= SEQUENCE { { 2 5 4 3 }, StringType( SIZE( 1...64 ) ) }
You might also find:
localityName ::= SEQUENCE { { 2 5 4 7 }, StringType( SIZE( 1...64 ) ) }
stateOrProvinceName
::= SEQUENCE { { 2 5 4 8 }, StringType( SIZE( 1...64 ) ) }
Some profiles require at least some of these AVAs to be present, for example
the German profile requires at least a countryName and commonName, and in some
cases also an organization name. This is a reasonable requirement, as a
minimum you should always include the country and common name.
Finally, you'll frequently also run into:
emailAddress ::= SEQUENCE { { 1 2 840 113549 1 9 1 }, IA5String }
from PKCS #9, although this shouldn't be there.
I can't afford to make exceptions. Once word leaks out that
a pirate has gone soft, people begin to disobey you and
it's nothing but work, work, work all the time
-- The Dread Pirate Roberts, "The Princess Bride"
The reason why oddball components like the emailAddress have no place in a DN
created as per the original X.500 vision is because the whole DN is intended to
be a strictly heirarchical construction specifying a path through a DIT.
Unfortunately the practice adopted by many CAs of tacking on an emailAddress,
an element which has no subordinate relationship to the other components of the
DN, creates a meaningless mishmash which doesn't follow this hierarchical
model. For this reason the ITU defined the GeneralName, which specifically
allows for components such as email addresses, URL's, and other non-DN items.
GeneralNames are discussed in "Extensions" below.
Since the GeneralName provides a proper means of specifying information like
email addresses, your software shouldn't populate DNs with these components,
however for compatibility with legacy implementations you need to be able to
accept existing certificates which contain odd things in the DN. Currently all
mailers appear to be able to handle an rfc822Name in an altName, so storing it
in the correct location shouldn't present any interoperability problems. One
problem with email address handling is that many mailers will accept not only
'J.Random Luser <jrandom@aol.com>' as a valid emailAddress/rfc822Name but will
be equally happy with 'President William Jefferson Clinton <jrandom@aol.com>'.
The former is simply invalid, but the latter can be downright dangerous because
it completely bypasses the stated purpose of email certificates, which is to
identify the other party in an email exchange. Both PKIX and S/MIME explicitly
require that an rfc822Name only contain an RFC 822 addr-spec which is defined
as local-part@domain, so the mailbox form 'Personal Name <local-part@domain>'
isn't allowed (many S/MIME implementations don't enforce this though).
Unfortunately X.509v3 just requires "an Internet electronic mail address
defined in accordance with Internet RFC 822" without tying it down any further,
so it could be either an addr-spec or a mailbox.
Okay, I'm going home to drink moderately and then pass out.
-- Steve Rhoades, "Married with Children"
The countryName is the ISO 3166 code for the country. Noone seems to know how
to specify non-country-aligned organisations, it's possible that 'EU' will be
used at some point but there isn't any way to encode a non-country code
although some organisations have tried using 'INT'. Actually noone really even
knows what a countryName is supposed to refer to (let alone something as
ambiguous as "locality"), for example it could be your place of birth, country
of citizenship, country of current residence, country of incorporation, country
where corporate HQ is located, country of choice for tax and/or jurisdictional
issues, or a number of other possibilities (moving from countryName to
stateOrProvinceName, people in the US military can choose a state as their
official "residence" for tax purposes even if they don't own any property in
that state, and politicians are allowed to run for office in one state while
their wives claim residence and run for office in another state).
The details of the StringType are discussed further down. It's a good idea to
actually limit the string lengths to 64 characters as required by X.520
because, although many implementations will accept longer encoded strings in
certs, some can't manipulate them once they've been decoded by the software,
and you'll run into problems with LDAP as well. This means residents of places
like Taumatawhakatangihangakoauotamateaturipukakapikimaungahoronukupokai-
whenuakitanataha are out of luck when it comes to getting X.509 certs.
Comparing two DNs has its own special problems, and is dealt with in the rather
lengthy "Comparing DNs" section below.
There appears to be some confusion about what format a Name in a certificate
should take.
Insufficient facts always invite danger
-- Spock, "Space Seed"
In theory it should be a full, proper DN, which traces a path through the X.500
DIT, eg:
C=US, L=Area 51, O=Hanger 18, OU=X.500 Standards Designers, CN=John Doe
but since the DIT's usually don't exist, exactly what format the DN should take
seems open to debate. A good guideline to follow is to organize the namespace
around the C, O, OU, and CN attribute types, but this is directed primarily at
corporate structures. You may also need to use ST(ate) and L(ocality) RDNs.
Some implementations seem to let you stuff anything with an OID into a DN,
which is not good.
There is nothing in any of these standards that would
prevent me from including a 1 gigabit MPEG movie of me
playing with my cat as one of the RDN components of the DN
in my certificate.
-- Bob Jueneman on IETF-PKIX
(There is a certificate of this form available from
http://www.cs.auckland.ac.nz/~pgut001/pubs/
{dave_ca|dave}.der, although the MPEG is limited to
just over 1MB)
With a number of organisations moving towards the use of LDAP-based directory
services, it may be that we'll actually see X.500 directories in our lifetime,
Well, it just so happens that your friend here is only
mostly dead. There's a big difference between mostly dead
and all dead. Now, mostly dead is slightly alive.
-- Miracle Max, "The Princess Bride"
which means you should make an attempt to have a valid DN in the certificate.
LDAP uses the RFC 1779 form of DN, which is the opposite endianness to the ISO
9594 form used above:
CN=John Doe, OU=X.500 Standards Designers, O=Hanger 18, L=Area 51, C=US
There are always alternatives
-- Spock, "The Galileo Seven"
In order to work with LDAP implementations, you should ensure you only have a
single AVA per RDN (which also avoids the abovementioned DER-encoding hassle).
As the above text has probably indicated, DNs don't really work - there's no
clear idea of what they should look like, most users don't know about (and
don't want to know about) X.500 and its naming conventions, and as a
consequence of this the DN can end up containing just about anything. At the
moment they seem to be heading in two main directions:
- Public CAs typically set C=CA country, O=CA name, OU=certificate type,
CN=user name
- A small subset of CAs in Europe which issue certs in accordance with
various signature laws and profiles with their own peculiar requirements
can have all sorts of oddities in the DN. You won't run into many of
these in the wild.
- A small subsets of CAs will modify the DN by adding a unique ID value to
the CN to make it a truly Distinguished Name. See the Bugs and
Peculiarities sections for more information on this.
- Private CAs (mostly people or organisations signing their own certs)
typically set any DN fields supported by their software to whatever makes
sense for them (some software requires all fields in the set
{C,O,OU,SP,L,CN} to be filled in, leading to strange or meaningless entries
as people try and guess what a Locality is supposed to be).
Generally you'll only run into certs from public CAs, for which the general
rule is that the cert is identified by the CN and/or email address. Some CAs
issue certs with identical CN's and use the email address to disambiguate them,
others modify the CN to make it unique. The accepted user interface seems to
be to let users search on the CN and/or email address (and sometimes also the
serial number, which doesn't seem terribly useful), display a list of matches,
and let the user pick the cert they want. Probably the best strategy for a
user interface which handles certs is:
if( email address known )
get a cert which matches the email address (any one should do);
elseif( name known )
search for all certs with CN=name;
if( multiple matches )
display email addresses for matched certs to user, let them choose;
else
error;
If you need something unique to use as an identifier (for example for a
database key) and you know your own software (or more generally software which
can do something useful with the identifier) will be used, use an X.500
serialNumber in a subjectAltName directoryName or use a subjectAltName
otherName (which was explicitly created to allow user-defined identifiers).
For internal cert lookups, encode the cert issuer and serial number as a PKCS
#7 issuerAndSerialNumber, hash it down to a fixed size with SHA-1 (you can
either use the full 20 bytes or some convenient truncated form like 64 bits),
and use that to identify the cert. This works because the internal structure
of the DN is irrelevant anyway, and having a fixed-size unique value makes it
very easy to perform a lookup in various data structures (for example the
random hash value generated leads to probabalistically balanced search trees
without requiring any extra effort).
Validity
--------
Validity ::= SEQUENCE {
notBefore UTCTIME,
notAfter UTCTIME
}
This field denotes the time at which you have to pay your CA a renewal fee to
get the certificate reissued. The IETF originally recommended that all times
be expressed in GMT and seconds not be encoded, giving:
YYMMDDHHMMZ
as the time encoding. This provided an unambiguous encoding because a value of
00 seconds was never encoded, which meant that if you read a UTCTime value
generated by an implementation which didn't use seconds and wrote it out again
with an implementation which did, it would have the same encoding because the
00 wouldn't be encoded.
However newer standards (starting with the Defence Messaging System (DMS),
SDN.706), require the format to be:
YYMMDDHHMMSSZ
even if the seconds are 00. The ASN.1 encoding rules were in late 1996 amended
so that seconds are always encoded, with a special note that midnight is
encoded as ...000000Z and not ...240000Z. You should therefore be prepared to
encounter UTCTimes with and without the final 00 seconds field, however all
newer certificates encode 00 seconds. If you read and then write out an
existing object you may need to remember whether the seconds were encoded or
not in the original because adding the 00 will invalidate the signature (this
problem is slowly disappearing as pre-00 certificates expire).
A good workaround for this problem when generating certificates is to ensure
that you never generate a certificate with the seconds set to 00, which means
that even if other software re-encodes your certificate, it can't get the
encoding wrong.
At least one widely-used product generated incorrect non-GMT encodings so you
may want to consider handling the "+/-xxxx" time offset format, but you should
flag it as a decoding error nonetheless.
In coming up with the worlds least efficient machine-readable time encoding
format, the ISO nevertheless decided to forgo the encoding of centuries, a
problem which has been kludged around by redefining the time as UTCTime if the
date is 2049 or ealier, and GeneralizedTime if the date is 2050 or later (the
original plan was to cut over in 2015, but it was felt that moving it back to
2050 would ensure that the designers were either retired or dead by the time
the issue became a serious problem, leaving someone else to take the blame).
To decode a date, if it's UTCTime and the year is less than or equal to 49 it's
20xx, if it's UTCTime and the year is equal to or greater than 50 it's 19xx,
and if it's GeneralizedTime it's encoded properly (but shouldn't really be used
for dates before 2050 because you could run into interoperability problems with
existing software). Yuck.
To make this even more fun, another spec at one time gave the cutover date as
2050/2051 rather than 2049/2050, and allowed GeneralizedTime to be used before
2050 if you felt you could get away with it. It's likely that a lot of
conforming systems will briefly become nonconforming systems in about half a
centuries time, in a kind of security-standards equivalent of the age-old
paradox in which Christians and Moslems will end up in the other side's version
of hell.
Confusion now hath made his masterpiece.
-- Macduff, "Macbeth", II.i.
Another issue to be aware of is the problem of issuer certificates which have a
different validity time than the subject certificates they are used to sign.
Although this isn't specified in any standard, some software requires validity
period nesting, in which the subject validity period lies inside the issuer
validity period. Most software however performs simple pointwise checking in
which it checks whether a cert chain is valid at a certain point in time
(typically the current time). Maintaining the validity nesting requires that a
certain amount of care be used in designing overlapping validity periods
between successive generations of certificates in a hierarchy. Further
complications arise when an existing CA is re-rooted or re-parented (for
example a divisional CA is subordinated to a corporate CA). Australian and New
Zealand readers will appreciate the significance of using the term "re-rooted"
to describe this operation.
Finally, CAs are handling the problem of expiring certificates by reissuing
current ones with the same name and key but different validity periods. In
some cases even CA roots have been reissued with the only different being
extended validity periods. This can result in multiple identical-seeming
certificates being valid at one time (in one case three certificates with the
same DN and key were valid at once). The semantics of these certificates/keys
are unknown. Perhaps Validity could simply be renamed to RenewalFeeDueDate to
reflect its actual usage.
An alternative way to avoid expiry problems is to give the certificate an
expiry date several decades in the future. This is popular for CA certs which
don't require an annual renewal fee.
SubjectPublicKeyInfo
--------------------
This contains the public key, either a SEQUENCE of values or a single INTEGER.
Keep in mind that ASN.1 integers are signed, so if any integers you want to
encode have the high bit set you need to add a single zero octet to the start
of the encoded value to ensure that the high bit isn't mistaken for a sign bit.
In addition you are allowed at most a single 0 byte at the start of an encoded
value (and that only when the high bit is set), if the internal representation
you use contains zero bytes at the start you have to remove them on encoding.
This is a bit of a nuisance when encoding signatures which have INTEGER values,
since you can't tell how big the encoded signature will be without actually
generating it.
UniqueIdentifier
----------------
UniqueIdentifier ::= BITSTRING
These were added in X509v2 to handle the possible reuse of subject and/or
issuer names over time. Their use is deprecated by the IETF, so you shouldn't
generate these in your certificates. If you're writing certificate-handling
code, just treat them as a blob which happens to be an encoded bitstring.
Extensions
----------
Extensions ::= SEQUENCE OF Extension
Extension ::= SEQUENCE {
extnid OBJECT IDENTIFIER,
critical BOOLEAN DEFAULT FALSE,
extnValue OCTETSTRING
}
X.509 certificate extensions are like a LISP property list: an ISO-standardised
place to store crufties. Extensions can consist of key and policy information,
certificate subject and issuer attributes, certificate path constraints, CRL
distribution points, and private extensions.
X.509v3 and the X.509v4 draft contains the ASN.1 formats for the standard V3
Certificate, V2 CRL and V2 CRLEntry extensions. In theory you should be able
to handle all of these, but there are large numbers of them and some may not be
in active use, or may be meaningless in some contexts.
'It's called a shovel,' said the Senior Wrangler. 'I've
seen the gardeners use them. You stick the sharp end in
the ground. Then it gets a bit technical'
-- Terry Pratchett, "Reaper Man"
The extensions are encoded with IMPLICIT tags, it's traditional to specify this
in some other part of the standard which is at least 20 pages away from the
section where the extension is actually defined (but see the comments above
about the mixture of explicit and implicit tags in ASN.1 definitions).
There are a whole series of superseded and deprecated OIDs for extensions,
often going back through several generations. Older software and certificates
(and buggy newer software) will still use obsolete OIDs, any new software
should try and emit attributes tagged with the OID du jour rather than using
deprecated OIDs.
We can break extensions into two types, constraint extensions and informational
extensions. Constraint extensions limit the way in which the key in a
certificate, or the certificate itself, can be used. For example they may
limit the key usage to digital signatures only, or limit the DNs for which a CA
may issue certificates. The most common constraint extensions are basic
constraints, key usage and extended key usage, certificate policies (modified
by policy mappings and policy constraints), and name constraints. In contrast,
informational extensions contain information which may or may not be useful for
certificate users, but which doesn't limit the certificate use in any way. For
example an informational extension may contain additional information which
identifies the CA which issued it. The most common informational extensions
are key identifiers and alternative names.
The processing of these extensions is mostly specified in three different
standards, which means that there are three often subtly incompatible ways to
handle them. In theory, constraint extensions should be enforced religiously,
however the three standards which cover certificates sometimes differ both in
how they specify the interpretation of the critical flag, and how they require
constraint extensions to be enforced.
We could not get it out of our minds that some subtle but
profoundly alien element had been added to the aesthetic
feeling behind the technique.
-- H.P.Lovecraft, "At the Mountains of Madness"
The general idea behind the critical flag is that it is used to protect the
issuing CA against any assumptions made by software which doesn't implement
support for a particular extension (none of the X.509-related standards provide
much of a definition for what a minimally, average, and fully compliant
implementation needs to support, so it's something of a hit and miss
proposition for an implementation to rely on the correct handling of a
particular extension). One commentator has compared the various certificate
contraints as serving as the equivalent of a Miranda warning ("You have the
right to remain silent, you have the right to an attorney, ...") to anyone
using the certificate. Without the critical flag, an issuer who believes that
the information contained in an extension is particularly important has no real
defence if the end users software chooses to ignore the extension.
The original X.509v3 specification requires that a certificate be regarded as
invalid if an unrecognised critical extension is encountered. As for the
extension itself, if it's non-critical you can use whatever interpretation you
choose (that is, the extension is specified as being of an advisory nature
only). This means that if you encounter constraints which require that a key
be used only for digital signatures, you're free to use it for encryption
anyway. If you encounter a key which is marked as being a non-CA key, you can
use it as a CA key anyway. The X.509v3 interpretation of extensions is a bit
like the recommended 130 km/h speed limit on autobahns, the theoretical limit
is 130, you're sitting there doing 180, and you're getting overtaken by
Porsches doing about 250. The problem with the original X.509v3 definitions is
that although they specify the action to take when you don't recognise an
extension, they don't really define the action when you do recognise it. Using
this interpretation, it's mostly pointless including non-critical extensions
because everyone is free to ignore them (for example the text for the keyUsage
extension says that "it is an advisory field and does not imply that usage of
the key is restricted to the purpose indicated", which means that the main
message it conveys is "I want to bloat up the certificate unnecessarily").
The second interpretation of extensions comes from the IETF PKIX profile. Like
X.509v3, this also requires that a certificate be regarded as invalid if an
unrecognised critical extension is encountered. However it seems to imply that
a critical extension must be processed, and probably considers non-critical
extensions to be advisory only. Unfortunately the wording is ambiguous enough
that a number of interpretations exist. Section 4.2 says that "CAs are
required to support <constraint extensions>", but the degree of support is left
open, and what non-CAs are supposed to do isn't specified. The paragraph
which follows this says that implementations "shall recognise extensions",
which doesn't imply any requirement to actually act on what you recognise. Even
the term "process" is somewhat vague, since processing an extension can consist
of popping up a warning dialog with a message which may or may not make sense
to the user, with an optional "Don't display this warning again" checkbox. In
this case the application certainly recognised the extension and arguably even
processed it, but it didn't force compliance with the intent of the extension,
which was probably what was intended by the terms "recognise" and "process".
The third interpretation comes from S/MIME, which requires that implementations
correctly handle a subset of the constraint and informational extensions.
However, as with PKIX, "correctly handle" isn't specified, so it's possible to
"correctly handle" an extension as per X.509v3, as per PKIX (choose the
interpretation you prefer), or as per S/MIME, which leaves the issue open (it
specifies that implementations may include various bits and pieces in their
extensions, but not how they should be enforced). S/MIME seems to place a
slightly different interpretation on the critical flag, limiting its use to the
small subset of extensions which are mentioned in the S/MIME spec, so it's not
possible to add other critical extensions to an S/MIME certificate.
"But it izz written!" bellowed Beelzebub.
"But it might be written differently somewhere else" said
Crowley. "Where you can't read it".
"In bigger letters" said Aziraphale.
"Underlined" Crowley added.
"Twice" suggested Aziraphale.
-- Neil Gaiman and Terry Pratchett, "Good Omens"
Finally, the waters are further muddied by CA policies, which can add their own
spin to the above interpretations. For example the Verisign CPS, section
2.4.3, says that "all persons shall process the extension [...] or else ignore
the extension", which would seem to cover all the bases. Other policies are
somewhat more specific, for example Netscapes certificate extension
specification says that the keyUsage extension can be ignored if it's not
marked critical, but Netscape Navigator does appear to enforce the
basicConstraints extension in most cases.
The whole issue is complicated by the fact that implementations from a large
vendor will reject a certificate which contains critical constraint extensions,
so that even if you interpret the critical flag to mean "this extension must be
enforced" (rather than just "reject this certificate if you don't recognise the
extension"), you can't use it because it will render the certificate unusable.
These implementations provide yet another interpretation of the critical flag,
"reject this certificate if you encounter a critical extension". The same
vendor also has software which ignores the critical flag entirely, making the
software essentially useless to relying parties who can't rely on it to perform
as required (the exact behaviour depends on the software and version, so one
version might reject a certificate with a critical extension while another
would ignore a critical extension).
Zaphod stared at him as if expecting a cuckoo to leap out
of his forehead on a small spring.
-- Douglas Adams, "The Restaurant at the End of the
Universe"
Because of this confusion, it's probably impossible to include a set of
constraint extensions in a certificate which will be handled properly by
different implementations. Because of problems like this, the digital
signature laws of some countries are requiring certification of the software
being used as part of compliance with the law, so that you can't just claim
that your software "supports X.509v3 certificates" (everyone claims this
whether they actually do or not), you actually have to prove that it supports
what's required by the particular countries' laws. If you're in a country
which has digital signature legislation, make sure the software you're using
has been certified to conform to the legal requirements.
The best interpretation of constraint extensions is that if a certificate is
marked as an X.509v3 certificate, constraints should always be enforced. This
includes enforcing implied settings if the extension is missing, so that a
certificate being used in a CA role which has no basicConstraints extension
present should be regarded as being invalid (note however the problem with
PKIX-compliant certificates described later on). However even if one of the
standards is reworded to precisely define extension handling, there are still
plenty of other standards and interpretations which can be used. The only
solution to this would be to include a critical policy extension which requires
that all constraint extensions up and down the cert chain be enforced. Going
back to the autobahn analogy, this mirrors the situation at the Austrian
border, where everyone slows down to the strictly enforced speed limit as soon
as they cross the border.
Currently the only way to include a constraint enforcement extension is to make
it a critical policy extension. This is somewhat unfortunate since including
some other random policy may make the extension unrecognisable, causing it, and
the entire certificate, to be rejected (as usual, what constitutes an
unrecognisable extension is open to debate: if you can process all the fields
in an extension but don't recognise the contents of one of the fields, it's up
to you whether you count this as being unrecognisable or not).
A better alternative would be to define a new extension, enforceConstraints:
enforceConstraints EXTENSION ::= {
SYNTAX EnforceConstraintsSyntax
IDENTIFIED BY id-ce-enforceConstraints
}
EnforceConstraintsSyntax ::= BOOLEAN DEFAULT FALSE
This makes the default setting compatible with the current "do whatever you
feel like" enforcement of extensions. Enforcing constraints is defined as
enforcing all constraints contained in constraint extensions, incuding implied
settings if the extension is missing, as part of the certificate chain
validation process (which means that they should be enforced up and down the
cert chain). Recognising/supporting/handling/<whatever other wording is used
in standards> an extension is defined as processing and acting on all
components of all fields of an extension in a manner which is compliant with
the semantic intent of the extension.
'Where was I?' said Zaphod Beeblebrox the Fourth.
'Pontificating' said Zaphod Beeblebrox.
'Oh yes'.
-- Douglas Adams, "The Restaurant at the End of the
Universe"
Just to mention a further complication with critical extensions, there are
instances in which it's possible to create certificates which are always
regarded as being invalid due to conflicts with extensions. For example a
generation n-1 critical extension might be replaced by a generation n critical
extension, resulting in a mixture of certs with generation n-1 extensions,
generation n-1 and generation n extensions (for compatibility) and (eventually)
generation n extensions only. However until every piece of software is
upgraded, generation n-1 software will be forced to reject all certs with
generation n extensions, even the (supposedly) backwards-compatibile certs with
both generations of extension in them.
'Mr.Beeblebrox, sir', said the insect in awed wonder,
'you're so weird you should be in movies'.
-- Douglas Adams, "The Restaurant at the End of the
Universe"
Key Usage, Extended Key Usage, and Netscape cert-type
X.509 and PKIX use keyUsage and extKeyUsage to select the key to use from a
selection of keys unless the extension is marked critical, in which case it's
treated as a usage restriction. Microsoft claims to support key usage
enforcement, although experimentation with implementations has shown that it's
mostly ignored (see the entry on Microsoft bugs further on). In addition if an
extKeyUsage extension is present, all certificates in the chain up to the CA
root must also support the same extKeyUsage (so that, for example, a general-
purpose CA can't sign a server gated crypto certificate - the reasoning behind
this is obvious). As it turns out though, extKeyUsage seems to be mostly
ignored just like keyUsage.
Netscape uses keyUsage as a key selection mechanism, and uses the Netscape
cert-type extension in a complex manner described in the Netscape certificate
extension specification. Since the cert-type extension includes the equivalent
of the basicConstraints CA flag, it's possible to specify some types of CA with
the cert-type extension. If you do this, you should be careful to synchronise
the basicConstraints CA flag with the setting of the cert-type extension
because some implementations (you can probably guess which one) will allow a
Netscape CA-like usage to override a non-CA keyUsage value, treating the
certificate as if it were a CA certificate. In addition Netscape also enforces
the same extKeyUsage chaining as Microsoft.
Unfortunately the extKeyUsage chaining interpretation is wrong according to
PKIX, since the settings apply to the key in the certificate (ie the CA's key)
rather than the keys in the certificates it issues. In other words an
extKeyUsage of emailProtection would indicate that the CA's certificate is
intended for S/MIME encryption, not that the CA can issue S/MIME certificates.
Both of the major implementators of certificate-handling software use the
chaining interpretation, but there also exist implementations which use the
PKIX interpretation, so the two main camps will fail to verify the other side's
cert chains unless they're in the (smaller) third camp which just ignores
extKeyUsage.
For keyUsage there is much disagreement over the use of the digitalSignature
and nonRepuduation bits since there was no clear definition in X.509 of when
the nonrepudiation flag should be used alongside or in place of the digital
signature flag. One school of thought holds that digitalSignature should be
used for ephemeral authentication (something which occurs automatically and
frequently) and nonRepuduation for legally binding long-term signatures
(something which is performed consciously and less frequently). Another school
of thought holds that nonRepuduation should act as an additional function for
the digitalSignature mechanism, with digitalSignature being a mechanism bit and
nonRepuduation being a service bit. The different profiles are split roughly
50:50 on this, with some complicating things by specifying that both bits
should be set but the certificate not be used for one or the other purpose.
Probably the best usage is to use digitalSignature for "digital signature for
authentication purposes" and nonRepudiation for "digital signature for
nonrepudiation purposes".
"I think" said the Metatron, "that I shall need to seek
further instructions".
"I alzzo" said Beelzebub.
-- Neil Gaiman and Terry Pratchett, "Good Omens"
In terms of profiles, MISSI and FPKI follow the above recommendation, PKIX uses
nonRepudiation strictly for nonrepudiation and digitalSignature for everything
else, ISO uses digitalSignature for entity authentication and nonRepudiation
strictly for nonrepudiation (leaving digital signatures for data authentication
without nonrepudiation hanging), and others use something in between. When
this issue was debated on PKI lists in mid-1998, over 100 messages were
exchanged without anyone really being able to uncontestably define what
digitalSignature and nonRepudiation really signified. The issue is further
confused by the fact that noone can agree on what the term "nonRepudiation"
actually means, exemplified by a ~200-message debate in mid-1999 which couldn't
reach any useful conclusion.
He had attached the correct colour-coded wires to the
correct pins; he'd checked that it was the right amperage
fuse; he'd screwed it all back together. So far, no
problems. He plugged it into the socket. Then he switched