summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2016-01-21 13:33:57 -0500
committerAndrew Cady <d@jerkface.net>2016-01-21 13:33:57 -0500
commit71cff90ba42b49ea81d8c92adbbf8bd0f1343499 (patch)
tree6edc8e4e30835f1abff14c291c218da0f557d2c4
parentd313b531e9f83878face52c33955f477db164e1f (diff)
update documentation to reflect new code
-rw-r--r--README.md173
1 files changed, 37 insertions, 136 deletions
diff --git a/README.md b/README.md
index c101c43..e55607f 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,21 @@
1# Let's Encrypt ACME protocol 1# Let's Encrypt ACME protocol
2 2
3```
4Usage: acme-encrypt-exe --key FILE --domain DOMAIN --dir DIR [--email ADDRESS]
5 [--terms URL] [--staging]
6 This is a work in progress.
7
8Available options:
9 -h,--help Show this help text
10 --key FILE filename of your private RSA key
11 --domain DOMAIN the domain name to certify
12 --dir DIR output directory for ACME challenges
13 --email ADDRESS an email address with which to register an account
14 --terms URL the terms param of the registration request
15 --staging use staging servers instead of live servers
16 (certificates will not be real!)
17```
18
3This is a simple Haskell script to obtain a certificate from [Let's 19This is a simple Haskell script to obtain a certificate from [Let's
4Encrypt](https://letsencrypt.org/) using their ACME protocol. 20Encrypt](https://letsencrypt.org/) using their ACME protocol.
5 21
@@ -9,165 +25,50 @@ Encrypt](https://letsencrypt.org/) using their ACME protocol.
9 25
10- The ACME spec: https://letsencrypt.github.io/acme-spec/ 26- The ACME spec: https://letsencrypt.github.io/acme-spec/
11 27
12Most values are still hard-coded for my initial attempt (i.e. my email address
13and a domain of mine).
14
15
16## Discover the URL for letsencrypt ACME endpoints
17
18API endpoints are listed at https://acme-v01.api.letsencrypt.org/directory and
19are currently hard-coded in the script.
20
21```
22> curl -s https://acme-v01.api.letsencrypt.org/directory | json_pp
23{
24 "new-cert" : "https://acme-v01.api.letsencrypt.org/acme/new-cert",
25 "new-authz" : "https://acme-v01.api.letsencrypt.org/acme/new-authz",
26 "revoke-cert" : "https://acme-v01.api.letsencrypt.org/acme/revoke-cert",
27 "new-reg" : "https://acme-v01.api.letsencrypt.org/acme/new-reg"
28}
29```
30
31
32## Generate user account keys 28## Generate user account keys
33 29
34You need an account with Let's Encrypt to ask and receive certificates for your 30The needed keys will be automatically generated with HsOpenSSL. You can also
35domains. The account is controlled by a public/private key pair: 31pre-generate them manually, in which case they won't be overwritten:
36
37```
38openssl genrsa 4096 > user.key
39openssl rsa -in user.key -pubout > user.pub
40```
41
42
43## Generate nonces
44 32
45 33
46Each request to the API have a nonce to prevent replays. The nonce is currently
47hard-coded in the script. New nonces can be obtained from letsencrypt with
48
49```
50> generate-nonce.sh
51``` 34```
52 35openssl genrsa 4096 > user.key
53 36mkdir -p ${DOMAIN_NAME}
54## Create user account 37openssl genrsa 4096 > ${DOMAIN_NAME}/rsa.key
55
56Generate `registration.body` by using the `acme.hs` script then POST it to
57letsencrypt (note it assumes you agree to their subscriber agreement):
58
59```
60> curl -s -X POST --data-binary "@registration.body" \
61 https://acme-v01.api.letsencrypt.org/acme/new-reg | json_pp
62{
63 "agreement" : "https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf",
64 "contact" : [
65 "mailto:noteed@gmail.com"
66 ],
67 "key" : {
68 "e" : "...",
69 "kty" : "RSA",
70 "n" : "..."
71 },
72 "id" : 36009,
73 "createdAt" : "2015-12-04T14:22:08.321951547Z",
74 "initialIp" : "80.236.245.73"
75}
76```
77
78
79## Request a challenge
80
81
82Let's Encrypt needs a proof that you control the claimed domain. You can
83request a challenge with `challenge-request.body`.
84
85```
86> curl -s -X POST --data-binary "@challenge-request.body" \
87 https://acme-v01.api.letsencrypt.org/acme/new-authz | json_pp
88{
89 "expires" : "2015-12-21T18:44:52.331487674Z",
90 "challenges" : [
91 {
92 "status" : "pending",
93 "uri" : "https://acme-v01.api.letsencrypt.org/acme/challenge/vXZ1UnZ-y1q7sntnf6NdOfbPAwetJFBqOtvp7FHCjaU/1844047",
94 "type" : "tls-sni-01",
95 "token" : "oielAbB7MdyCl29mqjzlqGdrCQSB8SyJaxHbAgQBA7Q"
96 },
97 {
98 "uri" : "https://acme-v01.api.letsencrypt.org/acme/challenge/vXZ1UnZ-y1q7sntnf6NdOfbPAwetJFBqOtvp7FHCjaU/1844048",
99 "status" : "pending",
100 "type" : "http-01",
101 "token" : "DjyJpI3HVWAmsAwMT5ZFpW8dj19cel6ml6qaBUeGpCg"
102 }
103 ],
104 "identifier" : {
105 "type" : "dns",
106 "value" : "aaa.reesd.com"
107 },
108 "combinations" : [
109 [
110 0
111 ],
112 [
113 1
114 ]
115 ],
116 "status" : "pending"
117}
118``` 38```
119 39
120The script assumes you'll answer the challenge by hosting a file at a location 40## Send CSR
121chosen by Let's Encrypt. Extract the token for the `http-01` challenge and run
122the script again. Now you have to host the file at the location reported by the
123script.
124 41
125Once this is done, you can ask Let's Encrypt to check the file. 42The CSR will be automatically created. You can also create it yourself with:
126 43
127``` 44```
128> curl -s -X POST --data-binary "@challenge-response.body" \ 45> openssl req -new -sha256 -key ${DOMAIN}/rsa.key \
129 https://acme-v01.api.letsencrypt.org/acme/challenge/vXZ1UnZ-y1q7sntnf6NdOfbPAwetJFBqOtvp7FHCjaU/1844048 | json_pp 46 -subj "/CN=aaa.reesd.com" -outform DER > ${DOMAIN}/csr.der
130{
131 "token" : "DjyJpI3HVWAmsAwMT5ZFpW8dj19cel6ml6qaBUeGpCg",
132 "keyAuthorization" : "DjyJpI3HVWAmsAwMT5ZFpW8dj19cel6ml6qaBUeGpCg.EJe0KReqzCUq6leNOerMC9naZSHxP9TJzGxCcsGkNrw",
133 "type" : "http-01",
134 "uri" : "https://acme-v01.api.letsencrypt.org/acme/challenge/vXZ1UnZ-y1q7sntnf6NdOfbPAwetJFBqOtvp7FHCjaU/1844048",
135 "status" : "pending"
136}
137``` 47```
138 48
139The same URL can then be polled until the status becomes valid. 49## Receive certificate
140 50
51The signed certificate will be saved by this program in
52``./${DOMAIN}/cert.der``. You can copy that file to the place your TLS server is
53configured to read it.
141 54
142## Send CSR / Receive certificate 55You can also view the certificate like so:
143
144The CSR is created with:
145 56
146``` 57```
147> openssl genrsa 4096 > domain.key 58> openssl x509 -inform der -in ${DOMAIN}/cert.der -noout -text | less
148> openssl req -new -sha256 -key domain.key -subj "/CN=aaa.reesd.com" > aaa.reesd.com.csr
149> openssl req -in aaa.reesd.com.csr -outform DER > aaa.reesd.com.csr.der
150``` 59```
151 60
152And the signed certificate can be obtained from Let's Encrypt:
153
154```
155> curl -s -X POST --data-binary "@csr-request.body" \
156 https://acme-v01.api.letsencrypt.org/acme/new-cert > aaa.reesd.com.cert.der
157```
158
159
160## Create a certificate for HAProxy 61## Create a certificate for HAProxy
161 62
162Including explicit DH key exchange parameters to prevent Logjam attack 63Including explicit DH key exchange parameters to prevent Logjam attack
163(https://weakdh.org/). 64(https://weakdh.org/).
164 65
165``` 66```
166> openssl x509 -inform der -in aaa.reesd.com.cert.der \ 67> openssl x509 -inform der -in ${DOMAIN}/cert.der \
167 -out aaa.reesd.com.cert.pem 68 -out ${DOMAIN}/cert.pem
168> openssl dhparam -out aaa.reesd.com-dhparams.pem 2048 69> openssl dhparam -out ${DOMAIN}/dhparams.pem 2048
169> cat aaa.reesd.com.cert.pem \ 70> cat ${DOMAIN}/cert.pem \
170 lets-encrypt-x1-cross-signed.pem \ 71 lets-encrypt-x1-cross-signed.pem \
171 aaa.reesd.com.key \ 72 ${DOMAIN}/rsa.key \
172 aaa.reesd.com-dhparams.pem > aaa.reesd.com-combined.pem 73 ${DOMAIN}/dhparams.pem > aaa.reesd.com-combined.pem
173``` 74```