Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Signing and Authentication subkeys #358

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

jrruethe
Copy link

@jrruethe jrruethe commented Aug 9, 2021

This pull request is for adding a Signing subkey and an Authentication subkey, in addition to the existing Encryption subkey. It also changes the Primary key to be Certify only. This structure matches best practices found here and here.

One of the benefits of this structure is that it becomes possible to use the Trezor to deterministically generate the Primary and Subkeys, use the included recovery script to mimic the generation and recover the secret portions (suggested to only do this in an offline Tails environment), then move the secret subkeys to a smartcard device like a Yubikey 5. This allows one to achieve the security and determinism of the Trezor (especially when utilizing Shamir), while maintaining the compatability and convienience of a smartcard like the Yubikey. Note that with this scheme, the Primary (certifying) key remains completely offline, and is not intended to be used.

The current code creates a Primary key with Certify and Sign capabilities, and a single Encryption Subkey. The Primary key uses SLIP 13, while the Encryption Subkey uses SLIP 17. Both use derivation index 0 of their respective schemes. The code uses a single boolean named ecdh to differentiate the two.

This pull request adds an enum named KeyFlags. This enum accomplishes 3 things simultaneously:

  • Determines the capabilities of the keys
  • Determines the derivation index
  • Determines the curve algorithm

The derivation index comes into play because we want the Primary Key, Signing Subkey, and Authentication Subkey to all be different. I chose to use derivation indices 0, 1, 2 for these respectively. The derivation index is normally passed to the Trezor via the IdentityType message, using a field named index. Currently, this value is not set by trezor-agent, so it defaults to 0. In order for _identity_proto to properly set the index, it needs to be available in the identity_dict of the Identity class. Per SLIP 13/17, the derivation index is separate from the identity_str (RFC 3986 URI), therefore the index is derived from a KeyFlag parameter added to the constructor. This change does end up rippling through some code, notably necessatating an Identity for each Public Key created in init.

A majority of the rest of the changes involve replacing the ecdh variable with the KeyFlags enum and adjusting functions and calls accordingly.

A second change was needed to accomplish the goal. Now that multiple subkeys (and therefore multiple KeyFlags) are at play, the decode class needed to be able to parse these KeyFlags from the keys. The KeyFlags are stored inside the hashed area of the signature packets for a key. According to page 69 of RFC 4880, the signature packet always follows the pubkey/subkey packet, so the load_by_keygrip was rewritten to map them together and return it to get_identity. A unit test was added for this.

Finally, gpg version 2.1.14 adds a new subpacket type 33, which is not part of RFC 4880 (and has caused some problems for other clients). It is used for verifying cross-certification of signing subkeys, and is only specifically required for signing subkeys (not authentication subkeys, this was verified by using gpg to generate a new key with subkeys, then dump the packets). Here are some handy links:

That last link shows a "gotcha", where the signature creation date must be greater than 0 for gpg to register it as a cross-certification signature. I chose to add 1 to the embedded signature creation time. This does not affect the public keys themselves.

Lastly, I rearranged some fields to match the same order that gpg produces, refactored libagent/gpg/__init__.py since the inclusion of the subkeys has introduced some repetition.

I did multiple tests to ensure backward compatability. First, I wiped a Trezor and initialized it with a mnemonic of all all all all all all all all all all all all. Then, I used the current version of trezor-agent to both sign and encrypt a file.

Next, I used the version of trezor-agent from this pull request to both verify and decrypt the file, using the "normal" key layout. The fingerprints and keygrips were also compared and found to be the same. Afterwards, I did the test again by passing the --smartcard flag to generate the three subkeys. The fingerprint and keygrip of the certifying key and encryption key are the same, as expected, and the "smartcard" layout is able to both verify and decrypt the same file.

