Hi Hans,
thanks for your feedback.
Before I answer the specific points, let me make some arguments why I
designed the API like it is:
1. The API should be as easy as possible to use, even for newbies in
Android development. This means that as much functionality as possible
should be implemented on the side of the OpenPGP Provider. This lead to
my decision to never expose key ids via the API.
- So on first use the private key used for an app is choosen by the
user -> The app never gets the key id of the private key
- To encrypt something the app only needs to know the user id of the
recipient. In most cases this is the email (could also be jabber ids in
future applications).
- This also introduces more security and control for users , e.g. the
app can't choose on itself which key to use for signing
2. To make the API easy, I am also trying to keep the interface as small
as possible, but I already had some problems due to this self-imposed
limitations :(
3. Last main point: As much as I like to have a perfect API that solves
every possible corner case, I would really like to get forward and get
this accepted as the API version 1. As I said in previous mails, I think
the need for a new OpenPGP app that works with k9mail is urgent (APG has
many big bugs: selection of multiple encryption keys is broken, PRNG
fixes are not applied). I for short release times: release early and
ofter :D
Yes this is indeed a problem I faced already while implementing the
k9mail integration. The option to automatically encrypt is currently not
available with the new API (and is properly greyed out in the account
preferences)
To prevent exposing key ids we could introduce a simple function:
boolean isKeyAvailable(in userId)
which is not asynchronous as the other functions, thus no callback.
> * do calling apps need to be able to encrypt using key IDs (e.g.
> f123eb458239289d) or is using email address style identifiers sufficient? For
> an email program, I can see only using the email address and having the
> OpenPGP provider handle the rest, like prompting the user if there are
> multiple keys that match a given email address. But these functions should
> also work for other standard uses of OpenPGP, like signing software. So for
> example, a OpenPGP key for a Launchpad PPA apt repo has a signing key
> associated with that. Those keys often do not have email-style user IDs
> associated with the key. But an Android should be able to still work with
> keys like that using this API. For an example, check out:
>
> gpg --recv-keys 97BB3B58
> gpg2 --fingerprint --with-colons 97BB3B58
> apt-key list (on Debian-deriv systems)
This is indeed a limitation of the API when not exposing key ids. If
there is really need for something like this, I would propose
implementing a new interface exactly for this special case.
Additionally I don't like this approach of using untrusted keys from a
keyserver...
> * what exact behaviors the API functions trigger? One thing that is clear to
> me is that the OpenPGP provider should handle all stuff related to the
> password and prompting for it. The calling apps should be happily ignorant of
> the state of the password caching and UI prompting. I think that the OpenPGP
> provider should also handle choosing the right key when there are multiple
> matches for a given user ID.
I think the behavior is the freedom of the OpenPGP Provider ;)
Keychain handles the selection of the private key on first use, password
promt, selection of encryption keys on duplicate keys for one user id,
querying missing keys (not implemented right now).
> * maybe the allowUserInteraction option should be a global settable flag
> rather than in the calling functions. I think most apps will either choose
> one state or the other and stick with it rather than occasionally use it or
> not. This is how gpgme works, it has a whole bunch of global options.
>
> * @param allowUserInteraction
> * Allows the OpenPGP Provider to handle missing keys by
> showing activities
I also thought to make it a global option, but my current use case is as
follows:
On opening a signed mail, it gets automatically verified and then the
verification status is displayed. When the key is missing it could be
annoying to always get a dialog asking to download the key. So I thought
to make the first function call with allowUserInteraction=false. And
when signature check fails a button gets visible which does the same
call but with allowUserInteraction=true to allow the download of missing
keys.
Note: In the current k9mail pull requests this is not implemented, but I
would like to do it in a new pull request when I got time.
>
>
> * one thing I haven't figured out how to map cleanly to an API is all the
> variations of binary/ASCII input and output. Maybe there could be a set of
> simple methods that always output the same format as is input. Then keep the
> current functions for people who need to go from binary to ASCII or vice
> versa. So the methods would be like:
>
> encrypt(in String inputAscii, in String[] encryptionUserIds, in
> IOpenPgpCallback callback);
> encrypt(in byte[] inputBytes, in String[] encryptionUserIds, in
> IOpenPgpCallback callback);
> encrypt(in byte[] inputBytes, in String[] encryptionUserIds,
> in boolean asciiArmor, in IOpenPgpCallback callback);
>
> But then the output is returned via IOpenPgpCallback, so adding two sets of
> callback types might be annoying. If we're marking the input with an
> asciiArmor boolean, then the output should also be marked. So perhaps its
> easiest to have separate bytes[] and String IOpenPgpCallback methods. Or
> maybe its enough to just have this defined in IOpenPgpCallback:
>
> oneway void onSuccess(in String outputAscii, in OpenPgpSignatureResult
> signatureResult);
> oneway void onSuccess(in byte[] outputBytes, in OpenPgpSignatureResult
> signatureResult);
> oneway void onError(in OpenPgpError error);
If the input is an ascii armored string or just a byte array should be a
check on OpenPGP Keychain's side, so no need to specify the format of
the input.
asciiArmror option allows to request for a specific output format. So I
am not sure if it's always ASCII to ASCII and binary to binary (consider
attachments).
But that said, I also don't like the option, because it's another
parameter in the long function declaration ;)
> * Also, Dominik, one detail about this comment: "Encode for ASCII (Radix-64,
> 33 percent overhead compared to binary)". I've never seen anyone refer to
> ASCII-armor as "Radix-64". It is called "base64". If you're on UNIX, try
> `man gpg` or `man base64` for docs on that.
Radix-64 is base64 with a checksum. See
http://tools.ietf.org/html/rfc4880#page-53. Actually
This should also be the ecnoding used in gpg and bouncy castle when
using armoring.
The next 3 days I am on vacation, and the following week I need to do
some other work, so don't expect fast answers ;)
Regards
Dominik