2 // X509CertificateBuilder.cs: Handles building of X.509 certificates.
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 // (C) 2004 Novell (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System
.Security
.Cryptography
;
35 namespace Mono
.Security
.X509
{
38 * Certificate ::= SEQUENCE {
39 * tbsCertificate TBSCertificate,
40 * signatureAlgorithm AlgorithmIdentifier,
41 * signature BIT STRING
43 * TBSCertificate ::= SEQUENCE {
44 * version [0] Version DEFAULT v1,
45 * serialNumber CertificateSerialNumber,
46 * signature AlgorithmIdentifier,
50 * subjectPublicKeyInfo SubjectPublicKeyInfo,
51 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
52 * -- If present, version MUST be v2 or v3
53 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
54 * -- If present, version MUST be v2 or v3
55 * extensions [3] Extensions OPTIONAL
56 * -- If present, version MUST be v3 --
58 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
59 * CertificateSerialNumber ::= INTEGER
60 * Validity ::= SEQUENCE {
66 * generalTime GeneralizedTime
69 public class X509CertificateBuilder
: X509Builder
{
73 private string issuer
;
74 private DateTime notBefore
;
75 private DateTime notAfter
;
76 private string subject
;
77 private AsymmetricAlgorithm aa
;
78 private byte[] issuerUniqueID
;
79 private byte[] subjectUniqueID
;
80 private X509ExtensionCollection extensions
;
82 public X509CertificateBuilder () : this (3) {}
84 public X509CertificateBuilder (byte version
)
87 throw new ArgumentException ("Invalid certificate version");
88 this.version
= version
;
89 extensions
= new X509ExtensionCollection ();
93 get { return version; }
94 set { version = value; }
97 public byte[] SerialNumber
{
102 public string IssuerName
{
103 get { return issuer; }
104 set { issuer = value; }
107 public DateTime NotBefore
{
108 get { return notBefore; }
109 set { notBefore = value; }
112 public DateTime NotAfter
{
113 get { return notAfter; }
114 set { notAfter = value; }
117 public string SubjectName
{
118 get { return subject; }
119 set { subject = value; }
122 public AsymmetricAlgorithm SubjectPublicKey
{
127 public byte[] IssuerUniqueId
{
128 get { return issuerUniqueID; }
129 set { issuerUniqueID = value; }
132 public byte[] SubjectUniqueId
{
133 get { return subjectUniqueID; }
134 set { subjectUniqueID = value; }
137 public X509ExtensionCollection Extensions
{
138 get { return extensions; }
142 /* SubjectPublicKeyInfo ::= SEQUENCE {
143 * algorithm AlgorithmIdentifier,
144 * subjectPublicKey BIT STRING }
146 private ASN1
SubjectPublicKeyInfo ()
148 ASN1 keyInfo
= new ASN1 (0x30);
150 keyInfo
.Add (PKCS7
.AlgorithmIdentifier ("1.2.840.113549.1.1.1"));
151 RSAParameters p
= (aa
as RSA
).ExportParameters (false);
152 /* RSAPublicKey ::= SEQUENCE {
153 * modulus INTEGER, -- n
154 * publicExponent INTEGER } -- e
156 ASN1 key
= new ASN1 (0x30);
157 key
.Add (ASN1Convert
.FromUnsignedBigInteger (p
.Modulus
));
158 key
.Add (ASN1Convert
.FromUnsignedBigInteger (p
.Exponent
));
159 keyInfo
.Add (new ASN1 (UniqueIdentifier (key
.GetBytes ())));
161 else if (aa
is DSA
) {
162 DSAParameters p
= (aa
as DSA
).ExportParameters (false);
163 /* Dss-Parms ::= SEQUENCE {
168 ASN1 param
= new ASN1 (0x30);
169 param
.Add (ASN1Convert
.FromUnsignedBigInteger (p
.P
));
170 param
.Add (ASN1Convert
.FromUnsignedBigInteger (p
.Q
));
171 param
.Add (ASN1Convert
.FromUnsignedBigInteger (p
.G
));
172 keyInfo
.Add (PKCS7
.AlgorithmIdentifier ("1.2.840.10040.4.1", param
));
173 ASN1 key
= keyInfo
.Add (new ASN1 (0x03));
174 // DSAPublicKey ::= INTEGER -- public key, y
175 key
.Add (ASN1Convert
.FromUnsignedBigInteger (p
.Y
));
178 throw new NotSupportedException ("Unknown Asymmetric Algorithm " + aa
.ToString ());
182 private byte[] UniqueIdentifier (byte[] id
)
184 // UniqueIdentifier ::= BIT STRING
185 ASN1 uid
= new ASN1 (0x03);
186 // first byte in a BITSTRING is the number of unused bits in the first byte
187 byte[] v
= new byte [id
.Length
+ 1];
188 Buffer
.BlockCopy (id
, 0, v
, 1, id
.Length
);
190 return uid
.GetBytes ();
193 protected override ASN1
ToBeSigned (string oid
)
196 ASN1 tbsCert
= new ASN1 (0x30);
199 // TBSCertificate / [0] Version DEFAULT v1,
200 byte[] ver
= { (byte)(version - 1) }
;
201 ASN1 v
= tbsCert
.Add (new ASN1 (0xA0));
202 v
.Add (new ASN1 (0x02, ver
));
205 // TBSCertificate / CertificateSerialNumber,
206 tbsCert
.Add (new ASN1 (0x02, sn
));
208 // TBSCertificate / AlgorithmIdentifier,
209 tbsCert
.Add (PKCS7
.AlgorithmIdentifier (oid
));
211 // TBSCertificate / Name
212 tbsCert
.Add (X501
.FromString (issuer
));
214 // TBSCertificate / Validity
215 ASN1 validity
= tbsCert
.Add (new ASN1 (0x30));
216 // TBSCertificate / Validity / Time
217 validity
.Add (ASN1Convert
.FromDateTime (notBefore
));
218 // TBSCertificate / Validity / Time
219 validity
.Add (ASN1Convert
.FromDateTime (notAfter
));
221 // TBSCertificate / Name
222 tbsCert
.Add (X501
.FromString (subject
));
224 // TBSCertificate / SubjectPublicKeyInfo
225 tbsCert
.Add (SubjectPublicKeyInfo ());
228 // TBSCertificate / [1] IMPLICIT UniqueIdentifier OPTIONAL
229 if (issuerUniqueID
!= null)
230 tbsCert
.Add (new ASN1 (0xA1, UniqueIdentifier (issuerUniqueID
)));
232 // TBSCertificate / [2] IMPLICIT UniqueIdentifier OPTIONAL
233 if (subjectUniqueID
!= null)
234 tbsCert
.Add (new ASN1 (0xA1, UniqueIdentifier (subjectUniqueID
)));
236 // TBSCertificate / [3] Extensions OPTIONAL
237 if ((version
> 2) && (extensions
.Count
> 0))
238 tbsCert
.Add (new ASN1 (0xA3, extensions
.GetBytes ()));