-
Notifications
You must be signed in to change notification settings - Fork 169
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
[feat] Extend Key expiration and sign public key #171
Conversation
- use --edit-key but confining it to key expiry through an interface - only allow for 1 subkey extension - extension period is counted from the creation date
…when only signing verification fails
fe25279
to
a9f71c9
Compare
@kalikaneko you labeled this pr for the next-release do you know when that will be, or what we could do about to move things forward? ;) As far as I know it has been reviewed a few days after you have been started with the current release by @bwagnerr, something else? I know we spoke about last month, but I just wanted to make sure things do not get forgotten from both sides. =) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gnupg/gnupg.py
Outdated
@@ -558,6 +558,39 @@ def _parse_keys(self, result): | |||
if keyword in valid_keywords: | |||
getattr(result, keyword)(L) | |||
|
|||
def extend_key(self, keyid, validity='1y', passphrase=None, extend_subkey=True): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find a big weird the name extend_key
when the validity
parameter is taken from it's creation date instead, it's too easy to acutally shorten the expiration date by mistake. What about rename it to expire
as it's called in gnupg?
gnupg/gnupg.py
Outdated
to extend the key, from its creation date. | ||
:param str passphrase: passphrase used when creating the key, leave None otherwise | ||
:param bool extend_subkey: to indicate whether the first subkey will also extended | ||
by the same period --default is True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think extend_subkey
should act on all subkeys, not just on the first one. Or let you choose what subkey to act on. It's a bit estrange to hardcode it to modify only the first subkey.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right! We should definitely act on all subkeys, but we're not sure how to determine how many keys there are. Any ideas how to do this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about self.list_sigs(keyid)[0]['subkeys']
? It somehow feels hacky to use list_sigs for that, but list_keys will return the whole keyring which might be slow for big keyrings.
Maybe we should have a method to get keys from the fingerprint/uid/..., maybe an extra param in list_keys?
Anyway I'm happy with the hacky solution for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call, @meskio.
We tried to make a unit test to check if all subkeys were getting the expiration time changed, but we couldn't find a way to fetch the individual expiration time of each subkey.
gnupg/gnupg.py
Outdated
|
||
:param str keyid: key shortID, longID, email_address or fingerprint | ||
:param str validity: 0 or number of days (d), or weeks (*w) , or months (*m) or years (*y) | ||
to extend the key, from its creation date. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
validity
is a concept by itself in gnupg related to the trust of the key (https://www.gnupg.org/gph/en/manual/x334.html).
Maybe we can come up with a better name for this param. time? expiration_time?
gnupg/gnupg.py
Outdated
@@ -496,6 +496,38 @@ def list_packets(self, raw_data): | |||
result) | |||
return result | |||
|
|||
def sign_key(self, keyid, passphrase=None): | |||
""" sign (an imported) public key - keyid, with default secret key |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will be handy to have a default_key
param like in the sign
method, to be able to select the secret key to be used to sign with. I will be ok with just adding a comment with a TODO if this requires some work.
result = self._result_map['signing'](self) | ||
confirm_command = "%sy\n" % input_command | ||
p.stdin.write(confirm_command) | ||
self._collect_output(p, result, stdin=p.stdin) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use self._handel_io
here? I think it will deal with all the subprocess basically the same way that is done here. But I'm still confused why some commands use it and others not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We saw that self._handle_io
uses files and we're not reading from files. We're not sure if it makes sense to write to a stream just to use a method. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, let's keep it like that then.
This better reflects that the expiration date will change independently of previous date. with @tuliocasagrande
gnupg/_parsers.py
Outdated
@@ -878,13 +878,13 @@ def __init__(self, gpg): | |||
self._gpg = gpg | |||
self.status = 'ok' | |||
|
|||
def _handle_status(self, key, value): | |||
def _handle_status(self, key): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this value
is needed.
Now when I run it I get:
In [9]: gpg.expire('73102FE1', expiration_time='1w')
Exception in thread Thread-548:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "gnupg/_meta.py", line 650, in _read_response
result._handle_status(keyword, value)
TypeError: _handle_status() takes exactly 2 arguments (3 given)
Out[9]: <gnupg._parsers.KeyExpirationResult at 0x7fe91a9d06d0>
dc759ed
to
4c9623c
Compare
We decided to use list_sigs to get the number of subkeys, because the list_keys will return the whole keyring, which might be slow for big keyrings.
4c9623c
to
2aafbc7
Compare
The expire method was raising IndexError when passing an inexisting keyid. I prefered to use a try..except block instead of checking the return of list_sigs, because this solution is easier to extend in case of list_sigs changes to raise KeyNotFound or something.
I've merged it into develop. |
Key expiry date extension:
Public key signing: