File: X509CertificateBuilder.cs

package info (click to toggle)
mono 6.14.1%2Bds2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,282,732 kB
  • sloc: cs: 11,182,461; xml: 2,850,281; ansic: 699,123; cpp: 122,919; perl: 58,604; javascript: 30,841; asm: 21,845; makefile: 19,602; sh: 10,973; python: 4,772; pascal: 925; sql: 859; sed: 16; php: 1
file content (244 lines) | stat: -rw-r--r-- 7,678 bytes parent folder | download | duplicates (15)
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
//
// X509CertificateBuilder.cs: Handles building of X.509 certificates.
//
// Author:
//	Sebastien Pouliot <sebastien@ximian.com>
//
// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
// (C) 2004 Novell (http://www.novell.com)
//

//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System;
using System.Security.Cryptography;

namespace Mono.Security.X509 {
	// From RFC3280
	/*
	 * Certificate  ::=  SEQUENCE  {
	 *      tbsCertificate       TBSCertificate,
	 *      signatureAlgorithm   AlgorithmIdentifier,
	 *      signature            BIT STRING  
	 * }
	 * TBSCertificate  ::=  SEQUENCE  {
	 *      version         [0]  Version DEFAULT v1,
	 *      serialNumber         CertificateSerialNumber,
	 *      signature            AlgorithmIdentifier,
	 *      issuer               Name,
	 *      validity             Validity,
	 *      subject              Name,
	 *      subjectPublicKeyInfo SubjectPublicKeyInfo,
	 *      issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
	 *                           -- If present, version MUST be v2 or v3
	 *      subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
	 *                           -- If present, version MUST be v2 or v3
	 *      extensions      [3]  Extensions OPTIONAL
	 *                           -- If present, version MUST be v3 --  
	 * }
	 * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
	 * CertificateSerialNumber  ::=  INTEGER
	 * Validity ::= SEQUENCE {
	 *      notBefore      Time,
	 *      notAfter       Time  
	 * }
	 * Time ::= CHOICE {
	 *      utcTime        UTCTime,
	 *      generalTime    GeneralizedTime 
	 * }
	 */
	public class X509CertificateBuilder : X509Builder {
 
		private byte version;
		private byte[] sn;
		private string issuer;
		private DateTime notBefore;
		private DateTime notAfter;
		private string subject;
		private AsymmetricAlgorithm aa;
		private byte[] issuerUniqueID;
		private byte[] subjectUniqueID;
		private X509ExtensionCollection extensions;

		public X509CertificateBuilder () : this (3) {}
	
		public X509CertificateBuilder (byte version) 
		{
			if (version > 3)
				throw new ArgumentException ("Invalid certificate version");
			this.version = version;
			extensions = new X509ExtensionCollection ();
		}

		public byte Version {
			get { return version; }
			set { version = value; }
		}

		public byte[] SerialNumber {
			get { return sn; }
			set { sn = value; }
		}

		public string IssuerName {
			get { return issuer; }
			set { issuer = value; }
		}

		public DateTime NotBefore {
			get { return notBefore; }
			set { notBefore = value; }
		}

		public DateTime NotAfter {
			get { return notAfter; }
			set { notAfter = value; }
		}

		public string SubjectName {
			get { return subject; }
			set { subject = value; }
		}

		public AsymmetricAlgorithm SubjectPublicKey {
			get { return aa; }
			set { aa = value; }
		}

		public byte[] IssuerUniqueId {
			get { return issuerUniqueID; }
			set { issuerUniqueID = value; }
		}

		public byte[] SubjectUniqueId {
			get { return subjectUniqueID; }
			set { subjectUniqueID = value; }
		}

		public X509ExtensionCollection Extensions {
			get { return extensions; }
		}


