Smakdev
ACME


Content
  1. Getting all dirs
  2. Getting a Nonce
  3. Create account
  4. Create order
  5. Getting all dirs

The CA domain will be reffered as "CA.com"
and you should replace it with the CA of your choise like "letsencrypt.org".

Your domain will be reffered as "YourDomain.com"
and should be replaced with your domain like "smakdev.net".

1. Getting all dirs: // Firs of all you need to get all of the directories from the CA of your choice
To get the dirs you need to send a GET request to the servers /dir path like this:

GET /dir HTTP/1.1 Accept-Language: en Host: CA.com

And the server should answer with something like this:

HTTP/1.1 200 OK Content-Type: application/json { "newNonce": "https://CA.com/acme/new-nonce", "newAccount": "https://CA.com/acme/new-account", "newOrder": "https://CA.com/acme/new-order", "newAuthz": "https://CA.com/acme/new-authz", "revokeCert": "https://CA.com/acme/revoke-cert", "keyChange": "https://CA.com/acme/key-change", "meta": { "termsOfService": "https://CA.com/acme/terms/2017-5-30", "website": "https://CA.com/", "caaIdentities": ["CA.com"], "externalAccountRequired": false } }

These values should be saved for later use.

Sources:
rfc8555 section 7.1.1



2. Getting a Nonce: // The nonce will be used when making other requests to the server
To get a nonce you send a HEAD request with the "newNonce" directory from part 1.

HEAD /acme/newNonce HTTP/1.1 Host: CA.com

And you will get something like this if successfull:

HTTP/1.1 200 OK Replay-Nonce: oFvnlFP1wIhRlYS2jTaXbA Cache-Control: no-store Link: <https://CA.com/acme/directory>;rel="index"

Take the value from the Replay-Nonce header and store it.

Sources:
rfc8555 section 7.2



3. Create account: // An account is needed if you want to do anything
This will be a long one.
To get an account you need to send a POST request to the "newAccount" directory from part 1.

POST /acme/new-account HTTP/1.1 Host: CA.com Content-Type: application/jose+json { "protected": base64url({ "alg": "ES256", "jwk": {...}, "nonce": "6S8IqOGY7eL2lsGoTZYifg", "url": "https://CA.com/acme/new-account" }), "payload": base64url({ "termsOfServiceAgreed": true }), "signature": "RZPOnYoPs1PhjszF...-nh6X1qtOFPB519I" }

This request is in jose format wich means there are some needed headers, so we will go through them a litle bit.

The "protected" header is like your id card.
The "alg"(algorithm) part is for algorithm type you use for the signature.
The "jwk" will be taken up later.
The "nonce" should be your nonce from part 2.
The "url" should be the entire url for a new account from part 1.

The "payload" header is like your bag with all of your stuff.
The "termsOfServiceAgreed" can be needed to be true to create an account.

The "signature" should be: base64url(ES256(base64url(protected)+'.'+base64url(payload))).

The base64url() means that everything inside should be base64url encoded before they are sent.

JWK
{ "kty": "EC", "crv": "P-256", "x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU", "y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0" }


The "kty" says what ryptographic algorithm family is used in the key, the recomended one is "EC".
The "crv" says what curve is used.
The "x" is the x possition of the curve.
The "y" is the y possition of the curve.

If you have done it right it should look something like this:

HTTP/1.1 201 Created Cache-Control: public, max-age=0, no-cache Content-Type: application/json; charset=utf-8 Location: https://CA.com/my-account/4 Replay-Nonce: EksZN31XagCtew6Aev4RCA Date: Sat, 08 Jan 2022 16:50:35 GMT Content-Length: 232 { "status": "valid", "contact": null, "key": { "kty": "EC", "crv": "P-256", "x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU", "y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0" }, "ID": "4" }

You will need the value of the Location header.

Sources:
rfc7515
rfc8555 section 7.3



4. Create order:
To get a certificate you first need to place an order for you domain(s).
So send a POST request to the "newOrder" directory from part 1.

POST /acme/new-order HTTP/1.1 Host: 127.0.0.1 Content-Type: application/jose+json { "protected": base64url({ "alg": "ES256", "kid": "https://CA.com/acme/acct/evOfKhNU60wg", "nonce": "5XJ1L3lEkMG7tR6pA00clA", "url": "https://CA.com/acme/new-order" }), "payload": base64url({ "identifiers": [ { "type": "dns", "value": "www.YourDomain.com" }, { "type": "dns", "value": "YourDomain.com" } ], "notBefore": "2016-01-01T00:04:00+04:00", "notAfter": "2016-01-08T00:04:00+04:00" }), "signature": "H6ZXtGjTZyUnPeKn...wEA4TklBdh3e454g" }

And the result should be something like this:

