@@ -39,6 +39,8 @@ function Certificate(opts) {
3939 assert . date ( opts . validFrom , 'options.validFrom' ) ;
4040 assert . date ( opts . validUntil , 'optons.validUntil' ) ;
4141
42+ assert . optionalArrayOfString ( opts . purposes , 'options.purposes' ) ;
43+
4244 this . _hashCache = { } ;
4345
4446 this . subjects = opts . subjects ;
@@ -49,6 +51,7 @@ function Certificate(opts) {
4951 this . serial = opts . serial ;
5052 this . validFrom = opts . validFrom ;
5153 this . validUntil = opts . validUntil ;
54+ this . purposes = opts . purposes ;
5255}
5356
5457Certificate . formats = formats ;
@@ -108,6 +111,10 @@ Certificate.prototype.isSignedBy = function (issuerCert) {
108111
109112 if ( ! this . issuer . equals ( issuerCert . subjects [ 0 ] ) )
110113 return ( false ) ;
114+ if ( this . issuer . purposes && this . issuer . purposes . length > 0 &&
115+ this . issuer . purposes . indexOf ( 'ca' ) === - 1 ) {
116+ return ( false ) ;
117+ }
111118
112119 return ( this . isSignedByKey ( issuerCert . subjectKey ) ) ;
113120} ;
@@ -180,6 +187,47 @@ Certificate.createSelfSigned = function (subjectOrSubjects, key, options) {
180187 if ( serial === undefined )
181188 serial = new Buffer ( '0000000000000001' , 'hex' ) ;
182189
190+ var purposes = options . purposes ;
191+ if ( purposes === undefined )
192+ purposes = [ ] ;
193+
194+ if ( purposes . indexOf ( 'signature' ) === - 1 )
195+ purposes . push ( 'signature' ) ;
196+
197+ /* Self-signed certs are always CAs. */
198+ if ( purposes . indexOf ( 'ca' ) === - 1 )
199+ purposes . push ( 'ca' ) ;
200+ if ( purposes . indexOf ( 'crl' ) === - 1 )
201+ purposes . push ( 'crl' ) ;
202+
203+ /*
204+ * If we weren't explicitly given any other purposes, do the sensible
205+ * thing and add some basic ones depending on the subject type.
206+ */
207+ if ( purposes . length <= 3 ) {
208+ var hostSubjects = subjects . filter ( function ( subject ) {
209+ return ( subject . type === 'host' ) ;
210+ } ) ;
211+ var userSubjects = subjects . filter ( function ( subject ) {
212+ return ( subject . type === 'user' ) ;
213+ } ) ;
214+ if ( hostSubjects . length > 0 ) {
215+ if ( purposes . indexOf ( 'serverAuth' ) === - 1 )
216+ purposes . push ( 'serverAuth' ) ;
217+ }
218+ if ( userSubjects . length > 0 ) {
219+ if ( purposes . indexOf ( 'clientAuth' ) === - 1 )
220+ purposes . push ( 'clientAuth' ) ;
221+ }
222+ if ( userSubjects . length > 0 || hostSubjects . length > 0 ) {
223+ if ( purposes . indexOf ( 'keyAgreement' ) === - 1 )
224+ purposes . push ( 'keyAgreement' ) ;
225+ if ( key . type === 'rsa' &&
226+ purposes . indexOf ( 'encryption' ) === - 1 )
227+ purposes . push ( 'encryption' ) ;
228+ }
229+ }
230+
183231 var cert = new Certificate ( {
184232 subjects : subjects ,
185233 issuer : subjects [ 0 ] ,
@@ -188,7 +236,8 @@ Certificate.createSelfSigned = function (subjectOrSubjects, key, options) {
188236 signatures : { } ,
189237 serial : serial ,
190238 validFrom : validFrom ,
191- validUntil : validUntil
239+ validUntil : validUntil ,
240+ purposes : purposes
192241 } ) ;
193242 cert . signWith ( key ) ;
194243
@@ -236,6 +285,42 @@ Certificate.create =
236285 if ( serial === undefined )
237286 serial = new Buffer ( '0000000000000001' , 'hex' ) ;
238287
288+ var purposes = options . purposes ;
289+ if ( purposes === undefined )
290+ purposes = [ ] ;
291+
292+ if ( purposes . indexOf ( 'signature' ) === - 1 )
293+ purposes . push ( 'signature' ) ;
294+
295+ if ( options . ca === true ) {
296+ if ( purposes . indexOf ( 'ca' ) === - 1 )
297+ purposes . push ( 'ca' ) ;
298+ if ( purposes . indexOf ( 'crl' ) === - 1 )
299+ purposes . push ( 'crl' ) ;
300+ }
301+
302+ var hostSubjects = subjects . filter ( function ( subject ) {
303+ return ( subject . type === 'host' ) ;
304+ } ) ;
305+ var userSubjects = subjects . filter ( function ( subject ) {
306+ return ( subject . type === 'user' ) ;
307+ } ) ;
308+ if ( hostSubjects . length > 0 ) {
309+ if ( purposes . indexOf ( 'serverAuth' ) === - 1 )
310+ purposes . push ( 'serverAuth' ) ;
311+ }
312+ if ( userSubjects . length > 0 ) {
313+ if ( purposes . indexOf ( 'clientAuth' ) === - 1 )
314+ purposes . push ( 'clientAuth' ) ;
315+ }
316+ if ( userSubjects . length > 0 || hostSubjects . length > 0 ) {
317+ if ( purposes . indexOf ( 'keyAgreement' ) === - 1 )
318+ purposes . push ( 'keyAgreement' ) ;
319+ if ( key . type === 'rsa' &&
320+ purposes . indexOf ( 'encryption' ) === - 1 )
321+ purposes . push ( 'encryption' ) ;
322+ }
323+
239324 var cert = new Certificate ( {
240325 subjects : subjects ,
241326 issuer : issuer ,
@@ -244,7 +329,8 @@ Certificate.create =
244329 signatures : { } ,
245330 serial : serial ,
246331 validFrom : validFrom ,
247- validUntil : validUntil
332+ validUntil : validUntil ,
333+ purposes : purposes
248334 } ) ;
249335 cert . signWith ( issuerKey ) ;
250336
0 commit comments