trezor-agent
trezor-agent copied to clipboard
Add support for OnlyKey
We forked an old version of trezor-agent back when it just had SSH support and have been using this for OnlyKey: https://docs.crp.to/onlykey-agent.html https://github.com/trustcrypto/onlykey-agent
Thanks by the way, its been working really well. We are looking to update this and since trezor-agent has support for additional hardware now, Ledger and KeepKey, I was wondering if you would accept a PR to add support for OnlyKey as an additional agent in https://github.com/romanz/trezor-agent/tree/master/agents?
I wanted to ask before I do the work to make the changes required to do this.
Thanks!
Sounds good, I will be happy to accept the PR :)
@romanz I have implemented support for OnlyKey, including:
- SSH (ed25519 and nist256p1)
- GPG Sign (ed25519 and nist256p1)
- GPG Decrypt (curve25519 and nist256p1)
Doesn't support the PIN functionality though so I am thinking I will remove those command args that aren't used, OnlyKey has on device PIN entry.
I still have to do more testing before the PR but just wanted to provide the update - https://github.com/romanz/trezor-agent/compare/master...onlykey:onlykey-agent-merge
If you are interested in trying it out I will gladly send over a free onlykey, just shoot an email to t at crp.to with shipping address and I will send one over. Thanks!
@romanz I am looking into implementing RSA support as well for GPG and SSH as onlykey already supports RSA keys, any advice on where to start here? I expect I will need to find a way to parse the pkcs v1.5 blob (256 bytes for RSA 2048 and 512 for RSA 4096).
@romanz I have implemented support for OnlyKey, including: * SSH (ed25519 and nist256p1) * GPG Sign (ed25519 and nist256p1) * GPG Decrypt (curve25519 and nist256p1)
Cool, thanks for the update!
Doesn't support the PIN functionality though so I am thinking I will remove those command args that aren't used, OnlyKey has on device PIN entry.
Sounds good.
I still have to do more testing before the PR but just wanted to provide the update - master...onlykey:onlykey-agent-merge
Looks good overall, will do a full review when you'll open the PR.
@romanz I am looking into implementing RSA support as well for GPG and SSH as onlykey already supports RSA keys, any advice on where to start here?
Good question - since TREZOR et al. don't support RSA, I am not sure how such keys are represented in SSH/GPG...
@romanz I have completed implementing the following features:
- Add support for existing functionality for OnlyKey, derived keys for nist256p1, curve25519, ed25519 for GPG and SSH
- Add support for static keys, some times we have had users ask about not using the derived keys and instead using local keys stored on device. This has been implemented and is used like this:
-dk arg is decryption key -sk arg is signing key
Note: OnlyKey supports 16 static ECC keys (101 -116), and 4 static RSA keys (1-4)
$ onlykey-gpg init "user [email protected]" -sk 102 -dk 101 $ onlykey-agent user@domain -sk 102 -dk 101 $ onlykey-agent user@domain -sk 102 -dk 101 -c
- Add support for RSA keys for SSH. This is used like this: $ onlykey-agent "user [email protected]" -e rsa -sk 2 -dk 1 Note: since RSA keys are not derived -sk and -dk are required
The above is tested and working but I wanted to reach out to see if you have any ideas about what's not working below:
ISSUE#1 - Add support for RSA keys for GPG. Since RSA keys are not derived we just use -i for import existing public key. So import instead of creating pubkey. This works but I run into issue where when it runs gpg2--list-secret-keys none are found:
$ onlykey-gpg init "[email protected] [email protected]" -vv -sk 2 -dk 1 -i public.asc && GPG date | gpg2 --encrypt -r "user" | gpg2 --decrypt
2020-07-16 16:03:54,317 DEBUG run: ['/usr/local/Cellar/gnupg/2.2.20/bin/gpg', '--homedir', '/Users/x/.gnupg/trezor', '--import-ownertrust', '/Users/t/.gnupg/trezor/ownertrust.txt'] [__init__.py:115]
gpg: inserting ownertrust of 6
2020-07-16 16:03:54,326 DEBUG run: ['/usr/local/Cellar/gnupg/2.2.20/bin/gpg', '--homedir', '/Users/x/.gnupg/trezor', '--list-secret-keys', '[email protected] <[email protected]>'] [__init__.py:115]
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: error reading key: No secret key
Traceback (most recent call last):
File "/Users/x/opt/anaconda3/bin/onlykey-gpg", line 8, in <module>
sys.exit(gpg_tool())
File "/Users/x/opt/anaconda3/bin/onlykey_agent.py", line 6, in <lambda>
gpg_tool = lambda: libagent.gpg.main(DeviceType)
File "/Users/x/opt/anaconda3/lib/python3.7/site-packages/libagent/gpg/__init__.py", line 378, in main
return args.func(device_type=device_type, args=args)
File "/Users/x/opt/anaconda3/lib/python3.7/site-packages/libagent/gpg/__init__.py", line 226, in run_init
check_call(keyring.gpg_command(['--homedir', homedir, '--list-secret-keys', args.user_id]))
File "/Users/x/opt/anaconda3/lib/python3.7/site-packages/libagent/gpg/__init__.py", line 116, in check_call
subprocess.check_call(args=args, stdin=stdin, env=env)
File "/Users/x/opt/anaconda3/lib/python3.7/subprocess.py", line 363, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['/usr/local/Cellar/gnupg/2.2.20/bin/gpg', '--homedir', '/Users/x/.gnupg/trezor', '--list-secret-keys', '[email protected] <[email protected]>']' returned non-zero exit status 2.
ISSUE#2 - Lets say we have a private key set in OnlyKey ECC slot 101 and 102, the following will work:
$ onlykey-gpg init "[email protected] [email protected]" -vv -sk 102 -dk 101 && GPG date | gpg2 --encrypt -r "crptest" | gpg2 --decrypt
2020-07-16 16:11:33,927 DEBUG out: 'tru::1:1594930292:0:3:1:5\npub:-:256:22:345940EB83C97E97:0:::-:::scESC:::::ed25519:::0:\nfpr:::::::::C9A19C19C78B5D2041EE28C9345940EB83C97E97:\nuid:-::::::F94409DBA3D6194724C58F73630C3740E10B7310::[email protected] <[email protected]>::::::::::0:\nsub:-:256:18:D2831D730E2264B5:0::::::e:::::cv25519::\nfpr:::::::::B91801058E7F937EADB00597D2831D730E2264B5:\n' [__init__.py:109]
2020-07-16 16:11:33,928 DEBUG setting /Users/t/.gnupg/trezor/ownertrust.txt contents:
C9A19C19C78B5D2041EE28C9345940EB83C97E97:6
[__init__.py:122]
2020-07-16 16:11:33,928 DEBUG run: ['/usr/local/Cellar/gnupg/2.2.20/bin/gpg', '--homedir', '/Users/t/.gnupg/trezor', '--import-ownertrust', '/Users/t/.gnupg/trezor/ownertrust.txt'] [__init__.py:115]
gpg: inserting ownertrust of 6
2020-07-16 16:11:33,936 DEBUG run: ['/usr/local/Cellar/gnupg/2.2.20/bin/gpg', '--homedir', '/Users/t/.gnupg/trezor', '--list-secret-keys', '[email protected] <[email protected]>'] [__init__.py:115]
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
sec ed25519 1970-01-01 [SC]
C9A19C19C78B5D2041EE28C9345940EB83C97E97
uid [ultimate] [email protected] <[email protected]>
ssb cv25519 1970-01-01 [E]
gpg: WARNING: no command supplied. Trying to guess what you mean ...
gpg: can't open 'date'
gpg: WARNING: cipher algorithm AES256 not found in recipient preferences
gpg: encrypted with 256-bit ECDH key, ID D2831D730E2264B5, created 1970-01-01
"[email protected] <[email protected]>"
So then without changing anything we try and import the pubkey instead of creating it, everything is the same except the PGP key id/date. It gets this error:
$ onlykey-gpg init "[email protected] [email protected]" -vv -sk 102 -dk 101 -i [email protected] && GPG date | gpg2 --encrypt -r "crptest" | gpg2 --decrypt
2020-07-16 16:12:31,557 DEBUG out: 'tru::1:1594930350:0:3:1:5\npub:-:256:22:FDCABBD34C763B10:1594041052:::-:::scESC:::::ed25519:::0:\nfpr:::::::::BA28DF0123F2A9AA72255790FDCABBD34C763B10:\nuid:-::::1594041052::F94409DBA3D6194724C58F73630C3740E10B7310::[email protected] <[email protected]>::::::::::0:\nsub:-:256:18:BE3EA7B2ED208930:1594041052::::::e:::::cv25519::\nfpr:::::::::F83A3D33BEBD6E6C9C57E5A4BE3EA7B2ED208930:\n' [__init__.py:109]
2020-07-16 16:12:31,558 DEBUG setting /Users/t/.gnupg/trezor/ownertrust.txt contents:
BA28DF0123F2A9AA72255790FDCABBD34C763B10:6
[__init__.py:122]
2020-07-16 16:12:31,559 DEBUG run: ['/usr/local/Cellar/gnupg/2.2.20/bin/gpg', '--homedir', '/Users/t/.gnupg/trezor', '--import-ownertrust', '/Users/t/.gnupg/trezor/ownertrust.txt'] [__init__.py:115]
gpg: inserting ownertrust of 6
2020-07-16 16:12:31,570 DEBUG run: ['/usr/local/Cellar/gnupg/2.2.20/bin/gpg', '--homedir', '/Users/t/.gnupg/trezor', '--list-secret-keys', '[email protected] <[email protected]>'] [__init__.py:115]
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
sec ed25519 2020-07-06 [SC]
BA28DF0123F2A9AA72255790FDCABBD34C763B10
uid [ultimate] [email protected] <[email protected]>
ssb cv25519 2020-07-06 [E]
gpg: WARNING: no command supplied. Trying to guess what you mean ...
gpg: can't open 'date'
gpg: ecdh failed in gcry_cipher_decrypt: Checksum error
gpg: encrypted with 256-bit ECDH key, ID BE3EA7B2ED208930, created 2020-07-06
"[email protected] <[email protected]>"
gpg: public key decryption failed: Checksum error
gpg: decryption failed: No secret key
Seems similar to the RSA issue, but here it prompts for and receives the ECDH value, its just not matching what it expected (Checksum error). Any ideas on what needs to change here? The reason I would like to support this is so that users can bring and use existing keys from services like protonmail and it will work with the agent and generate valid signatures that you could then use with other services.
Any guidance would be greatly appreciated. https://github.com/onlykey/trezor-agent/tree/onlykey-agent-merge
@romanz Also I replaced the ed25519 library with pynacl as ed25519 library has to compile from source and doesn't work on windows without dev tools and they say this here - https://pypi.org/project/ed25519/ "Not Recommended For New Applications: Use pynacl Instead"
FYI, GPG created curve25519 keys are flipped backwards pretty sure that will fix my ISSUE2 - http://gnupg.10057.n7.nabble.com/Correct-method-to-generate-a-Curve25519-keypair-td56013.html
@romanz Also I replaced the ed25519 library with pynacl as ed25519 library has to compile from source and doesn't work on windows without dev tools and they say this here - https://pypi.org/project/ed25519/ "Not Recommended For New Applications: Use pynacl Instead"
Many thanks! Would it be possible to split this into a separate PR please?
I would be happy to review and merge first the nist256p1, curve25519, ed25519 SSH and GPG support (without the RSA and static keys support for now).
Would it possible to split those into a separate PR (rebased over the pynacl
PR)?
@romanz sorry for delay, I just saw your response here. I have everything working now (except import RSA keys for GPG) and the full PR ready, I will break this up into multiple PRs as you suggested.
@romanz Just wanted to check on the PR. Does everything look good and do you know when you would be able to merge this?
Thanks!
Sorry, I missed the notification - will take a look tomorrow.
I don't think the full support has landed yet, has it? I don't see implementation for -sk
in #337.