Lastly, I used the contrib/trezor_agent_recovery.py script to recover the public and private keys. The public key was compared to the one generated by trezor-agent init --smartcard and found to be the same, and the private key was the proper pair. Using the private key, I was able to decrypt the file without the Trezor.

This confirms the ability to both generate and recover the private subkeys, for moving to a Yubikey 5.

I tried to maintain the same coding style that was present, and made sure that pylint and pytest both passed. If you have any questions, let me know. Thank you!

@slvrfn
Copy link

slvrfn commented Sep 19, 2021

@jrruethe Have you tried generating a ssh key after these changes? I just tried and am getting the following error:

Traceback (most recent call last):
File "/home/cameron/miniconda3/envs/trezor/bin/trezor-agent", line 8, in
sys.exit(ssh_agent())
File "/home/cameron/miniconda3/envs/trezor/bin/trezor_agent.py", line 4, in
ssh_agent = lambda: ssh.main(DeviceType)
File "/home/cameron/miniconda3/envs/trezor/lib/python3.9/site-packages/libagent/ssh/init.py", line 173, in wrapper
return func(*args, **kwargs)
File "/home/cameron/miniconda3/envs/trezor/lib/python3.9/site-packages/libagent/ssh/init.py", line 269, in main
identities = [device.interface.Identity(
TypeError: init() missing 1 required positional argument: 'keyflag'

It appears there is a parameter in Identity: keyflag that is not set from "libagent/ssh/init.py"

@jrruethe
Copy link
Author

I have not, but I can look at that and fix it. I only did testing with GPG, not SSH. Thanks for the heads up!

@jrruethe
Copy link
Author

@slvrfn I believe I fixed the issue you had with SSH.

@romanz romanz mentioned this pull request Oct 22, 2021
@lukechilds
Copy link

Hey, awesome work on this @jrruethe! Just wanted to check what the status of this is?

@jrruethe
Copy link
Author

@lukechilds I've been using my branch without issues for my own purposes, so for what I needed it is complete. I used it to generate deterministic subkeys from the Trezor and load them onto my Yubikey 5 NFC, which can then be used with the standard GPG installation.

@romanz
Copy link
Owner

romanz commented Dec 13, 2021

Sorry for the very delayed response...
Could you please rebase over the latest master?

@McCodeman
Copy link

McCodeman commented Feb 8, 2022

@lukechilds I've been using my branch without issues for my own purposes, so for what I needed it is complete. I used it to generate deterministic subkeys from the Trezor and load them onto my Yubikey 5 NFC, which can then be used with the standard GPG installation.

@jrruethe Do you have a writeup or can you point me in the right direction for moving loading subkeys onto the Yubikey 5 NFC.

@talosgt
Copy link

talosgt commented Feb 26, 2022

@lukechilds I've been using my branch without issues for my own purposes, so for what I needed it is complete. I used it to generate deterministic subkeys from the Trezor and load them onto my Yubikey 5 NFC, which can then be used with the standard GPG installation.

@jrruethe Hi Joe! This is exactly what I wanted to get working. As @McCodeman would you please be able to provide instructions on how to do exactly what you said? I would love to backup the Trezor master key and create/revoke subkeys and use them with my Yubikey. Sounds amazing! Thanks!!

@jrruethe
Copy link
Author

Essentially, I used the script in this pull request "contrib/trezor_agent_recover.py" with the "--smartcard" option. I used a Tails environment that was not connected to the internet, and entered my Trezor seed into the script, which output the private GPG keys (both the master and subkeys). After that, I just used the standard instructions for moving the subkeys to a Yubikey, such as this guide: https://github.com/drduh/YubiKey-Guide

There isn't a way to extract the private keys directly from the Trezor itself, which is why I supplied the recovery script. The recovery script generates the same keys as the Trezor when the same seed is used. This means that signing and encryption operations done with the Trezor can be used with the Yubikey, and vice versa.

@talosgt
Copy link

talosgt commented Feb 26, 2022

Essentially, I used the script in this pull request "contrib/trezor_agent_recover.py" with the "--smartcard" option. I used a Tails environment that was not connected to the internet, and entered my Trezor seed into the script, which output the private GPG keys (both the master and subkeys). After that, I just used the standard instructions for moving the subkeys to a Yubikey, such as this guide: https://github.com/drduh/YubiKey-Guide

There isn't a way to extract the private keys directly from the Trezor itself, which is why I supplied the recovery script. The recovery script generates the same keys as the Trezor when the same seed is used. This means that signing and encryption operations done with the Trezor can be used with the Yubikey, and vice versa.

Thanks for replying so quick! I'm an absolute novice on github. I don't mind running the python file on my regular computer as I'm just testing around with my Trezor, there's nothing on it. My question is how do I just run the file? Just open Terminal and run the saved file? Or do I enter my seed somewhere into the python script and run it? I did a shamir seed, so I would have enter the entire thing? Then do I remove do a "rm -r trezor" that I currently have and then run the script as if I'm doing the "trezor-gpg init... -- smartcard" command? I sent you an email in hopes that you can guide me, I don't mind compensating for your time as I'm very interested in this. I came across GPG not long ago and became very interested. Thanks!

@talosgt
Copy link

talosgt commented Feb 26, 2022

@jrruethe sorry, how do you run this version of the script instead of the usual "trezor-gpg init..." ?

@jrruethe
Copy link
Author

For an ubuntu-based system, the following commands should get you started:

sudo apt install python3-setuptools
git clone https://github.com/jrruethe/trezor-agent.git
cd trezor-agent
git checkout subkeys
sudo python3 ./setup.py install
python3 ./contrib/trezor_agent_recover.py --smartcard true

@talosgt
Copy link

talosgt commented Feb 26, 2022

@jrruethe thanks for getting back! I got a traceback, maybe I'm doing something wrong?

Traceback (most recent call last): File "trezor_agent_recover.py", line 25, in <module> from libagent.formats import KeyFlags # type: ignore ImportError: cannot import name 'KeyFlags' from 'libagent.formats' (/home/granttesler/.local/lib/python3.8/site-packages/libagent/formats.py)

@talosgt
Copy link

talosgt commented Mar 25, 2022

@jrruethe any advice for why I'm getting the Traceback for the Keyflags error that I listed above?

@lukechilds
Copy link

@jrruethe your contrib/trezor_agent_recover.py is really useful to me. I'm not too familiar with the internals of this lib, would it be simple to modify it to also export the SSH key?

@jrruethe
Copy link
Author

Unfortunately, I don't have the capacity to work on this any more right now.

For SSH, I have my GPG agent set up to also be an SSH agent. SSH connections utilize the authorization subkey on the Yubikey.

This guide has instructions on how to go that route:
https://github.com/drduh/YubiKey-Guide

@lukechilds
Copy link

lukechilds commented Aug 13, 2022

No worries @jrruethe, that sounds ideal. I'll look into it, thanks!

Comment on lines +28 to +29
curve_name_to_curve = {"nist256p1": curves.NIST256p}
curve_name_to_seed = {"nist256p1": "Nist256p1 seed"}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jrruethe Thanks for this work!
Any chance of you having some time to add ed25519 support to your script and rebase on top of master?
I'd be very much interested in using it with my current keys, but they're edwards.
Thanks

@romanz
Copy link
Owner

romanz commented May 29, 2023

@jrruethe Could you please rebase your PR over latest master?
I would be happy to merge it :)

@jrruethe
Copy link
Author

jrruethe commented Jun 1, 2023

I'll try to do this soon, I gotta test it out again with a real trezor

@jrruethe
Copy link
Author

jrruethe commented Jun 2, 2023

After rebasing, I can't seem to decrypt files, so apparently I messed something up. I'll try to dig in deeper if I get a chance

@jrruethe
Copy link
Author

jrruethe commented Jun 2, 2023

@romanz Ok, I got it all working and retested it with a real trezor. I also tested the trezor_agent_recover.py script again, and everything looks good.

Ready to merge! Thanks!

EDIT - I certainly hope I did that right, my git is not as strong as it should be :)

