ueno/ruby-gpgme

Deleting a private key on macOS Big Sur hangs

Opened this issue · 4 comments

dvkch commented

I've encountered an issue where deleting a key would hang forever, using the following code:

GPGME::Key.find(:public, key_id).each { |k| k.delete!(true) }

# or
GPGME::Key.find(:private key_id).each { |k| k.delete!(true) }
�(B�(B�(0lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk�(B�(B�(0x�(B Do you really want to permanently delete the OpenPGP secret key: �(0x�(B�(B�(0x�(B "EnsoTest <test@example.com>"�(0x�(B�(B�(0x�(B 2048-bit RSA key, ID 0FDD92544BA73B80,�(0x�(B�(B�(0x�(B created 2020-08-25.�(0x�(B�(B�(0x�(B ?�(0x�(B�(B�(0x�(B�(B�(0x�(B�(B�(0x�(B     �(B<Delete key>�(B

If the key is a public key with no associated private key it works fine. If this is a public key with an associated private key, or if it is a private key itself, it will hang for around 2 minutes.

I have been able to reproduce this every time when running rspec on a Rails 6.0 project; the key was generated once and is re-added to the my test env using:

private_key = IO.read('spec/support/test_gpg')
key_id = GPGME::Key.import(private_key).imports.map(&:fpr)

Maybe there is an additional argument or configuration that is missing to prevent user confirmation via STDIN ?

@dvkch were you able to find any workaround to input the user confirmation?

dvkch commented

@errfanwadia Unfortunately not. There might be a way in Ruby to connect to STDIN and STDOUT to know when the lib asks for confirmation and write it to STDOUT programmatically from another thread, but I haven't had the chance to test it though

The current gem is not supporting this for now but the gpg/gpgme has an additional function gpgme_op_delete_ext where we can put the flags for the force delete:

/* Flags for the key delete functions.  */
#define GPGME_DELETE_ALLOW_SECRET (1 << 0)  /* Also delete secret key.     */
#define GPGME_DELETE_FORCE        (1 << 1)  /* Do not ask user to confirm.  */

see:

@errfanwadia Unfortunately not. There might be a way in Ruby to connect to STDIN and STDOUT to know when the lib asks for confirmation and write it to STDOUT programmatically from another thread, but I haven't had the chance to test it though

you can definitely do this, but it is kind of painful obviously. All 3 are predefined as IO objects named STDOUT, STDIN, and STDERR. Instead tho, you might consider just marking the key untrusted. It will still be there, but not get used normally.