mkcert.sh 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #! /bin/bash
  2. #
  3. # Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
  4. # Copyright (c) 2016 Viktor Dukhovni <[email protected]>.
  5. # All rights reserved.
  6. #
  7. # Licensed under the OpenSSL license (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 OPTIND=1
  99. local purpose=
  100. while getopts p:c: o
  101. do
  102. case $o in
  103. p) purpose="$OPTARG";;
  104. c) certpol="$OPTARG";;
  105. *) echo "Usage: $0 genca [-p EKU][-c policyoid] cn keyname certname cakeyname cacertname" >&2
  106. return 1;;
  107. esac
  108. done
  109. shift $((OPTIND - 1))
  110. local cn=$1; shift
  111. local key=$1; shift
  112. local cert=$1; shift
  113. local cakey=$1; shift
  114. local cacert=$1; shift
  115. local skid="subjectKeyIdentifier = hash"
  116. local akid="authorityKeyIdentifier = keyid"
  117. exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = critical,CA:true")
  118. if [ -n "$purpose" ]; then
  119. exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$purpose")
  120. fi
  121. if [ -n "$NC" ]; then
  122. exts=$(printf "%s\nnameConstraints = %s\n" "$exts" "$NC")
  123. fi
  124. if [ -n "$certpol" ]; then
  125. exts=$(printf "%s\ncertificatePolicies = %s\n" "$exts" "$certpol")
  126. fi
  127. csr=$(req "$key" "CN = $cn") || return 1
  128. echo "$csr" |
  129. cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \
  130. -set_serial 2 -days "${DAYS}" "$@"
  131. }
  132. gen_nonbc_ca() {
  133. local cn=$1; shift
  134. local key=$1; shift
  135. local cert=$1; shift
  136. local cakey=$1; shift
  137. local cacert=$1; shift
  138. local skid="subjectKeyIdentifier = hash"
  139. local akid="authorityKeyIdentifier = keyid"
  140. exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid")
  141. exts=$(printf "%s\nkeyUsage = %s\n" "$exts" "keyCertSign, cRLSign")
  142. for eku in "$@"
  143. do
  144. exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$eku")
  145. done
  146. csr=$(req "$key" "CN = $cn") || return 1
  147. echo "$csr" |
  148. cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \
  149. -set_serial 2 -days "${DAYS}"
  150. }
  151. # Usage: $0 genpc keyname certname eekeyname eecertname pcext1 pcext2 ...
  152. #
  153. # Note: takes csr on stdin, so must be used with $0 req like this:
  154. #
  155. # $0 req keyname dn | $0 genpc keyname certname eekeyname eecertname pcext ...
  156. genpc() {
  157. local key=$1; shift
  158. local cert=$1; shift
  159. local cakey=$1; shift
  160. local ca=$1; shift
  161. exts=$(printf "%s\n%s\n%s\n%s\n" \
  162. "subjectKeyIdentifier = hash" \
  163. "authorityKeyIdentifier = keyid, issuer:always" \
  164. "basicConstraints = CA:false" \
  165. "proxyCertInfo = critical, @pcexts";
  166. echo "[pcexts]";
  167. for x in "$@"; do echo $x; done)
  168. cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
  169. -set_serial 2 -days "${DAYS}"
  170. }
  171. # Usage: $0 geneealt keyname certname eekeyname eecertname alt1 alt2 ...
  172. #
  173. # Note: takes csr on stdin, so must be used with $0 req like this:
  174. #
  175. # $0 req keyname dn | $0 geneealt keyname certname eekeyname eecertname alt ...
  176. geneealt() {
  177. local key=$1; shift
  178. local cert=$1; shift
  179. local cakey=$1; shift
  180. local ca=$1; shift
  181. exts=$(printf "%s\n%s\n%s\n%s\n" \
  182. "subjectKeyIdentifier = hash" \
  183. "authorityKeyIdentifier = keyid" \
  184. "basicConstraints = CA:false" \
  185. "subjectAltName = @alts";
  186. echo "[alts]";
  187. for x in "$@"; do echo $x; done)
  188. cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
  189. -set_serial 2 -days "${DAYS}"
  190. }
  191. genee() {
  192. local OPTIND=1
  193. local purpose=serverAuth
  194. while getopts p: o
  195. do
  196. case $o in
  197. p) purpose="$OPTARG";;
  198. *) echo "Usage: $0 genee [-p EKU] cn keyname certname cakeyname cacertname" >&2
  199. return 1;;
  200. esac
  201. done
  202. shift $((OPTIND - 1))
  203. local cn=$1; shift
  204. local key=$1; shift
  205. local cert=$1; shift
  206. local cakey=$1; shift
  207. local ca=$1; shift
  208. exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
  209. "subjectKeyIdentifier = hash" \
  210. "authorityKeyIdentifier = keyid, issuer" \
  211. "basicConstraints = CA:false" \
  212. "extendedKeyUsage = $purpose" \
  213. "subjectAltName = @alts" "DNS=${cn}")
  214. csr=$(req "$key" "CN = $cn") || return 1
  215. echo "$csr" |
  216. cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
  217. -set_serial 2 -days "${DAYS}" "$@"
  218. }
  219. geneenocsr() {
  220. local OPTIND=1
  221. local purpose=serverAuth
  222. while getopts p: o
  223. do
  224. case $o in
  225. p) purpose="$OPTARG";;
  226. *) echo "Usage: $0 genee [-p EKU] cn certname cakeyname cacertname" >&2
  227. return 1;;
  228. esac
  229. done
  230. shift $((OPTIND - 1))
  231. local cn=$1; shift
  232. local cert=$1; shift
  233. local cakey=$1; shift
  234. local ca=$1; shift
  235. exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
  236. "subjectKeyIdentifier = hash" \
  237. "authorityKeyIdentifier = keyid, issuer" \
  238. "basicConstraints = CA:false" \
  239. "extendedKeyUsage = $purpose" \
  240. "subjectAltName = @alts" "DNS=${cn}")
  241. cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
  242. -set_serial 2 -days "${DAYS}" "$@"
  243. }
  244. genss() {
  245. local cn=$1; shift
  246. local key=$1; shift
  247. local cert=$1; shift
  248. exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
  249. "subjectKeyIdentifier = hash" \
  250. "authorityKeyIdentifier = keyid, issuer" \
  251. "basicConstraints = CA:false" \
  252. "extendedKeyUsage = serverAuth" \
  253. "subjectAltName = @alts" "DNS=${cn}")
  254. csr=$(req "$key" "CN = $cn") || return 1
  255. echo "$csr" |
  256. cert "$cert" "$exts" -signkey "${key}.pem" \
  257. -set_serial 1 -days "${DAYS}" "$@"
  258. }
  259. gennocn() {
  260. local key=$1; shift
  261. local cert=$1; shift
  262. csr=$(req_nocn "$key") || return 1
  263. echo "$csr" |
  264. cert "$cert" "" -signkey "${key}.pem" -set_serial 1 -days -1 "$@"
  265. }
  266. "$@"