@romanz
Copy link
Owner

romanz commented Jun 3, 2023

I suggest cherry-picking only your commits into a clean branch over master.

@romanz
Copy link
Owner

romanz commented Jun 3, 2023

I have squashed all the changes above into a single commit: f16310f.
Please review it - it should contain the same code as e11afff above:

$ git diff e11afff f16310f

@romanz
Copy link
Owner

romanz commented Jun 3, 2023

It seems that CI didn't run on this PR...

My bad - fixed in 2b49eac (please rebase over latest master).

Copy link
Owner

@romanz romanz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jrruethe Could you please fix the CI errors here:
https://github.com/romanz/trezor-agent/actions/runs/5162519295/jobs/9300268171#step:5:67

You can also run the tests locally via tox, which used to run the following checks:

$ tox
...
py3: commands[0]> pycodestyle libagent
py3: commands[1]> isort --skip-glob .tox -c libagent
py3: commands[2]> pylint --reports=no --rcfile .pylintrc libagent
py3: commands[3]> pydocstyle libagent
py3: commands[4]> coverage run --source libagent -m pytest -v libagent
...

@jrruethe
Copy link
Author

jrruethe commented Jun 3, 2023

I think thats better? tox looks happy locally, for me.

@jrruethe
Copy link
Author

jrruethe commented Jun 5, 2023

