default, a certificate "needs renewal" when it has passed 66% (default threshold) of its allotted lifetime. This threshold can be adjusted using the '--expires-in' flag. Additionally, by default only the leaf certificate will be checked by the command; to check each certificate in the chain use the '--bundle' flag. ## POSITIONAL ARGUMENTS : The path to a certificate OR a hostname with protocol prefix. ## EXIT CODES This command returns '0' if the X509 certificate needs renewal, '1' if the X509 certificate does not need renewal, '2' if the X509 certificate file does not exist, and '255' for any other error. ## EXAMPLES Check if the leaf certificate in the file certificate.crt has passed 66 percent of its validity period: ''' $ step certificate needs-renewal ./certificate.crt ''' Check if any certificate in the bundle has passed 66 percent of its validity period: ''' $ step certificate needs-renewal ./certificate.crt --bundle ''' Check if the leaf certificate provided by smallstep.com has passed 66 percent of its vlaidity period: ''' $ step certificate needs-renewal https://smallstep.com ''' Check if any certificate in the bundle for smallstep.com has has passed 66 percent of its validity period: ''' $ step certificate needs-renewal https://smallstep.com --bundle ''' Check if certificate.crt expires within 1 hour 15 minutes from now: ''' $ step certificate needs-renewal ./certificate.crt --expires-in 1h15m ''' Check if certificate for smallstep.com is expired or not: ''' $ step certificate needs-renewal https://smallstep.com --expires-in 0s ''' Check if certificate has passed 75 percent of its validity period: ''' $ step certificate needs-renewal ./certificate.crt --expires-in 75% ''' Check a remote certificate using a custom root certificate: ''' $ step certificate needs-renewal https://smallstep.com --roots ./root-ca.crt ''' Check a remote certificate using a custom list of root certificates: ''' $ step certificate needs-renewal https://smallstep.com \ --roots "./root-ca.crt,./root-ca2.crt,/root-ca3.crt" ''' Check a remote certificate using a custom directory of root certificates: ''' $ step certificate needs-renewal https://smallstep.com \ --roots "./path/to/root/certificates/" ''' **step ca sign** command signs the given csr and generates a new certificate. ## POSITIONAL ARGUMENTS : File with the certificate signing request (PEM format) : File to write the certificate (PEM format) ## EXAMPLES Sign a new certificate for the given CSR: ''' $ TOKEN=$(step ca token internal.example.com) $ step ca sign --token $TOKEN internal.csr internal.crt ''' Sign a new certificate with a 1h validity: ''' $ TOKEN=$(step ca token internal.example.com) $ step ca sign --token $TOKEN --not-after=1h internal.csr internal.crt ''' Sign a new certificate using the offline mode, requires the configuration files, certificates, and keys created with **step ca init**: ''' $ step ca sign --offline internal internal.csr internal.crt ''' Sign a new certificate using the offline mode with additional flag to avoid console prompts: ''' $ step ca sign --offline --password-file ./pass.txt internal internal.csr internal.crt ''' Sign a new certificate using an X5C provisioner: NOTE: You must have a X5C provisioner configured (using **step ca provisioner add**). ''' $ step ca sign foo.internal foo.csr foo.crt --x5c-cert leaf-x5c.crt --x5c-key leaf-x5c.key ''' **Certificate Templates** - With a provisioner configured with a custom template we can use the **--set** flag to pass user variables: ''' $ step ca sign foo.csr foo.crt --set dnsNames=foo.internal.com $ step ca sign foo.csr foo.crt --set dnsNames='["foo.internal.com","bar.internal.com"]' ''' Or you can pass them from a file using **--set-file**: ''' $ cat path/to/data.json { "dnsNames": ["foo.internal.com","bar.internal.com"] } $ step ca sign foo.csr foo.crt --set-file path/to/data.json ''' **step CA ACME** - In order to use the step CA ACME protocol you must add a ACME provisioner to the step CA config. See **step ca provisioner add -h**. Sign a CSR using the step CA ACME server and a standalone server to serve the challenges locally (standalone mode is the default): ''' $ step ca sign foo.csr foo.crt --provisioner my-acme-provisioner ''' Sign a CSR using the step CA ACME server and an existing server along with webroot mode to serve the challenges locally: ''' $ step ca sign foo.csr foo.crt \ --provisioner my-acme-provisioner --webroot "./acme-www" \ ''' Sign a CSR using the ACME protocol served by another online CA (not step CA, e.g. letsencrypt). NOTE: Let's Encrypt requires that the Subject Common Name of a requested certificate be validated as an Identifier in the ACME order along with any other SANS. Therefore, the Common Name must be a valid DNS Name. The step CA does not impose this requirement. ''' $ step ca sign foo.csr foo.crt \ --acme https://acme-staging-v02.api.letsencrypt.org/directory '''**step certificate inspect** prints the details of the certificate or CSR in a human- or machine-readable format. Beware: Local certificates are never verified. Always verify a certificate (using **step certificate verify**) before relying on the output of this command. If crt-file contains multiple certificates (i.e., it is a certificate "bundle") the first certificate in the bundle will be output. Pass the --bundle option to print all certificates in the order in which they appear in the bundle. ## POSITIONAL ARGUMENTS : Path to a certificate or certificate signing request (CSR) to inspect. A hyphen ("-") indicates STDIN as . ## EXIT CODES This command returns 0 on success and \>0 if any error occurs. ## EXAMPLES Inspect a local certificate (default to text format): ''' $ step certificate inspect ./certificate.crt ''' Inspect a local certificate bundle (default to text format): ''' $ step certificate inspect ./certificate-bundle.crt --bundle ''' Inspect a local certificate in json format: ''' $ step certificate inspect ./certificate.crt --format json ''' Inspect a local certificate bundle in json format: ''' $ step certificate inspect ./certificate.crt --format json --bundle ''' Inspect a remote certificate (using the default root certificate bundle to verify the server): ''' $ step certificate inspect https://smallstep.com ''' Inspect a remote certificate (using the standard port derived from the URL prefix): ''' $ step certificate inspect smtps://smtp.gmail.com ''' Inspect an invalid remote certificate: ''' $ step certificate inspect --insecure https://expired.badssl.com ''' Inspect a remote certificate chain (using the default root certificate bundle to verify the server): ''' $ step certificate inspect https://google.com --bundle ''' Inspect a remote certificate using a custom root certificate to verify the server: ''' $ step certificate inspect https://smallstep.com --roots ./root-ca.crt ''' Inspect a remote certificate using a custom list of root certificates to verify the server: ''' $ step certificate inspect https://smallstep.com \ --roots "./root-ca.crt,./root-ca2.crt,/root-ca3.crt" ''' Inspect a remote certificate using a custom directory of root certificates to verify the server: ''' $ step certificate inspect https://smallstep.com \ --roots "./path/to/root/certificates/" ''' Inspect a remote certificate chain in json format using a custom directory of root certificates to verify the server: ''' $ step certificate inspect https://google.com --format json \ --roots "./path/to/root/certificates/" --bundle ''' Inspect a remote certificate chain in PEM format: ''' $ step certificate inspect https://smallstep.com --format pem --bundle ''' Inspect a local CSR in text format (default): ''' $ step certificate inspect foo.csr ''' Inspect a local CSR in json: ''' $ step certificate inspect foo.csr --format json ''' 2.302585092994045684017991454684364207601101488628772976033327900967572609677352480235997205089598298341967784042286248633409525465082806756666287369098781689482907208325554680843799894826233198528393505308965377732628846163366222287698219886746543667474404243274365155048934314939391479619404400222105101714174800368808401264708068556774321622835522011480466371565912137345074785694768346361679210180644507064800027750268491674655058685693567342067058113642922455440575892572420824131469568901675894025677631135691929203337658714166023010570308963457207544037084746994016826928280848118428931484852494864487192780967627127577539702766860595249671667418348570442250719796500471495105049221477656763693866297697952211071826454973477266242570942932258279850258550978526538320760672631716430950599508780752371033310119785754733154142180842754386359177811705430982748238504564801909561029929182431823752535770975053956518769751037497088869218020518933950723853920514463419726528728696511086257149219884997874887377134568620916705849807828059751193854445009978131146915934666241071846692310107598438319191292230792503747298650929009880391941702654416816335727555703151596113564846546190897042819763365836983716328982174407366009162177850541779276367731145041782137660111010731042397832521894898817597921798666394319523936855916447118246753245630912528778330963604262982153040874560927760726641354787576616262926568298704957954913954918049209069438580790032763017941503117866862092408537949861264933479354871737451675809537088281067452440105892444976479686075120275724181874989395971643105518848195288330746699317814634930000321200327765654130472621883970596794457943468343218395304414844803701305753674262153675579814770458031413637793236291560128185336498466942261465206459942072917119370602444929358037007718981097362533224548366988505528285966192805098447175198503666680874970496982273220244823343097169111136813588418696549323714996941979687803008850408979618598756579894836445212043698216415292987811742973332588607915912510967187510929248475023930572665446276200923068791518135803477701295593646298412366497023355174586195564772461857717369368404676577047874319780573853271810933883496338813069945569399346101090745616033312247949360455361849123333063704751724871276379140924398331810164737823379692265637682071706935846394531616949411701841938119405416449466111274712819705817783293841742231409930022911502362192186723337268385688273533371925103412930705632544426611429765388301822384091026198582888433587455960453004548370789052578473166283701953392231047527564998119228742789713715713228319641003422124210082180679525276689858180956119208391760721080919923461516952599099473782780648128058792731993893453415320185969711021407542282796298237068941764740642225757212455392526179373652434440560595336591539160312524480149313234572453879524389036839236450507881731359711238145323701508413491122324390927681724749607955799151363982881058285740538000653371655553014196332241918087621018204919492651483892The intended for use with this key. Corresponds to the **"alg"** JWK parameter. is case-sensitive. If unset, the default depends on the key use, key type, and curve (for EC and OKP keys). Defaults are: : | key type | use | curve | default algorithm | |----------|-----|---------|-------------------| | EC | sig | P-256 | ES256 | | EC | sig | P-384 | ES384 | | EC | sig | P-521 | ES512 | | oct | sig | N/A | HS256 | | RSA | sig | N/A | RS256 | | OKP | sig | Ed25519 | EdDSA | | EC | enc | P-256 | ECDH-ES | | EC | enc | P-384 | ECDH-ES | | EC | enc | P-521 | ECDH-ES | | oct | enc | N/A | A256GCMKW | | RSA | enc | N/A | RSA-OAP-256 | : If the key **"use"** is **"sig"** (signing) must be one of: **HS256** : HMAC using SHA-256 **HS384** : HMAC using SHA-384 **HS512** : HMAC using SHA-512 **RS256** : RSASSA-PKCS1-v1_5 using SHA-256 **RS384** : RSASSA-PKCS1-v1_5 using SHA-384 **RS512** : RSASSA-PKCS1-v1_5 using SHA-512 **ES256** : ECDSA using P-256 and SHA-256 **ES384** : ECDSA using P-384 and SHA-384 **ES512** : ECDSA using P-521 and SHA-512 **PS256** : RSASSA-PSS using SHA-256 and MGF1 with SHA-256 **PS384** : RSASSA-PSS using SHA-384 and MGF1 with SHA-384 **PS512** : RSASSA-PSS using SHA-512 and MGF1 with SHA-512 **EdDSA** : EdDSA signature algorithm : If the key **"use"** is **"enc"** (encryption) must be one of: **RSA1_5** : RSAES-PKCS1-v1_5 **RSA-OAEP** : RSAES OAEP using default parameters **RSA-OAEP-256** : RSAES OAEP using SHA-256 and MGF1 with SHA-256 **A128KW** : AES Key Wrap with default initial value using 128-bit key **A192KW** : AES Key Wrap with default initial value using 192-bit key **A256KW** : AES Key Wrap with default initial value using 256-bit key **dir** : Direct use of a shared symmetric key as the content encryption key (CEK) **ECDH-ES** : Elliptic Curve Diffie-Hellman Ephemeral Static key agreement **ECDH-ES+A128KW** : ECDH-ES using Concat KDF and CEK wrapped with "A128KW" **ECDH-ES+A192KW** : ECDH-ES using Concat KDF and CEK wrapped with "A192KW" **ECDH-ES+A256KW** : ECDH-ES using Concat KDF and CEK wrapped with "A256KW" **A128GCMKW** : Key wrapping with AES GCM using 128-bit key **A192GCMKW** : Key wrapping with AES GCM using 192-bit key **A256GCMKW** : Key wrapping with AES GCM using 256-bit key **PBES2-HS256+A128KW** : PBES2 with HMAC SHA-256 and "A128KW" wrapping **PBES2-HS384+A192KW** : PBES2 with HMAC SHA-256 and "A192KW" wrapping **PBES2-HS512+A256KW** : PBES2 with HMAC SHA-256 and "A256KW" wrapping **step ca revoke** command revokes a certificate with the given serial number. **Active Revocation**: A certificate is no longer valid from the moment it has been actively revoked. Clients are required to check against centralized sources of certificate validity information (e.g. by using CRLs (Certificate Revocation Lists) or OCSP (Online Certificate Status Protocol)) to verify that certificates have not been revoked. Active Revocation requires clients to take an active role in certificate validation for the benefit of real time revocation. **Passive Revocation**: A certificate that has been passively revoked can no longer be renewed. It will still be valid for the remainder of it's validity period, but cannot be prolonged. The benefit of passive revocation is that clients can verify certificates in a simple, decentralized manner without relying on centralized 3rd parties. Passive revocation works best with short certificate lifetimes. A revocation request can be authorized using a JWK provisioner token, or using a client certificate. When you supply a serial number, you're prompted to choose a provisioner, and a provisioner token is transparently generated. Any JWK provisioner can revoke any certificate. When you supply a certificate and private key (with --crt and --key), mTLS is used to authorize the revocation. Certificates generated using an OIDC provisioner cannot be revoked by their serial number. ## POSITIONAL ARGUMENTS : The serial number of the certificate that should be revoked. Can be left blank, either to be supplied by prompt, or when using the --cert and --key flags for revocation over mTLS. ## EXAMPLES Revoke a certificate using a transparently generated JWK provisioner token and the default 'unspecified' reason: ''' $ step ca revoke 308893286343609293989051180431574390766 ''' Revoke a certificate using a transparently generated token and configured reason and reasonCode: ''' $ step ca revoke --reason "laptop compromised" --reasonCode 1 308893286343609293989051180431574390766 ''' Revoke a certificate using a transparently generated token and configured reason and stringified reasonCode: ''' $ step ca revoke --reason "laptop compromised" --reasonCode "key compromise" 308893286343609293989051180431574390766 ''' Revoke a certificate using that same certificate to validate and authorize the request (rather than a token) over mTLS: ''' $ step ca revoke --cert mike.cert --key mike.key ''' Revoke a certificate using a JWK token, pre-generated by a provisioner, to authorize the request with the CA: ''' $ TOKEN=$(step ca token --revoke 308893286343609293989051180431574390766) $ step ca revoke --token $TOKEN 308893286343609293989051180431574390766 ''' Revoke a certificate in offline mode: ''' $ step ca revoke --offline 308893286343609293989051180431574390766 ''' Revoke a certificate in offline mode using --cert and --key (the cert/key pair will be validated against the root and intermediate certificates configured in the step CA): ''' $ step ca revoke --offline --cert foo.crt --key foo.key '''**step ca provisioner add** adds a provisioner to the CA configuration. ## POSITIONAL ARGUMENTS : The name of the provisioner. ## EXAMPLES Create a JWK provisioner with newly generated keys and a template for x509 certificates: ''' step ca provisioner add cicd --type JWK --create --x509-template ./templates/example.tpl ''' Create a JWK provisioner and explicitly select the configuration file to update: ''' step ca provisioner add cicd --type JWK --create --ca-config /path/to/ca.json ''' Create a JWK provisioner with duration claims: ''' step ca provisioner add cicd --type JWK --create --x509-min-dur 20m --x509-default-dur 48h --ssh-user-min-dur 17m --ssh-host-default-dur 16h ''' Create a JWK provisioner with existing keys: ''' step ca provisioner add jane@doe.com --type JWK --public-key jwk.pub --private-key jwk.priv ''' Create an OIDC provisioner: ''' step ca provisioner add Google --type OIDC --ssh \ --client-id 1087160488420-8qt7bavg3qesdhs6it824mhnfgcfe8il.apps.googleusercontent.com \ --client-secret udTrOT3gzrO7W9fDPgZQLfYJ \ --configuration-endpoint https://accounts.google.com/.well-known/openid-configuration ''' Create an X5C provisioner: ''' step ca provisioner add x5c --type X5C --x5c-roots x5c_ca.crt ''' Create an ACME provisioner: ''' step ca provisioner add acme --type ACME ''' Create an ACME provisioner, forcing a CN and requiring EAB: ''' step ca provisioner add acme --type ACME --force-cn --require-eab ''' Create an ACME provisioner for device attestation: ''' step ca provisioner add attestation --type ACME --challenge device-attest-01 ''' Create an K8SSA provisioner: ''' step ca provisioner add kube --type K8SSA --ssh --public-key key.pub ''' Create an SSHPOP provisioner for renewing SSH host certificates:") ''' step ca provisioner add sshpop --type SSHPOP ''' Create a SCEP provisioner with 'secret' challenge and AES-256-CBC encryption: ''' step ca provisioner add my_scep_provisioner --type SCEP --challenge secret --encryption-algorithm-identifier 2 ''' Create an Azure provisioner with two resource groups, one subscription ID and one object ID: ''' $ step ca provisioner add Azure --type Azure \ --azure-tenant bc9043e2-b645-4c1c-a87a-78f8644bfe57 \ --azure-resource-group identity --azure-resource-group accounting \ --azure-subscription-id dc760a01-2886-4a84-9abc-f3508e0f87d9 \ --azure-object-id f50926c7-abbf-4c28-87dc-9adc7eaf3ba7 ''' Create a GCP provisioner that will only accept the SANs provided in the identity token: ''' $ step ca provisioner add Google --type GCP \ --disable-custom-sans --gcp-project internal ''' Create a GCP provisioner that can be used across all projects within an organization: ''' $ step ca provisioner add Google --type GCP --gcp-organization 123456789 ''' Create an AWS provisioner that will only accept the SANs provided in the identity document and will allow multiple certificates from the same instance: ''' $ step ca provisioner add Amazon --type AWS \ --aws-account 123456789 --disable-custom-sans --disable-trust-on-first-use ''' Create an AWS provisioner that will use a custom certificate to validate the instance identity documents: ''' $ step ca provisioner add Amazon --type AWS \ --aws-account 123456789 '''**step certificate sign** generates a signed certificate from a certificate signing request (CSR). ## POSITIONAL ARGUMENTS : The path to a certificate signing request (CSR) to be signed. : The path to an issuing certificate. : The path to a private key for signing the CSR. ## EXIT CODES This command returns 0 on success and \>0 if any error occurs. ## EXAMPLES Sign a certificate signing request using the leaf profile: ''' $ step certificate sign leaf.csr issuer.crt issuer.key # or $ step certificate sign --profile leaf leaf.csr issuer.crt issuer.key ''' Sign a CSR and bundle the new certificate with the issuer: ''' $ step certificate sign --bundle leaf.csr issuer.crt issuer.key ''' Sign a CSR with custom validity and bundle the new certificate with the issuer: ''' $ step certificate sign --bundle --not-before -1m --not-after 16h leaf.csr issuer.crt issuer.key ''' Sign a CSR but do not add the Common Name to the SANs extension of the certificate: ''' $ step certificate sign --omit-cn-san leaf.csr issuer.crt issuer.key ''' Sign an intermediate ca: ''' $ step certificate sign --profile intermediate-ca intermediate.csr issuer.crt issuer.key ''' Sign an intermediate ca that can sign other intermediates; in this example, the issuer must set the pathLenConstraint at least to 2 or without a limit: ''' $ step certificate sign --profile intermediate-ca --path-len 1 intermediate.csr issuer.crt issuer.key ''' Sign a CSR but only use information present in it, it doesn't add any key or extended key usages if they are not in the CSR. ''' $ step certificate sign --profile csr test.csr issuer.crt issuer.key ''' Sign a CSR with only clientAuth as key usage using a template: ''' $ cat coyote.tpl { "subject": { "country": "US", "organization": "Coyote Corporation", "commonName": "{{ .Subject.CommonName }}" }, "emailAddresses": {{ toJson .Insecure.CR.EmailAddresses }}, "keyUsage": ["digitalSignature"], "extKeyUsage": ["clientAuth"] } $ step certificate create --csr coyote@acme.corp coyote.csr coyote.key $ step certificate sign --template coyote.tpl coyote.csr issuer.crt issuer.key ''' Sign a CSR using a template and allow configuring the subject using the **--set** and **--set-file** flags. ''' $ cat rocket.tpl { "subject": { "country": {{ toJson .Insecure.User.country }}, "organization": {{ toJson .Insecure.User.organization }}, "organizationalUnit": {{ toJson .Insecure.User.organizationUnit }}, "commonName": {{toJson .Subject.CommonName }} }, "sans": {{ toJson .SANs }}, {{- if typeIs "*_rsa.PublicKey" .Insecure.CR.PublicKey }} "keyUsage": ["keyEncipherment", "digitalSignature"], {{- else }} "keyUsage": ["digitalSignature"], {{- end }} "extKeyUsage": ["serverAuth", "clientAuth"] } $ cat organization.json { "country": "US", "organization": "Acme Corporation", "organizationUnit": "HQ" } $ step certificate create --csr rocket.acme.corp rocket.csr rocket.key $ step certificate sign --template rocket.tpl \ --set-file organization.json --set organizationUnit=Engineering \ rocket.csr issuer.crt issuer.key ''' Sign a CSR using : ''' $ step certificate sign \ --kms 'pkcs11:module-path=/usr/local/lib/softhsm/libsofthsm2.so;token=smallstep?pin-value=password' \ leaf.csr issuer.crt 'pkcs11:id=4001' ''' **step crypto nacl box** command group uses public-key cryptography to encrypt, decrypt and authenticate messages. The implementation is based on NaCl's crypto_box function. NaCl crypto_box function is designed to meet the standard notions of privacy and third-party unforgeability for a public-key authenticated-encryption scheme using nonces. For formal definitions see, e.g., Jee Hea An, "Authenticated encryption in the public-key setting: security notions and analyzes," https://eprint.iacr.org/2001/079. Distinct messages between the same (sender, receiver) set are required to have distinct nonces. For example, the lexicographically smaller public key can use nonce 1 for its first message to the other key, nonce 3 for its second message, nonce 5 for its third message, etc., while the lexicographically larger public key uses nonce 2 for its first message to the other key, nonce 4 for its second message, nonce 6 for its third message, etc. Nonces are long enough that randomly generated nonces have negligible risk of collision. There is no harm in having the same nonce for different messages if the (sender, receiver) sets are different. This is true even if the sets overlap. For example, a sender can use the same nonce for two different messages if the messages are sent to two different public keys. By default nonces are alphanumeric, but it's possible to use binary nonces using the prefix 'base64:' and the standard base64 encoding of the data, e.g. 'base64:081D3pFPBkwx1bURR9HQjiYbAUxigo0Z'. The prefix 'string:' is also accepted, but it will be equivalent to not using a prefix. Nonces cannot be longer than 24 bytes. NaCl crypto_box is not meant to provide non-repudiation. On the contrary: they guarantee repudiability. A receiver can freely modify a boxed message, and therefore cannot convince third parties that this particular message came from the sender. The sender and receiver are nevertheless protected against forgeries by other parties. In the terminology of https://groups.google.com/group/sci.crypt/msg/ec5c18b23b11d82c, NaCl crypto_box uses "public-key authenticators" rather than "public-key signatures." Users who want public verifiability (or receiver-assisted public verifiability) should instead use signatures (or signcryption). NaCl crypto_box is curve25519xsalsa20poly1305, a particular combination of Curve25519, Salsa20, and Poly1305 specified in "Cryptography in NaCl". This function is conjectured to meet the standard notions of privacy and third-party unforgeability. These commands are interoperable with NaCl: https://nacl.cr.yp.to/box.html ## EXAMPLES Create a keypair for encrypting/decrypting messages: ''' # Bob $ step crypto nacl box keypair bob.box.pub bob.box.priv # Alice $ step crypto nacl box keypair alice.box.pub alice.box.priv ''' Bob encrypts a message for Alice using her public key and signs it using his private key: ''' $ echo message | step crypto nacl box seal nonce alice.box.pub bob.box.priv 0oM0A6xIezA6iMYssZECmbMRQh77mzDt ''' Alice receives the encrypted message and the nonce and decrypts with her private key and validates the message from Bob using his public key: ''' $ echo 0oM0A6xIezA6iMYssZECmbMRQh77mzDt | step crypto nacl box open nonce bob.box.pub alice.box.priv message ''' Decrypt the message using a base64 nonce: ''' $ echo 0oM0A6xIezA6iMYssZECmbMRQh77mzDt | step crypto nacl box open base64:bm9uY2U= bob.box.pub alice.box.priv message '''