mkcert.sh 7.1 KB

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