HTTP/1.1 201 Created Replay-Nonce: MYAuvOpaoIiywTezizk5vw Link: <https://CA.com/acme/directory>;rel="index" Location: https://CA.com/acme/order/TOlocE8rfgo { "status": "pending", "expires": "2016-01-05T14:09:07.99Z", "notBefore": "2016-01-01T00:00:00Z", "notAfter": "2016-01-08T00:00:00Z", "identifiers": [ { "type": "dns", "value": "www.yourSite.org" }, { "type": "dns", "value": "yourSite.org" } ], "authorizations": [ "https://CA.com/acme/authz/PAniVnsZcis", "https://CA.com/acme/authz/r4HqLzrSrpI" ], "finalize": "https://CA.com/acme/order/TOlocE8rfgo/finalize" }

Save "authorizations" and "finalize" for later use.



5. Authorize domains:
To show to the CA that you own the domain you need to do challanges for all of the requested "identifiers".
You do this by first getting the identifier info by using the urls in "authorizations".
POST /acme/authz/PAniVnsZcis HTTP/1.1 Host: CA.com Content-Type: application/jose+json { "protected": base64url({ "alg": "ES256", "kid": "https://CA.com/acme/acct/evOfKhNU60wg", "nonce": "uQpSjlRb4vQVCjVYAyyUWg", "url": "https://CA.com/acme/authz/PAniVnsZcis" }), "payload": "", "signature": "nuSDISbWG8mMgE7H...QyVUL68yzf3Zawps" }
And you should get something like this
HTTP/1.1 200 OK Content-Type: application/json Link: <https://CA.com/acme/directory>;rel="index" { "status": "pending", "expires": "2016-01-02T14:09:30Z", "identifier": { "type": "dns", "value": "YourDomain.com" }, "challenges": [ { "type": "http-01", "url": "https://CA.com/acme/chall/prV_B7yEyA4", "token": "DGyRejmCefe7v4NfDGDKfA" } ] }

This tutorial only covers the challenge type of "http-01". You need to save the "challanges"[i]."type" for later and
give the token to your server so it can give it to your CA when requested.

Now it's time to inform the CA that we are ready for the challange.
You do this by sending a request to the challange url.
POST /acme/chall/prV_B7yEyA4 HTTP/1.1 Host: CA.com Content-Type: application/jose+json { "protected": base64url({ "alg": "ES256", "kid": "https://CA.com/acme/acct/evOfKhNU60wg", "nonce": "Q_s3MWoqT05TrdkM2MTDcw", "url": "https://CA.com/acme/chall/prV_B7yEyA4" }), "payload": base64url({}), "signature": "9cbg5JO1Gf5YLjjz...SpkUfcdPai9uVYYQ" }

This should return an updated version of last response.

After the "status" of all the domains has become "valid"
you should be able to use the "finalize" directory
POST /acme/order/TOlocE8rfgo/finalize HTTP/1.1 Host: example.com Content-Type: application/jose+json { "protected": base64url({ "alg": "ES256", "kid": "https://CA.com/acme/acct/evOfKhNU60wg", "nonce": "MSF2j2nawWHPxxkE3ZJtKQ", "url": "https://CA.com/acme/order/TOlocE8rfgo/finalize" }), "payload": base64url({ "csr": "MIIBPTCBxAIBADBFMQ...FS6aKdZeGsysoCo4H9P", }), "signature": "uOrUfIIk5RyQ...nw62Ay1cl6AB" }
And this should return the order with a new "certificate" field
HTTP/1.1 200 OK Replay-Nonce: CGf81JWBsq8QyIgPCi9Q9X Link: <https://CA.com/acme/directory>;rel="index" Location: https://CA.com/acme/order/TOlocE8rfgo { "status": "valid", "expires": "2016-01-20T14:09:07.99Z", "notBefore": "2016-01-01T00:00:00Z", "notAfter": "2016-01-08T00:00:00Z", "identifiers": [ { "type": "dns", "value": "www.YourDomain.com" }, { "type": "dns", "value": "YourDomain.com" } ], "authorizations": [ "https://CA.com/acme/authz/PAniVnsZcis", "https://CA.com/acme/authz/r4HqLzrSrpI" ], "finalize": "https://CA.com/acme/order/TOlocE8rfgo/finalize", "certificate": "https://CA.com/acme/cert/mAt3xBGaobw" }
Make a request to the "certificate" url
POST /acme/cert/mAt3xBGaobw HTTP/1.1 Host: CA.com Content-Type: application/jose+json Accept: application/pem-certificate-chain { "protected": base64url({ "alg": "ES256", "kid": "https://CA.com/acme/acct/evOfKhNU60wg", "nonce": "uQpSjlRb4vQVCjVYAyyUWg", "url": "https://CA.com/acme/cert/mAt3xBGaobw" }), "payload": "", "signature": "nuSDISbWG8mMgE7H...QyVUL68yzf3Zawps" }
Wich should return the issued cettificates.
HTTP/1.1 200 OK Content-Type: application/pem-certificate-chain Link: <https://CA.com/acme/directory>;rel="index" -----BEGIN CERTIFICATE----- [End-entity certificate contents] -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- [Issuer certificate contents] -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- [Other certificate contents] -----END CERTIFICATE-----

Now it's just to save them and use them in your program!