Trezorctl encrypt-keyvalue and decrypt-keyvalue

I find trezorctl’s documentation somewhat lacking, so I’m asking your help to figure things out regarding encrypt-keyvalue and decrypt-keyvalue (I did read SLIP-0011). the context is using them from the command line with a trezorctl installed through PyPI.

  1. when I enter KEY and VALUE, what is the character encoding used for interpreting the input?
  2. does the encoding change if I wrap KEY or VALUE in quotes?
  3. if I don’t want to use a KEY, is there a better way of doing that than an empty string argument ("")?
  4. what was the motivation behind using KEY as a secondary encryption key, i.e. a parameter that affects the ciphertext?
  5. how can I define the initialization vector?
1 Like

KEY is UTF-8, but Trezor can only display the ASCII range.

VALUE is hex encoding.

No, this is normal shell command. Quotes will be invisible to trezorctl unless you make an extra effort (in which case they will become a literal part of KEY, or be an invalid character of VALUE)

No. But the point of KEY is to be shown on Trezor, and even if you use the no-prompt variant (which you can’t currently do), there is zero reason not to specify a key.

The key is something you show on Trezor screen - this is where “Enable labeling?” in Suite comes from, and Trezor Password Manager is also using SLIP-11 for encryption.
So it would be irresponsible to make it not affect the encryption. Say you want to trick the user into decrypting their Suite labels, you just raise a prompt on Trezor saying “Claim your reward?” and it would covertly decrypt the labels.

Looks like trezorctl won’t let you do it.
But the functionality is present in trezorlib. You could write a simple script to pass the IV in; have a look at or other things in the tools/ directory.



I noticed I can enter (at least) ASCII for VALUE. which encoding is used for turning that text into hex?

there is at least one: you don’t have to remember it.

good point.

1 Like

Ah, that’s because I’m wrong. encrypt-keyvalue accepts an UTF-8 string. (though technically whatever your locale is set to, I think?)
decrypt-keyvalue accepts hex-encoded raw bytes that were the result of encrypt-keyvalue.

You still need to remember that it’s an empty string :woman_shrugging:

Do it like I do it, write a script and put it in a github gist, like so: Restic backup password generated by Trezor · GitHub
All this info is public: the derivation path, the key, in my usecase the value as well. Trezor encrypts the zero bytes and gives me a secret key in return that you can’t guess without my seed.

Speaking of, you can take this script as a template if you want to mess with the IV.

1 Like

I have an English locale. trezorctl apparently uses something else than 1-byte UTF-8 for non-ASCII characters because I can encrypt passwordpassword, but not pässwordpässword (both 16 characters long and “ä” is within the 1-byte UTF-8 range).

correct – just wanted to add that decrypt-keyvalue’s KEY also accepts ASCII/UTF-8/whatever it is that we couldn’t yet identify.

that’s the easiest to remember, a default value if you will.

I like your optimism that you think GitHub will always be available :slight_smile:

it’s not trezorctl but your shell making that choice

not sure why you think that? ä is codepoint 0xE4 which is > 128 and therefore two UTF-8 bytes. Only (non-extended) ASCII characters have 1-byte encoding.



my bad. I had the impression that U+0080U+00FF Unicode code points use the remaining 80ff bytes in the 1-byte space, which is apparently not the case.