Ephemeral Key Registration & Unlocking a Door
In this guide we're exploring user ephemeral keys, Ed25519, certificate chains and digital signatures using EdDSA - all of this to unlock a door!
Our SDK takes care of the complexity detailed in this guide, we strongly recommend using it for your application. The information provided here is for educational purposes and to help you understand the underlying processes.
Prerequisites
The examples in this article require a recent version of OpenSSL (we tested against OpenSSL 3.1.4). Verify your OpenSSL version by running:
openssl genpkey -algorithm ed25519
If that command succeeds, you're ready to proceed.
Concepts
Ed25519 is a public‐key signature system. It consists of:
- A private key, which you use to sign messages.
- A public key, which anyone can use to verify signatures.
Sentry Interactive relies on digital signatures to ensure that only the right user is performing an action. Under the hood:
- EdDSA stands for Edwards Digital Signature Algorithm, the algorithm used to generate and verify signatures.
- Ed25519 is the elliptic‐curve specification on which EdDSA operates.
If you've used RSA, Ed25519 works similarly but offers smaller key sizes and better performance.
Ephemeral Key Registration
Every time a user logs into a new device, we generate a new Ed25519 keypair and ask Sentry Interactive to sign it in the form of a keychain, we can perform these steps manually, let's start by generating a keypair.
openssl genpkey -algorithm ed25519 -outform DER -out private.key
Extract the public key
openssl pkey -inform DER -in private.key -pubout -outform DER -out public.key
We need to wrap the public key in base 64 encoding to be able to send it to Sentry Interactive:
cat public.key | base64 > public.base64.key
Now we can send it to Sentry Interactive using an auth key generated from the previous article; currently we need to use the
development endpoint - we'll save the response to a file called certs.json
curl "https://api.doordeck.com/auth/certificate" \
-X POST \
-H "Authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
--data-binary "{\"ephemeralKey\":\"`cat public.base64.key`\"}" > certs.json
This endpoint tells us our newly generated certificate chain and our Sentry Interactive user ID which we need for certain operations, such as having a door shared with us. We'll be using this information later so hold onto it.
Get A Door
Whilst we could jump straight into unlocking a door, you probably haven't got one setup yet, so I've thrown together a basic HTML form where you can input your user ID as displayed from the last step:
cat certs.json | jq .userId
Visit https://api.doordeck.com/demo/ and put your user ID in.
Unlock It!
Now we need to construct a signed JWT request and send it to Sentry Interactive to forward onto the Demo door - this is surprisingly similar to the OpenID token we created in the previous article since OpenID is built on top of JWT!
The header is easy, we take the certificate chain from the last step and put it in the x5c field, we then specify our
algorithm, EdDSA and typ as JWT, e.g.
{
"typ": "jwt",
"x5c": [
"MII...",
"MII...",
"MII...",
"MII..."
],
"alg": "EdDSA"
}
Most certificates start with MII but replace them with actual certificates as shown in the last step, in the same order.
The body is where we specify the door we want to unlock and how long our request is valid for, e.g.:
{
"iss": "YOUR_USER_ID",
"sub": "ad8fb900-4def-11e8-9370-170748b9fca8",
"operation": {
"type": "MUTATE_LOCK",
"locked": false
},
"exp": 1550497860,
"iat": 1550497800,
"nbf": 1550497800
}
You'll have to adjust a few fields in this JSON example, specifically you should put your user ID from the last step in
the iss field (as you're issuing the command), the subject here is the demo door ID so you can leave that the same,
but you'll need to set the iat and nbf fields to the current Unix timestamp in seconds then the exp field to the
current Unix timestamp + 60 seconds, this is adjustable but 60 seconds is a sensible default.
As JWT goes, we have to BASE64URL encode the header then the body and concatenate them with a . period in between.
alias base64url="base64 | sed 's/+/-/g;s/\//_/g;s/=//g'"
echo -n '{"typ":"jwt","x5c":["MII...","MII...","MII...","MII..."],"alg":"EdDSA"}' | base64url
echo -n '{"iss":"YOUR_USER_ID","sub":"ad8fb900-4def-11e8-9370-170748b9fca8","operation":{"type":"MUTATE_LOCK","locked":false},"exp":1550497860,"iat":1550497800,"nbf":1550497800}' | base64url
Combine these and perform a signature calculation.
echo -n eyJ0eXAiOiJqd3QiLCJ4NWMiOlsiTUlJLi4uIiwiTUlJLi4uIiwiTUlJLi4uIiwiTUlJLi4uIl0sImFsZyI6IkVkRFNBIn0K.eyJpc3MiOiJZT1VSX1VTRVJfSUQiLCJzdWIiOiJhZDhmYjkwMC00ZGVmLTExZTgtOTM3MC0xNzA3NDhiOWZjYTgiLCJvcGVyYXRpb24iOnsidHlwZSI6Ik1VVEFCTEVfTE9DSyIsImxvY2tlZCI6ZmFsc2V9LCJleHAiOjE1NTA0OTc4NjAsImlhdCI6MTU1MDQ5NzgwMCwibmJmIjoxNTUwNDk3ODAwfQo > token
openssl pkeyutl -sign -inkey private.key -rawin -in token | base64url
Phew, almost there! That command should output a signature in Base64Url format, e.g.
lA-iqBxlWd5JHT15_72dOQmFqglWrmJEVX2_-R0ZCelZrejquDJLMGAJV_8YpRD3cWaWDMCalB2Zc7juD4uXCQ
Combine it all together, and you get a complete JWT token which we can now send to Sentry Interactive.
curl 'https://api.doordeck.com/device/ad8fb900-4def-11e8-9370-170748b9fca8/execute' \
-X POST \
-H 'authorization: Bearer TOKEN' \
-H 'content-type: application/jwt' \
--data-binary "$JWT"
Sending this command should trigger the animated virtual door at https://demo.sentryinteractive.com/, don't forget, you may need to update the expiry time of your JWT since generating the initial payload.