├── README.md └── MonkeyCertLab.sh /README.md: -------------------------------------------------------------------------------- 1 | # MonkeyCertLab 2 | Private Certificate Authority Creation Suite 3 | 4 | This scripts creates a set of client and server test certificates. 5 | 6 | - Root Certificate 7 | - Server Certificates 8 | - Client Certificates 9 | * Valid Certificate 10 | * Expired Certificate 11 | * Revoked Certificate 12 | - OCSP Responder Certificate 13 | 14 | -------------------------------------------------------------------------------- /MonkeyCertLab.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | create_openssl_conf () { 4 | if [ -d $1 ]; then 5 | rm -r $1 6 | fi 7 | mkdir -p $1 8 | cp openssl.cnf.orig $1/openssl.cnf 9 | CAPWD=$(echo $PWD | sed 's/\//\\\//g') 10 | sed "s/CAPWD/$CAPWD/" -i $1/openssl.cnf 11 | sed "s/DOM/$1/g" -i $1/openssl.cnf 12 | sed "s/ORG/$2/g" -i $1/openssl.cnf 13 | } 14 | 15 | create_CA_folders () { 16 | mkdir -p $1/ca/private 17 | chmod 700 $1/ca/private 18 | mkdir -p $1/ca/certs 19 | mkdir -p $1/ca/newcerts 20 | echo "01" > $1/ca/serial 21 | touch $1/ca/index.txt 22 | echo "unique_subject = yes" > $1/ca/index.txt.attr 23 | } 24 | 25 | # create CA Root Certificate Private Key 26 | gen_CA_cert () { 27 | openssl genrsa -out $1/ca/private/cakey.pem 2048 28 | openssl req -batch -new -x509 -days 3650 -key $1/ca/private/cakey.pem -out $1/ca/cacert.pem -config $1/openssl.cnf 29 | } 30 | 31 | gen_server_cert () { 32 | mkdir -p $1/server 33 | SUBJECT=`openssl x509 -noout -subject -in $1/ca/cacert.pem` 34 | SUBJECT=${SUBJECT#*=} 35 | SUBJECT="${SUBJECT%%CN*}CN=$2.$1/emailAddress=hostmaster@$1" 36 | SUBJECT="${SUBJECT// = /=}" 37 | SUBJECT="/${SUBJECT//, //}" 38 | #echo "${SUBJECT}" 39 | openssl genrsa -out $1/server/$2.key 2048 40 | openssl req -batch -new -subj "$SUBJECT" -key $1/server/$2.key -out $1/server/$2.req -config $1/openssl.cnf 41 | openssl ca -batch -name "server" -in $1/server/$2.req -out $1/server/$2.pem -config $1/openssl.cnf 42 | 43 | } 44 | 45 | gen_user_cert () { 46 | SUBJECT=`openssl x509 -noout -subject -in $1/ca/cacert.pem` 47 | SUBJECT=${SUBJECT#*=} 48 | SUBJECT="${SUBJECT%%CN*}CN=$2/emailAddress=$2@$1" 49 | SUBJECT="${SUBJECT// = /=}" 50 | SUBJECT="/${SUBJECT//, //}" 51 | STARTDATE=`openssl x509 -noout -startdate -in $1/ca/cacert.pem` 52 | STARTDATE=${STARTDATE#*=} 53 | STARTDATEZ=`date -u -d "$STARTDATE" +%y%m%d%H%M%SZ` 54 | ENDDATESEC=`date -u -d "$STARTDATE" +%s` 55 | ENDDATESEC2=$(($ENDDATESEC+31536000)) 56 | ENDDATEZ=`date -u -d "1970-01-01 UTC $ENDDATESEC2 seconds" +%y%m%d%H%M%SZ` 57 | openssl genrsa -out $1/user/$2.key 2048 58 | openssl req -batch -new -subj "$SUBJECT" -key $1/user/$2.key -out $1/user/$2.req -config $1/openssl.cnf 59 | case $3 in 60 | valid) 61 | STARTDATE=`date -u -d "$STARTDATE" +%y%m%d%H%M%SZ` 62 | openssl ca -batch -name "user" -startdate $STARTDATEZ -enddate $ENDDATEZ -in $1/user/$2.req -out $1/user/$2.pem -config $1/openssl.cnf 63 | ;; 64 | expired) 65 | ENDDATESEC2=$(($ENDDATESEC+1)) 66 | ENDDATEZ=`date -u -d "1970-01-01 UTC $ENDDATESEC2 seconds" +%y%m%d%H%M%SZ` 67 | openssl ca -batch -name "user" -startdate $STARTDATEZ -enddate $ENDDATEZ -in $1/user/$2.req -out $1/user/$2.pem -config $1/openssl.cnf 68 | sleep 1 69 | openssl ca -config $1/openssl.cnf -updatedb 70 | ;; 71 | revoked) 72 | openssl ca -batch -name "user" -startdate $STARTDATEZ -enddate $ENDDATEZ -in $1/user/$2.req -out $1/user/$2.pem -config $1/openssl.cnf 73 | openssl ca -config $1/openssl.cnf -revoke $1/user/$2.pem 74 | ;; 75 | esac 76 | } 77 | 78 | gen_users () { 79 | mkdir -p $1/user 80 | gen_user_cert $1 user1 valid 81 | gen_user_cert $1 user2 expired 82 | gen_user_cert $1 user3 revoked 83 | } 84 | 85 | gen_CRL () { 86 | mkdir -p $1/crl 87 | DATE=`date -u +%y%m%d%H%M%S` 88 | openssl ca -gencrl -config $1/openssl.cnf -out $1/crl/crl-$DATE.pem 89 | ln -sf crl-$DATE.pem $1/crl/crl.pem 90 | } 91 | 92 | gen_ocsp_responder () { 93 | mkdir -p $1/ocsp 94 | SUBJECT=`openssl x509 -noout -subject -in $1/ca/cacert.pem` 95 | SUBJECT=${SUBJECT#*=} 96 | SUBJECT="${SUBJECT%%CN*}CN=ocsp.$1/emailAddress=ocsp@$1" 97 | SUBJECT="${SUBJECT// = /=}" 98 | SUBJECT="/${SUBJECT//, //}" 99 | #echo "${SUBJECT}" 100 | openssl genrsa -out $1/ocsp/ocsp.key 2048 101 | openssl req -batch -new -subj "$SUBJECT" -key $1/ocsp/ocsp.key -out $1/ocsp/ocsp.req -config $1/openssl.cnf 102 | openssl ca -batch -name "ocsp_responder" -in $1/ocsp/ocsp.req -out $1/ocsp/ocsp.pem -config $1/openssl.cnf 103 | 104 | } 105 | 106 | create_openssl_conf_orig () { 107 | cat > openssl.cnf.orig << EOF 108 | ###################################################### 109 | # OpenSSL config Template 110 | # last modification: 2015-05-10 111 | ###################################################### 112 | # 113 | # +CA 114 | # | 115 | # +-- user certificates 116 | # +-- server certificates 117 | # +-- ocsp_responder certificates 118 | # 119 | ###################################################### 120 | 121 | SSL = CAPWD 122 | RANDFILE = \$SSL/DOM/ca/private/.rand 123 | default_md = sha512 124 | 125 | ###################################################### 126 | [ ca ] 127 | default_ca = user 128 | 129 | ###################################################### 130 | [ user ] 131 | 132 | dir = \$SSL/DOM/ca 133 | certs = \$dir/certs 134 | crl_dir = \$dir/crl 135 | database = \$dir/index.txt 136 | new_certs_dir = \$dir/newcerts 137 | 138 | certificate = \$dir/cacert.pem 139 | serial = \$dir/serial 140 | crl = \$dir/crl.pem 141 | private_key = \$dir/private/cakey.pem 142 | 143 | x509_extensions = user_ext 144 | 145 | default_days = 365 146 | default_crl_days = 7 147 | default_md = sha512 148 | preserve = no 149 | 150 | policy = policy_match 151 | 152 | ###################################################### 153 | [ server ] 154 | 155 | dir = \$SSL/DOM/ca 156 | certs = \$dir/certs 157 | crl_dir = \$dir/crl 158 | database = \$dir/index.txt 159 | new_certs_dir = \$dir/newcerts 160 | 161 | certificate = \$dir/cacert.pem 162 | serial = \$dir/serial 163 | crl = \$dir/crl.pem 164 | private_key = \$dir/private/cakey.pem 165 | 166 | x509_extensions = server_ext 167 | 168 | default_days = 365 169 | default_crl_days = 7 170 | default_md = sha512 171 | preserve = no 172 | 173 | policy = policy_match 174 | 175 | ###################################################### 176 | [ ocsp_responder ] 177 | 178 | dir = \$SSL/DOM/ca 179 | certs = \$dir/certs 180 | crl_dir = \$dir/crl 181 | database = \$dir/index.txt 182 | new_certs_dir = \$dir/newcerts 183 | 184 | certificate = \$dir/cacert.pem 185 | serial = \$dir/serial 186 | crl = \$dir/crl.pem 187 | private_key = \$dir/private/cakey.pem 188 | 189 | x509_extensions = ocsp_responder_ext 190 | 191 | default_days = 365 192 | default_crl_days = 7 193 | default_md = sha512 194 | preserve = no 195 | 196 | policy = policy_match 197 | 198 | ###################################################### 199 | [ symbian ] 200 | dir = \$SSL/DOM/ca 201 | certs = \$dir/certs 202 | crl_dir = \$dir/crl 203 | database = \$dir/index.txt 204 | new_certs_dir = \$dir/newcerts 205 | 206 | certificate = \$dir/cacert.pem 207 | serial = \$dir/serial 208 | crl = \$dir/crl.pem 209 | private_key = \$dir/private/cakey.pem 210 | 211 | x509_extensions = sym_ext 212 | 213 | default_days = 365 214 | default_crl_days = 7 215 | default_md = sha512 216 | preserve = no 217 | 218 | policy = policy_match 219 | 220 | ###################################################### 221 | [ x509v3_FQDN ] 222 | subjectAltName=DNS:DOM 223 | 224 | ###################################################### 225 | [ policy_match ] 226 | countryName = match 227 | stateOrProvinceName = match 228 | organizationName = match 229 | organizationalUnitName = optional 230 | commonName = supplied 231 | emailAddress = optional 232 | 233 | ###################################################### 234 | [ req ] 235 | default_bits = 4096 236 | default_keyfile = privkey.pem 237 | distinguished_name = req_distinguished_name 238 | attributes = req_attributes 239 | x509_extensions = v3_ca 240 | 241 | string_mask = nombstr 242 | 243 | ###################################################### 244 | [ req_distinguished_name ] 245 | countryName = Country Name (2 letter code) 246 | countryName_default = DE 247 | countryName_min = 2 248 | countryName_max = 2 249 | 250 | stateOrProvinceName = State or Province Name (full name) 251 | stateOrProvinceName_default = Nordrhein-Westfalen 252 | 253 | 0.organizationName = Organization Name (eg, company) 254 | 0.organizationName_default = ORG 255 | 256 | #organizationalUnitName = Organizational Unit Name (eg, section) 257 | #organizationalUnitName_default = Ministry of Truth 258 | 259 | commonName = Common Name (eg, YOUR name) 260 | commonName_max = 64 261 | commonName_default = ROOT CA Certificate 262 | 263 | emailAddress = Email Address 264 | emailAddress_max = 40 265 | emailAddress_default = rootca@DOM 266 | 267 | ###################################################### 268 | [ req_attributes ] 269 | # nothing ;-) 270 | 271 | ###################################################### 272 | [ ocsp_responder_ext ] 273 | 274 | # These extensions are added when a ocsp-server certificate is issued 275 | keyUsage = digitalSignature, keyEncipherment, keyAgreement 276 | extendedKeyUsage = OCSPSigning 277 | subjectKeyIdentifier = hash 278 | authorityKeyIdentifier = keyid,issuer:always 279 | subjectAltName = email:copy 280 | issuerAltName = issuer:copy 281 | crlDistributionPoints = URI:http://crl.DOM 282 | nsCertType = server 283 | nsComment = "This is a OCSP test certificate!" 284 | 285 | ###################################################### 286 | [ user_ext ] 287 | 288 | # These extensions are added when a user certificate is issued 289 | keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment 290 | extendedKeyUsage = clientAuth, emailProtection, 1.3.6.1.4.1.311.20.2.2 291 | subjectKeyIdentifier = hash 292 | authorityKeyIdentifier = keyid,issuer:always 293 | subjectAltName = email:copy 294 | issuerAltName = issuer:copy 295 | crlDistributionPoints = URI:http://crl.DOM 296 | nsCertType = client, email 297 | nsComment = "This is a USER test certificate!" 298 | authorityInfoAccess = OCSP;URI:http://ocsp.DOM 299 | 300 | ###################################################### 301 | [ server_ext ] 302 | 303 | # These extensions are added when a server certificate is issued 304 | keyUsage = digitalSignature, keyEncipherment, keyAgreement 305 | extendedKeyUsage = serverAuth 306 | subjectKeyIdentifier = hash 307 | authorityKeyIdentifier = keyid,issuer:always 308 | subjectAltName = email:copy 309 | issuerAltName = issuer:copy 310 | crlDistributionPoints = URI:http://crl.DOM 311 | nsCertType = server 312 | nsComment = "This is a SERVER test certificate!" 313 | authorityInfoAccess = OCSP;URI:http://ocsp.DOM 314 | 315 | ###################################################### 316 | [ sym_ext ] 317 | keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment 318 | extendedKeyUsage = clientAuth, emailProtection 319 | subjectKeyIdentifier = hash 320 | authorityKeyIdentifier = keyid,issuer:always 321 | subjectAltName = email:copy 322 | issuerAltName = issuer:copy 323 | crlDistributionPoints = URI:http://crl.DOM 324 | nsCertType = client, email, objsign 325 | nsComment = "Monkey Laboratory Certificate" 326 | authorityInfoAccess = OCSP;URI:http://ocsp.DOM 327 | nsCaPolicyUrl = http://DOM/ssl/policy.html 328 | 329 | 330 | ###################################################### 331 | [ v3_ca ] 332 | 333 | # These extensions are added when 'RootCA' _signs_ itself. 334 | basicConstraints = critical, CA:TRUE 335 | keyUsage = cRLSign, keyCertSign, keyEncipherment, nonRepudiation, digitalSignature 336 | subjectKeyIdentifier = hash 337 | authorityKeyIdentifier = keyid,issuer:always 338 | subjectAltName = email:copy 339 | issuerAltName = issuer:copy 340 | crlDistributionPoints = URI:http://crl.DOM 341 | nsCertType = sslCA, emailCA, objCA 342 | nsComment = "This a CA root test certificate!" 343 | authorityInfoAccess = OCSP;URI:http://ocsp.DOM 344 | 345 | ###################################################### 346 | [ crl_ext ] 347 | 348 | # CRL extensions. 349 | # Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. 350 | issuerAltName = issuer:copy 351 | authorityKeyIdentifier = keyid:always,issuer:always 352 | 353 | EOF 354 | } 355 | 356 | check_variables () { 357 | # Check DOMAIN and ORG variables 358 | ERROR=0 359 | if [ "x$1" = "x" ]; then 360 | echo "ERROR: Missing domain name!" 361 | ERROR=1 362 | fi 363 | if [ "x$2" = "x" ]; then 364 | echo "ERROR: Missing organization name!" 365 | ERROR=1 366 | fi 367 | if [ $ERROR = 1 ]; then 368 | print_usage 369 | exit 370 | fi 371 | } 372 | 373 | print_usage () { 374 | echo "$0 name.dom \"org name\"" 375 | } 376 | 377 | # Check for openssl template configuration 378 | 379 | check_openssl_cnf_orig () { 380 | if [ ! -f openssl.cnf.orig ]; then 381 | create_openssl_conf_orig 382 | fi 383 | } 384 | 385 | # CA Hierarchy 386 | # 387 | # ROOT CA Certificate 388 | # O = Organization 389 | # OU = Organization Unit 390 | 391 | CMD=$1 392 | DOMAIN=$2 393 | ORG=$3 394 | 395 | 396 | case $CMD in 397 | create) 398 | # Create CA directory 399 | check_variables $DOMAIN "$ORG" 400 | check_openssl_cnf_orig 401 | 402 | create_openssl_conf $DOMAIN "$ORG" 403 | create_CA_folders $DOMAIN 404 | gen_CA_cert $DOMAIN "$ORG" 405 | gen_server_cert $DOMAIN www 406 | gen_server_cert $DOMAIN mail 407 | gen_users $DOMAIN 408 | gen_CRL $DOMAIN 409 | gen_ocsp_responder $DOMAIN 410 | ;; 411 | delete) 412 | ;; 413 | *) 414 | print_usage 415 | ;; 416 | esac 417 | 418 | --------------------------------------------------------------------------------