		/* SubjectPublicKeyInfo  ::=  SEQUENCE  {
		 *      algorithm            AlgorithmIdentifier,
		 *      subjectPublicKey     BIT STRING  }
		 */
		private ASN1 SubjectPublicKeyInfo () 
		{
			ASN1 keyInfo = new ASN1 (0x30);
			if (aa is RSA) {
				keyInfo.Add (PKCS7.AlgorithmIdentifier ("1.2.840.113549.1.1.1"));
				RSAParameters p = (aa as RSA).ExportParameters (false);
				/* RSAPublicKey ::= SEQUENCE {
				 *       modulus            INTEGER,    -- n
				 *       publicExponent     INTEGER  }  -- e
				 */
				ASN1 key = new ASN1 (0x30);
				key.Add (ASN1Convert.FromUnsignedBigInteger (p.Modulus));
				key.Add (ASN1Convert.FromUnsignedBigInteger (p.Exponent));
				keyInfo.Add (new ASN1 (UniqueIdentifier (key.GetBytes ())));
			}
			else if (aa is DSA) {
				DSAParameters p = (aa as DSA).ExportParameters (false);
				/* Dss-Parms  ::=  SEQUENCE  {
				 *       p             INTEGER,
				 *       q             INTEGER,
				 *       g             INTEGER  }
				 */
				ASN1 param = new ASN1 (0x30);
				param.Add (ASN1Convert.FromUnsignedBigInteger (p.P));
				param.Add (ASN1Convert.FromUnsignedBigInteger (p.Q));
				param.Add (ASN1Convert.FromUnsignedBigInteger (p.G));
				keyInfo.Add (PKCS7.AlgorithmIdentifier ("1.2.840.10040.4.1", param));
				ASN1 key = keyInfo.Add (new ASN1 (0x03));
				// DSAPublicKey ::= INTEGER  -- public key, y
				key.Add (ASN1Convert.FromUnsignedBigInteger (p.Y));
			}
			else
				throw new NotSupportedException ("Unknown Asymmetric Algorithm " + aa.ToString ());
			return keyInfo;
		}

		private byte[] UniqueIdentifier (byte[] id) 
		{
			// UniqueIdentifier  ::=  BIT STRING
			ASN1 uid = new ASN1 (0x03);
			// first byte in a BITSTRING is the number of unused bits in the first byte
			byte[] v = new byte [id.Length + 1];
			Buffer.BlockCopy (id, 0, v, 1, id.Length);
			uid.Value = v;
			return uid.GetBytes ();
		}

		protected override ASN1 ToBeSigned (string oid) 
		{
			// TBSCertificate
			ASN1 tbsCert = new ASN1 (0x30);

			if (version > 1) {
				// TBSCertificate / [0] Version DEFAULT v1,
				byte[] ver = { (byte)(version - 1) };
				ASN1 v = tbsCert.Add (new ASN1 (0xA0));
				v.Add (new ASN1 (0x02, ver));
			}

			// TBSCertificate / CertificateSerialNumber,
			tbsCert.Add (new ASN1 (0x02, sn));

			// TBSCertificate / AlgorithmIdentifier,
                        tbsCert.Add (PKCS7.AlgorithmIdentifier (oid));

			// TBSCertificate / Name
			tbsCert.Add (X501.FromString (issuer));

			// TBSCertificate / Validity
			ASN1 validity = tbsCert.Add (new ASN1 (0x30));
			// TBSCertificate / Validity / Time
			validity.Add (ASN1Convert.FromDateTime (notBefore));
			// TBSCertificate / Validity / Time
			validity.Add (ASN1Convert.FromDateTime (notAfter));

			// TBSCertificate / Name
			tbsCert.Add (X501.FromString (subject));

			// TBSCertificate / SubjectPublicKeyInfo
			tbsCert.Add (SubjectPublicKeyInfo ());
                        
			if (version > 1) {
				// TBSCertificate / [1]  IMPLICIT UniqueIdentifier OPTIONAL
				if (issuerUniqueID != null)
					tbsCert.Add (new ASN1 (0xA1, UniqueIdentifier (issuerUniqueID)));

				// TBSCertificate / [2]  IMPLICIT UniqueIdentifier OPTIONAL
				if (subjectUniqueID != null)
					tbsCert.Add (new ASN1 (0xA1, UniqueIdentifier (subjectUniqueID)));

				// TBSCertificate / [3]  Extensions OPTIONAL
				if ((version > 2) &&  (extensions.Count > 0))
					tbsCert.Add (new ASN1 (0xA3, extensions.GetBytes ()));
			}

			return tbsCert;
		}
	}
}