@romanz Anything else needed to get this merged?

@andrevmatos
Copy link
Contributor

@jrruethe any chance of getting the same capabilities for ed25519? It seems to be more advised these days than nist's.
Thanks

@jrruethe
Copy link
Author

jrruethe commented Jun 5, 2023

@andrevmatos I don't have any plans to implement that right now. I am just trying to get the current PR completed.

@romanz
Copy link
Owner

romanz commented Jun 6, 2023

@romanz Anything else needed to get this merged?

Will do the final review this weekend - many thanks for the contribution!

@romanz romanz self-assigned this Jun 8, 2023
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep this file in a separate repository/snippet please.
I prefer not to instruct the users to enter their seed on a non-secure device.

@@ -12,7 +12,7 @@

def create_identity(user_id):
"""Create AGE identity for hardware device."""
result = interface.Identity(identity_str='age://', curve_name="ed25519")
result = interface.Identity(identity_str='age://', curve_name="ed25519", keyflag=None)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't keyflag_to_index throw an exception?

$ age-plugin-trezor -i foo
2023-06-09 19:03:29,483 ERROR        age plugin failed: None                                                                              [__init__.py:178]
Traceback (most recent call last):
  File "/home/user/trezor-agent/libagent/age/__init__.py", line 174, in main
    run_pubkey(device_type=device_type, args=args)
  File "/home/user/trezor-agent/libagent/age/__init__.py", line 47, in run_pubkey
    pubkey = c.pubkey(identity=client.create_identity(args.identity), ecdh=True)
  File "/home/user/trezor-agent/libagent/age/client.py", line 15, in create_identity
    result = interface.Identity(identity_str='age://', curve_name="ed25519", keyflag=None)
  File "/home/user/trezor-agent/libagent/device/interface.py", line 69, in __init__
    self.identity_dict['index'] = keyflag_to_index(keyflag)
  File "/home/user/trezor-agent/libagent/formats.py", line 49, in keyflag_to_index
    return {
KeyError: None

user_ids += [p for p in packets if p['type'] == 'user_id']

for packets in packets_per_key:

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove the line

Suggested change

# The key packet contains the keygrip
# The signature packet contains the keyflag in the hashed area
# Map them together
# pylint: disable=consider-using-enumerate
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not to use for i, p in enumerate(packets) below?

mapping = {}
for i in range(0, len(packets)):
p = packets[i]
if p['type'] == 'pubkey' or \
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: no need to break into 2 lines

Suggested change
if p['type'] == 'pubkey' or \
if p['type'] == 'pubkey' or p['type'] == 'subkey':

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's just a random note by a random passerby, but... i also like structuring boolean trees as one entry per line. it's easier to parse for my brain when the textual structure is in sync with the semantic structure.

embedded_sig = None
else:
if subkey.keyflag == KeyFlags.SIGN:

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove empty line

Suggested change

KeyFlags.SIGN,
KeyFlags.AUTHENTICATE,
KeyFlags.CERTIFY_AND_SIGN):

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

