rnpgp / rnp

RNP: high performance C++ OpenPGP library used by Mozilla Thunderbird
https://www.rnpgp.org
Other
196 stars 55 forks source link

CLI: inform user if imported keys are already in the keyring. #1777

Closed ni4 closed 1 year ago

ni4 commented 2 years ago

Description

Currently rnpkeys --import keyfile displays nothing if imported key already exists in the keyring(s). This should be changed to notify user how much keys are in file and their status (i.e. 3 keys not changes, 1 key not changed and 2 updated, 3 new keys, whatever else).

antonsviridenko commented 1 year ago

Looks like existing API does not provide this information (i.e. rnp_import_keys()), so the keyfile contents should be imported into the temporary FFI object first, then contents of the main and temporary keystores should be compared, matching keys should be also compared for presence of matching UIDs, signatures, in order to detect if the key is updated. Am I right? Or there can be some more simple way?

ni4 commented 1 year ago

It should return the key status in JSON, via the results parameter, or this doesn't work for some cases?

antonsviridenko commented 1 year ago

Ok, missed that part

antonsviridenko commented 1 year ago

Does it make sense to print separate statistics for public and secret keys?

antonsviridenko commented 1 year ago

I guess signature import code https://github.com/rnpgp/rnp/blob/d1915c1e8a1d3ac5acc562c777cfcd56e79942df/src/rnpkeys/rnpkeys.cpp#L302

can be used as an example, just for some reasons it is printed on stderr, should be fixed to stdout, I think.

ni4 commented 1 year ago

stdout is considered as a way to put the operation result, i.e. exported key, signature, whatever else. While stderr is a way to communicate with user. This logic applies at least to the RNP. Also it would be good to print the amount of new secret keys imported, as update (as a bunch of sigs/userids) is applied to the both public key and secret key. I.e. something like: "Import finished. 3 new secret keys, 2 new public keys were imported, 4 keys were updated." or "Import finished. No updates to the keyring were made.".

antonsviridenko commented 1 year ago

@ni4 I've found an issue in counting unchanged keys, rnpkeys --import calls rnp_import_keys() with RNP_LOAD_SAVE_SINGLE flag enabled, and input is processed in a loop by calling rnp_import_keys() multiple times until EOF, therefore key parts already imported on a previous iteration can be reported as "unchanged". Here is an example import on an empty keyring with JSON results printed for debugging:

../../install_prefix/bin/rnpkeys --homedir testkr/ --import src/tests/data/test_stream_key_merge/key-both.asc 
Keyring directory 'testkr/' is empty.
Use "rnpkeys" command to generate a new key or import existing keys from the file or GnuPG keyrings.
{
  "keys":[
    {
      "public":"new",
      "secret":"none",
      "fingerprint":"090bd712a1166be572252c3c9747d2a6b3a63124"
    },
    {
      "public":"new",
      "secret":"none",
      "fingerprint":"51b45a4c74917272e4e34180af1114a47f5f5b28"
    },
    {
      "public":"new",
      "secret":"none",
      "fingerprint":"5fe514a54816e1b331686c2c16cd16f267ccdd4f"
    }
  ]
}

pub   3072/RSA 9747d2a6b3a63124 2018-08-31 [SC]
      090bd712a1166be572252c3c9747d2a6b3a63124
uid           key-merge-uid-2
uid           key-merge-uid-1
sub   3072/RSA af1114a47f5f5b28 2018-08-31 [E]
      51b45a4c74917272e4e34180af1114a47f5f5b28
sub   2048/DSA 16cd16f267ccdd4f 2018-08-31 [S]
      5fe514a54816e1b331686c2c16cd16f267ccdd4f
{
  "keys":[
    {
      "public":"unchanged",
      "secret":"new",
      "fingerprint":"090bd712a1166be572252c3c9747d2a6b3a63124"
    },
    {
      "public":"unchanged",
      "secret":"new",
      "fingerprint":"51b45a4c74917272e4e34180af1114a47f5f5b28"
    },
    {
      "public":"unchanged",
      "secret":"new",
      "fingerprint":"5fe514a54816e1b331686c2c16cd16f267ccdd4f"
    }
  ]
}
Import finished: 6 keys processed, 3 new public keys, 3 new secret keys, 0 updated, 3 unchanged.

Obviously there should be zero unchanged keys when importing into empty keyrings.

antonsviridenko commented 1 year ago

In example above public keys are imported in a first iteration, secret parts are imported in a second and already imported public counterparts are reported as "unchanged" when rnp_import_keys() is called second time.

ni4 commented 1 year ago

@antonsviridenko Actually, this output is not unexpected, as after the first call of rnp_import_keys() keyrings in memory are populated. This could be handled by keeping some mapping "keyid":"import status" in CLI. Also, it's not common to use both public and secret key in a single file, as public key part is extracted from the secret key.