1+ 'use strict' ;
2+
13var FS = require ( 'fs' ) ;
4+ var path = require ( 'path' ) ;
25var Forge = require ( 'node-forge' ) ;
36var pki = Forge . pki ;
7+ var mkdirp = require ( 'mkdirp' ) ;
8+ var async = require ( 'async' ) ;
49
510var CAattrs = [ {
611 name : 'commonName' ,
@@ -99,25 +104,33 @@ var ServerExtensions = [{
99104 name : 'subjectKeyIdentifier'
100105} ] ;
101106
102- var CA = function ( caFolder ) {
103- this . baseCAFolder = caFolder ;
104- this . certsFolder = this . baseCAFolder + '/certs' ;
105- this . keysFolder = this . baseCAFolder + '/keys' ;
106- try {
107- FS . mkdirSync ( this . baseCAFolder ) ;
108- } catch ( e ) { /* no op */ }
109- try {
110- FS . mkdirSync ( this . certsFolder ) ;
111- } catch ( e ) { /* no op */ }
112- try {
113- FS . mkdirSync ( this . keysFolder ) ;
114- } catch ( e ) { /* no op */ }
115- try {
116- var stats = FS . statSync ( this . certsFolder + '/ca.pem' ) ;
117- this . loadCA ( ) ;
118- } catch ( e ) {
119- this . generateCA ( ) ;
120- }
107+ var CA = function ( ) {
108+ } ;
109+
110+ CA . create = function ( caFolder , callback ) {
111+ var ca = new CA ( ) ;
112+ ca . baseCAFolder = caFolder ;
113+ ca . certsFolder = path . join ( ca . baseCAFolder , 'certs' ) ;
114+ ca . keysFolder = path . join ( ca . baseCAFolder , 'keys' ) ;
115+ async . series ( [
116+ mkdirp . bind ( null , ca . baseCAFolder ) ,
117+ mkdirp . bind ( null , ca . certsFolder ) ,
118+ mkdirp . bind ( null , ca . keysFolder ) ,
119+ function ( callback ) {
120+ FS . exists ( path . join ( ca . certsFolder , 'ca.pem' ) , function ( exists ) {
121+ if ( exists ) {
122+ ca . loadCA ( callback ) ;
123+ } else {
124+ ca . generateCA ( callback ) ;
125+ }
126+ } ) ;
127+ }
128+ ] , function ( err ) {
129+ if ( err ) {
130+ return callback ( err ) ;
131+ }
132+ return callback ( null , ca ) ;
133+ } ) ;
121134} ;
122135
123136CA . prototype . randomSerialNumber = function ( ) {
@@ -129,34 +142,55 @@ CA.prototype.randomSerialNumber = function () {
129142 return sn ;
130143}
131144
132- CA . prototype . generateCA = function ( ) {
133- var keys = pki . rsa . generateKeyPair ( 2048 ) ;
134- var cert = pki . createCertificate ( ) ;
135- cert . publicKey = keys . publicKey ;
136- cert . serialNumber = this . randomSerialNumber ( ) ;
137- cert . validity . notBefore = new Date ( ) ;
138- cert . validity . notAfter = new Date ( ) ;
139- cert . validity . notAfter . setFullYear ( cert . validity . notBefore . getFullYear ( ) + 10 ) ;
140- cert . setSubject ( CAattrs ) ;
141- cert . setIssuer ( CAattrs ) ;
142- cert . setExtensions ( CAextensions ) ;
143- cert . sign ( keys . privateKey , Forge . md . sha256 . create ( ) ) ;
144- this . CAcert = cert ;
145- this . CAkeys = keys ;
146- FS . writeFileSync ( this . certsFolder + '/ca.pem' , pki . certificateToPem ( cert ) ) ;
147- FS . writeFileSync ( this . keysFolder + '/ca.private.key' , pki . privateKeyToPem ( keys . privateKey ) ) ;
148- FS . writeFileSync ( this . keysFolder + '/ca.public.key' , pki . publicKeyToPem ( keys . publicKey ) ) ;
145+ CA . prototype . generateCA = function ( callback ) {
146+ var self = this ;
147+ pki . rsa . generateKeyPair ( { bits : 2048 } , function ( err , keys ) {
148+ if ( err ) {
149+ return callback ( err ) ;
150+ }
151+ var cert = pki . createCertificate ( ) ;
152+ cert . publicKey = keys . publicKey ;
153+ cert . serialNumber = self . randomSerialNumber ( ) ;
154+ cert . validity . notBefore = new Date ( ) ;
155+ cert . validity . notAfter = new Date ( ) ;
156+ cert . validity . notAfter . setFullYear ( cert . validity . notBefore . getFullYear ( ) + 10 ) ;
157+ cert . setSubject ( CAattrs ) ;
158+ cert . setIssuer ( CAattrs ) ;
159+ cert . setExtensions ( CAextensions ) ;
160+ cert . sign ( keys . privateKey , Forge . md . sha256 . create ( ) ) ;
161+ self . CAcert = cert ;
162+ self . CAkeys = keys ;
163+ async . parallel ( [
164+ FS . writeFile . bind ( null , path . join ( self . certsFolder , 'ca.pem' ) , pki . certificateToPem ( cert ) ) ,
165+ FS . writeFile . bind ( null , path . join ( self . keysFolder , 'ca.private.key' ) , pki . privateKeyToPem ( keys . privateKey ) ) ,
166+ FS . writeFile . bind ( null , path . join ( self . keysFolder , 'ca.public.key' ) , pki . publicKeyToPem ( keys . publicKey ) )
167+ ] , callback ) ;
168+ } ) ;
149169} ;
150170
151- CA . prototype . loadCA = function ( ) {
152- var certPEM = FS . readFileSync ( this . certsFolder + '/ca.pem' ) ;
153- var keyPrivatePEM = FS . readFileSync ( this . keysFolder + '/ca.private.key' ) ;
154- var keyPublicPEM = FS . readFileSync ( this . keysFolder + '/ca.public.key' ) ;
155- this . CAcert = pki . certificateFromPem ( certPEM ) ;
156- this . CAkeys = {
157- privateKey : pki . privateKeyFromPem ( keyPrivatePEM ) ,
158- publicKey : pki . publicKeyFromPem ( keyPublicPEM )
159- } ;
171+ CA . prototype . loadCA = function ( callback ) {
172+ var self = this ;
173+ async . auto ( {
174+ certPEM : function ( callback ) {
175+ FS . readFile ( path . join ( self . certsFolder , 'ca.pem' ) , 'utf-8' , callback ) ;
176+ } ,
177+ keyPrivatePEM : function ( callback ) {
178+ FS . readFile ( path . join ( self . keysFolder , 'ca.private.key' ) , 'utf-8' , callback ) ;
179+ } ,
180+ keyPublicPEM : function ( callback ) {
181+ FS . readFile ( path . join ( self . keysFolder , 'ca.public.key' ) , 'utf-8' , callback ) ;
182+ }
183+ } , function ( err , results ) {
184+ if ( err ) {
185+ return callback ( err ) ;
186+ }
187+ self . CAcert = pki . certificateFromPem ( results . certPEM ) ;
188+ self . CAkeys = {
189+ privateKey : pki . privateKeyFromPem ( results . keyPrivatePEM ) ,
190+ publicKey : pki . publicKeyFromPem ( results . keyPublicPEM )
191+ } ;
192+ return callback ( ) ;
193+ } ) ;
160194} ;
161195
162196CA . prototype . generateServerCertificateKeys = function ( hosts , cb ) {
0 commit comments