self.algo_id = self.curve_info['algo_id']
self.ecdh_packet = b''

elif keyflag == KeyFlags.ENCRYPT:

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

@@ -181,7 +182,8 @@ def parse_config(contents):
"""Parse config file into a list of Identity objects."""
for identity_str, curve_name in re.findall(r'\<(.*?)\|(.*?)\>', contents):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this regexp work for the new identity format?

@@ -14,7 +14,7 @@


def _create_identity(user_id):
result = interface.Identity(identity_str='signify://', curve_name='ed25519')
result = interface.Identity(identity_str='signify://', curve_name='ed25519', keyflag=None)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't keyflag_to_index throw an exception?

@romanz
Copy link
Owner

romanz commented Jun 9, 2023

I also tested it using fake-device agent (on 3c45889), and it seems that regular GPG identity fails to sign:

$ gpg --version
gpg (GnuPG) 2.2.27

$ export GNUPGHOME=/tmp/gnupg
$ rm -r /tmp/gnupg/

$ fake-device-gpg init "User"
2023-06-09 19:09:11,039 WARNING      This GPG tool is still in EXPERIMENTAL mode, so please note that the API and features may change without backwards compatibility! [__init__.py:171]
2023-06-09 19:09:11,045 WARNING      NOTE: in order to re-generate the exact same GPG key later, run this command with "--time=0" commandline flag (to set the timestamp of the GPG key manually). [__init__.py:86]
2023-06-09 19:09:11,045 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:09:11,045 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
2023-06-09 19:09:11,045 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:09:11,045 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
2023-06-09 19:09:11,051 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:09:11,051 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
2023-06-09 19:09:11,052 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:09:11,052 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
gpg: inserting ownertrust of 6
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   nistp256 1970-01-01 [C]
      8F37E3F7339D2542B8133BE64D8F4714A14548AC
uid           [ultimate] User
ssb   nistp256 1970-01-01 [E]

$ gpg --sign README.md 
gpg: using "User" as default secret key for signing
gpg: no default secret key: Unusable secret key
gpg: signing failed: Unusable secret key

It does seems to work on master:

$ rm -r /tmp/gnupg/
$ fake-device-gpg init "User"
2023-06-09 19:10:56,352 WARNING      This GPG tool is still in EXPERIMENTAL mode, so please note that the API and features may change without backwards compatibility! [__init__.py:118]
2023-06-09 19:10:56,357 WARNING      NOTE: in order to re-generate the exact same GPG key later, run this command with "--time=0" commandline flag (to set the timestamp of the GPG key manually). [__init__.py:33]
2023-06-09 19:10:56,358 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:10:56,358 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
2023-06-09 19:10:56,358 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:10:56,358 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
2023-06-09 19:10:56,358 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:10:56,358 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
2023-06-09 19:10:56,365 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:10:56,365 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
gpg: inserting ownertrust of 6
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   nistp256 1970-01-01 [SC]
      8F37E3F7339D2542B8133BE64D8F4714A14548AC
uid           [ultimate] User
ssb   nistp256 1970-01-01 [E]

$ rm README.md.gpg 
$ gpg --sign README.md 
gpg: using "User" as default secret key for signing

