mkcert.sh 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. #! /bin/bash
  2. #
  3. # Copyright (c) 2016 Viktor Dukhovni <openssl-users@dukhovni.org>.
  4. # All rights reserved.
  5. #
  6. # Contributed to the OpenSSL project under the terms of the OpenSSL license
  7. # included with the version of the OpenSSL software that includes this module.
  8. # 100 years should be enough for now
  9. #
  10. if [ -z "$DAYS" ]; then
  11. DAYS=36525
  12. fi
  13. if [ -z "$OPENSSL_SIGALG" ]; then
  14. OPENSSL_SIGALG=sha256
  15. fi
  16. if [ -z "$REQMASK" ]; then
  17. REQMASK=utf8only
  18. fi
  19. stderr_onerror() {
  20. (
  21. err=$("$@" >&3 2>&1) || {
  22. printf "%s\n" "$err" >&2
  23. exit 1
  24. }
  25. ) 3>&1
  26. }
  27. key() {
  28. local key=$1; shift
  29. local alg=rsa
  30. if [ -n "$OPENSSL_KEYALG" ]; then
  31. alg=$OPENSSL_KEYALG
  32. fi
  33. local bits=2048
  34. if [ -n "$OPENSSL_KEYBITS" ]; then
  35. bits=$OPENSSL_KEYBITS
  36. fi
  37. if [ ! -f "${key}.pem" ]; then
  38. args=(-algorithm "$alg")
  39. case $alg in
  40. rsa) args=("${args[@]}" -pkeyopt rsa_keygen_bits:$bits );;
  41. ec) args=("${args[@]}" -pkeyopt "ec_paramgen_curve:$bits")
  42. args=("${args[@]}" -pkeyopt ec_param_enc:named_curve);;
  43. *) printf "Unsupported key algorithm: %s\n" "$alg" >&2; return 1;;
  44. esac
  45. stderr_onerror \
  46. openssl genpkey "${args[@]}" -out "${key}.pem"
  47. fi
  48. }
  49. # Usage: $0 req keyname dn1 dn2 ...
  50. req() {
  51. local key=$1; shift
  52. key "$key"
  53. local errs
  54. stderr_onerror \
  55. openssl req -new -"${OPENSSL_SIGALG}" -key "${key}.pem" \
  56. -config <(printf "string_mask=%s\n[req]\n%s\n%s\n[dn]\n" \
  57. "$REQMASK" "prompt = no" "distinguished_name = dn"
  58. for dn in "$@"; do echo "$dn"; done)
  59. }
  60. req_nocn() {
  61. local key=$1; shift
  62. key "$key"
  63. stderr_onerror \
  64. openssl req -new -"${OPENSSL_SIGALG}" -subj / -key "${key}.pem" \
  65. -config <(printf "[req]\n%s\n[dn]\nCN_default =\n" \
  66. "distinguished_name = dn")
  67. }
  68. cert() {
  69. local cert=$1; shift
  70. local exts=$1; shift
  71. stderr_onerror \
  72. openssl x509 -req -"${OPENSSL_SIGALG}" -out "${cert}.pem" \
  73. -extfile <(printf "%s\n" "$exts") "$@"
  74. }
  75. genroot() {
  76. local cn=$1; shift
  77. local key=$1; shift
  78. local cert=$1; shift
  79. local skid="subjectKeyIdentifier = hash"
  80. local akid="authorityKeyIdentifier = keyid"
  81. exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = critical,CA:true")
  82. for eku in "$@"
  83. do
  84. exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$eku")
  85. done
  86. csr=$(req "$key" "CN = $cn") || return 1
  87. echo "$csr" |
  88. cert "$cert" "$exts" -signkey "${key}.pem" -set_serial 1 -days "${DAYS}"
  89. }
  90. genca() {
  91. local cn=$1; shift
  92. local key=$1; shift
  93. local cert=$1; shift
  94. local cakey=$1; shift
  95. local cacert=$1; shift
  96. local skid="subjectKeyIdentifier = hash"
  97. local akid="authorityKeyIdentifier = keyid"
  98. exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = critical,CA:true")
  99. for eku in "$@"
  100. do
  101. exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$eku")
  102. done
  103. if [ -n "$NC" ]; then
  104. exts=$(printf "%s\nnameConstraints = %s\n" "$exts" "$NC")
  105. fi
  106. csr=$(req "$key" "CN = $cn") || return 1
  107. echo "$csr" |
  108. cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \
  109. -set_serial 2 -days "${DAYS}"
  110. }
  111. gen_nonbc_ca() {
  112. local cn=$1; shift
  113. local key=$1; shift
  114. local cert=$1; shift
  115. local cakey=$1; shift
  116. local cacert=$1; shift
  117. local skid="subjectKeyIdentifier = hash"
  118. local akid="authorityKeyIdentifier = keyid"
  119. exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid")
  120. exts=$(printf "%s\nkeyUsage = %s\n" "$exts" "keyCertSign, cRLSign")
  121. for eku in "$@"
  122. do
  123. exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$eku")
  124. done
  125. csr=$(req "$key" "CN = $cn") || return 1
  126. echo "$csr" |
  127. cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \
  128. -set_serial 2 -days "${DAYS}"
  129. }
  130. # Usage: $0 genpc keyname certname eekeyname eecertname pcext1 pcext2 ...
  131. #
  132. # Note: takes csr on stdin, so must be used with $0 req like this:
  133. #
  134. # $0 req keyname dn | $0 genpc keyname certname eekeyname eecertname pcext ...
  135. genpc() {
  136. local key=$1; shift
  137. local cert=$1; shift
  138. local cakey=$1; shift
  139. local ca=$1; shift
  140. exts=$(printf "%s\n%s\n%s\n%s\n" \
  141. "subjectKeyIdentifier = hash" \
  142. "authorityKeyIdentifier = keyid, issuer:always" \
  143. "basicConstraints = CA:false" \
  144. "proxyCertInfo = critical, @pcexts";
  145. echo "[pcexts]";
  146. for x in "$@"; do echo $x; done)
  147. cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
  148. -set_serial 2 -days "${DAYS}"
  149. }
  150. # Usage: $0 genalt keyname certname eekeyname eecertname alt1 alt2 ...
  151. #
  152. # Note: takes csr on stdin, so must be used with $0 req like this:
  153. #
  154. # $0 req keyname dn | $0 genalt keyname certname eekeyname eecertname alt ...
  155. geneealt() {
  156. local key=$1; shift
  157. local cert=$1; shift
  158. local cakey=$1; shift
  159. local ca=$1; shift
  160. exts=$(printf "%s\n%s\n%s\n%s\n" \
  161. "subjectKeyIdentifier = hash" \
  162. "authorityKeyIdentifier = keyid" \
  163. "basicConstraints = CA:false" \
  164. "subjectAltName = @alts";
  165. echo "[alts]";
  166. for x in "$@"; do echo $x; done)
  167. cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
  168. -set_serial 2 -days "${DAYS}"
  169. }
  170. genee() {
  171. local OPTIND=1
  172. local purpose=serverAuth
  173. while getopts p: o
  174. do
  175. case $o in
  176. p) purpose="$OPTARG";;
  177. *) echo "Usage: $0 genee [-p EKU] cn keyname certname cakeyname cacertname" >&2
  178. return 1;;
  179. esac
  180. done
  181. shift $((OPTIND - 1))
  182. local cn=$1; shift
  183. local key=$1; shift
  184. local cert=$1; shift
  185. local cakey=$1; shift
  186. local ca=$1; shift
  187. exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
  188. "subjectKeyIdentifier = hash" \
  189. "authorityKeyIdentifier = keyid, issuer" \
  190. "basicConstraints = CA:false" \
  191. "extendedKeyUsage = $purpose" \
  192. "subjectAltName = @alts" "DNS=${cn}")
  193. csr=$(req "$key" "CN = $cn") || return 1
  194. echo "$csr" |
  195. cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
  196. -set_serial 2 -days "${DAYS}" "$@"
  197. }
  198. genss() {
  199. local cn=$1; shift
  200. local key=$1; shift
  201. local cert=$1; shift
  202. exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
  203. "subjectKeyIdentifier = hash" \
  204. "authorityKeyIdentifier = keyid, issuer" \
  205. "basicConstraints = CA:false" \
  206. "extendedKeyUsage = serverAuth" \
  207. "subjectAltName = @alts" "DNS=${cn}")
  208. csr=$(req "$key" "CN = $cn") || return 1
  209. echo "$csr" |
  210. cert "$cert" "$exts" -signkey "${key}.pem" \
  211. -set_serial 1 -days "${DAYS}" "$@"
  212. }
  213. gennocn() {
  214. local key=$1; shift
  215. local cert=$1; shift
  216. csr=$(req_nocn "$key") || return 1
  217. echo "$csr" |
  218. cert "$cert" "" -signkey "${key}.pem" -set_serial 1 -days -1 "$@"
  219. }
  220. "$@"