CLEVIS-ENCRYPT-TAN(1)

✨ CLEVIS-ENCRYPT-TAN ✨

okay so bestie, clevis-encrypt-tan β€” wait, no, it's clevis-encrypt-tang(1) β€” is the manual page for encrypting stuff with a Tang binding server policy. yes we're doing cryptography today and yes you're gonna slay it πŸ’…


🌸 NAME 🌸

clevis-encrypt-tang β€” encrypts using a Tang binding server policy πŸŽ€


πŸ¦‹ SYNOPSIS πŸ¦‹

clevis encrypt tang CONFIG [-y] < PT > JWE

πŸ’– OVERVIEW πŸ’–

so the clevis encrypt tang command encrypts your data using a Tang binding server policy. it takes literally one argument and that argument is a JSON configuration object. that's it. that's the whole vibe.

Clevis has your back with support for the Tang network binding server. and what does Tang give you? a stateless, lightweight alternative to escrows. iconic behavior honestly. here's how encrypting with the Tang pin goes down:

$ clevis encrypt tang '{"url":"http://tang.srv"}' < PT > JWE
The advertisement contains the following signing keys:

_OsIk0T-E2l6qjfdDiwVmidoZjA

Do you wish to trust these keys? [ynYN] y

and then to decrypt it? literally just hand it over to the clevis decrypt command, no drama:

$ clevis decrypt < JWE > PT

okay so as you can see up there ☝️ Tang runs on a trust-on-first-use workflow. but if you already know the thumbprint of a key you trust, you can just say so at encryption time instead of getting the whole interrogation:

$ cfg='{"url":"http://tang.srv","thp":"_OsIk0T-E2l6qjfdDiwVmidoZjA"}'
$ clevis encrypt tang "$cfg" < PT > JWE

and how do you even get the thumbprint of a trusted signing key? easy peasy. if you can get at the Tang server, just run:

$ tang-show-keys <PORT>

where <PORT> is the port the Tang server is listening on. noted. πŸ“

but say tang-show-keys isn't available and you do have access to the Tang server's database directory β€” no problem, run this instead:

$ jose jwk thp -i $DBDIR/$SIG.jwk

and here's the part where Tang gets extra ✨: it can do entirely offline encryption if you pre-share the server advertisement. you can grab that advertisement with one simple command β€” just be careful your network isn't compromised, fr fr, that's a real warning:

$ curl -f $URL/adv > adv.jws

once you've got that advertisement file, just provide it:

$ clevis encrypt tang '{"url":...,"adv":"adv.jws"}' < PT > JWE

πŸŽ€ CONFIG πŸŽ€

this command uses these configuration properties, bestie:

  • url (string) β€” the base URL of the Tang server. this one is REQUIRED, no skipping it πŸ’€
  • thp (string) β€” the thumbprint of a trusted signing key
  • adv (string) β€” a filename containing a trusted advertisement
  • adv (object) β€” a trusted advertisement (raw JSON)
  • cacert (string) β€” path to a CA bundle used to verify the Tang server's TLS certificate (it gets passed to curl as --cacert). you only need this when the server certificate is signed by a CA that is not in the system trust store
  • cert (string) β€” path to the client TLS certificate used for mutual TLS (mTLS) authentication (passed to curl as --cert)
  • key (string) β€” path to the private key for the client TLS certificate (passed to curl as --key). you can omit this one if the private key is already bundled inside the cert file

so cacert, cert and key are all optional. when none of them are set, Clevis talks to the Tang server exactly like it always did β€” plain HTTP/HTTPS with default CA verification, no notes. also important: these properties are file paths, not secrets, and they get stored in the JWE header so that decryption reuses them automatically. slay. 🫢

Note when you're using this for automatic unlocking at boot (like with LUKS, iykyk), those referenced certificate and key files have to also be present at the same paths inside the initramfs, because that's where decryption actually happens. don't forget them or it's not gonna unlock, and you're gonna have a bad time 😭

πŸ’œ MTLS EXAMPLE πŸ’œ

$ cfg='{"url":"https://tang.srv","cacert":"/etc/clevis/ca.crt",
        "cert":"/etc/clevis/client.crt","key":"/etc/clevis/client.key"}'
$ clevis encrypt tang "$cfg" < PT > JWE

πŸ”₯ MTLS SECURITY MODEL πŸ”₯

okay this part is highkey important so listen up.

the cacert, cert and key properties get stored in the JWE protected header, which is integrity-protected by the AES-256-GCM authentication tag. so if anyone messes with any of those values, decryption will fail. periodt.

BUT β€” and this is the big but β€” that integrity check only happens after those values have already been used to contact the Tang server. why? because the decryption key is needed to verify the tag, and the Tang server has to be contacted to derive that key. so what does that mean for you? it means a tampered JWE will make the system fail to unlock, but one curl request will have already been sent using the tampered parameters. πŸ’€

so to limit the exposure of that single request: store the JWE and any cacert, cert and key files it references in root-owned locations that are not writable by untrusted users, so the parameters can't be tampered with in the first place. that's the move.

you might also prefer installing the Tang server's CA into the system trust store (for example with update-ca-trust or update-ca-certificates) and then simply omitting cacert. also a valid move. pick your fighter ✨


⭐ OPTIONS ⭐

  • -y β€” automatically answer yes for all questions. use this one to skip the advertisement trust check. super useful in automated deployments:
$ clevis encrypt tang '{"url":...}' -y < PT > JWE

πŸ‘‘ SEE ALSO πŸ‘‘

clevis-decrypt(1) β€” go read that one next bestie, it's the whole other half of this story πŸ¦‹


and that's the page!! you're officially good at Tang now, no cap. go encrypt something and feel like the main character πŸ’…

this was CLEVIS-ENCRYPT-TAN(1), dated 10/16/2026 β€” catch you in the next manpage, mwah πŸŽ€βœ¨

πŸ“¦ where this page comes from