$ gpg --verify README.md.gpg 
gpg: Signature made Fri 09 Jun 2023 19:11:08 IDT
gpg:                using ECDSA key 8F37E3F7339D2542B8133BE64D8F4714A14548AC
gpg: Good signature from "User" [uncertain]

@jrruethe Could you please take a look?

@jrruethe
Copy link
Author

I also tested it using fake-device agent (on 3c45889), and it seems that regular GPG identity fails to sign:

$ gpg --version
gpg (GnuPG) 2.2.27

$ export GNUPGHOME=/tmp/gnupg
$ rm -r /tmp/gnupg/

$ fake-device-gpg init "User"
2023-06-09 19:09:11,039 WARNING      This GPG tool is still in EXPERIMENTAL mode, so please note that the API and features may change without backwards compatibility! [__init__.py:171]
2023-06-09 19:09:11,045 WARNING      NOTE: in order to re-generate the exact same GPG key later, run this command with "--time=0" commandline flag (to set the timestamp of the GPG key manually). [__init__.py:86]
2023-06-09 19:09:11,045 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:09:11,045 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
2023-06-09 19:09:11,045 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:09:11,045 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
2023-06-09 19:09:11,051 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:09:11,051 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
2023-06-09 19:09:11,052 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:09:11,052 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
gpg: inserting ownertrust of 6
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   nistp256 1970-01-01 [C]
      8F37E3F7339D2542B8133BE64D8F4714A14548AC
uid           [ultimate] User
ssb   nistp256 1970-01-01 [E]

$ gpg --sign README.md 
gpg: using "User" as default secret key for signing
gpg: no default secret key: Unusable secret key
gpg: signing failed: Unusable secret key

It does seems to work on master:

$ rm -r /tmp/gnupg/
$ fake-device-gpg init "User"
2023-06-09 19:10:56,352 WARNING      This GPG tool is still in EXPERIMENTAL mode, so please note that the API and features may change without backwards compatibility! [__init__.py:118]
2023-06-09 19:10:56,357 WARNING      NOTE: in order to re-generate the exact same GPG key later, run this command with "--time=0" commandline flag (to set the timestamp of the GPG key manually). [__init__.py:33]
2023-06-09 19:10:56,358 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:10:56,358 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
2023-06-09 19:10:56,358 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:10:56,358 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
2023-06-09 19:10:56,358 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:10:56,358 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
2023-06-09 19:10:56,365 CRITICAL     NEVER USE THIS CODE FOR REAL-LIFE USE-CASES!!!                                                       [fake_device.py:31]
2023-06-09 19:10:56,365 CRITICAL     ONLY FOR DEBUGGING AND TESTING!!!                                                                    [fake_device.py:32]
gpg: inserting ownertrust of 6
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   nistp256 1970-01-01 [SC]
      8F37E3F7339D2542B8133BE64D8F4714A14548AC
uid           [ultimate] User
ssb   nistp256 1970-01-01 [E]

$ rm README.md.gpg 
$ gpg --sign README.md 
gpg: using "User" as default secret key for signing

$ gpg --verify README.md.gpg 
gpg: Signature made Fri 09 Jun 2023 19:11:08 IDT
gpg:                using ECDSA key 8F37E3F7339D2542B8133BE64D8F4714A14548AC
gpg: Good signature from "User" [uncertain]

@jrruethe Could you please take a look?

The reason for the signing failure is that the key is being generated as [C] (certify only) instead of [SC] (signing and certify), but I haven't figured out why yet.

@talosgt
Copy link

talosgt commented Jun 28, 2023

any update to this?

@romanz
Copy link
Owner

romanz commented Jun 29, 2023

@talosgt There is an open issue (#358 (comment)) with this PR.

@doolio
Copy link
Contributor

doolio commented Sep 3, 2023

@jrruethe have you had a chance to look into the open issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants