Re: [k-9-mail] Rejected new OpenPGP/Crypto Providers

629 views
Skip to first unread message

cketti

unread,
May 12, 2013, 9:24:18 PM5/12/13
to k-9...@googlegroups.com, k-9-...@googlegroups.com, Dominik Schürmann
On 13.05.2013 01:05, Dominik Schürmann wrote:
> Hi folks,
>
> I made a bug report about it, but maybe the mailinglist is a better
> place to discuss the issues.

We have a developer mailing list: k-9...@googlegroups.com
Please follow-up there.

> see http://code.google.com/p/k9mail/issues/detail?id=5629
>
> I opened a bug report due to the recent rejected pull request to
> integrate a new crypto provider to be used with a new app called "PGP
> KeyRing" (https://github.com/k9mail/k-9/pull/295)
>
> cketti stated that "I don't like this patch. I don't like the fact
> that we have special code to support APG either. But at least APG is
> open source. Ideally someone would implement a real interface
> third-party applications could use to provide crypto services.
> Modifying K-9 to support every possible app out there is not an
> option."
>
>
>
> It's sad to hear that you don't want to support new crypto providers.

For me, supporting specific crypto providers is only an option if the crypto app itself is published under a open source license.


> We are also considering options how to integrate OpenPGP Keychain
> (https://github.com/dschuermann/openpgp-keychain), which is basically
> a fork of APG, into K9Mail.

Unlike "PGP KeyRing" this is an open source app, so I have no strong objections to adding support for "OpenPGP Keychain". However, I'd prefer a generic interface that doesn't require app-specific code in K-9 Mail (see below).


> I am not sure if I agree with your idea to provide a K9 mail
> interface for crypto providers. It will be difficult to provide an
> API from that side that is to be used by Crypto apps. What could be
> done, is providing a unified collection of Intents where crypto
> providers can register to. Then the user can choose with which app
> the intent should be opened (to for example decrypt) the content.
> BUT: There will be problems with this. Intents are rather limited in
> their functionality and need further user interaction that will
> complicate the (already over complicated) use of cryptography. Also
> milicious apps can register to these Intents as it is not possible to
> do further verification of their behaviour from K9's side. As I said
> it would be nice to have automatic decryption without further user
> interaction. This could be done by Intents that automatically close
> after decrypting. As this would impose a security risk (as every app
> can send this intent and force a decrypt of content without user
> interaction), we require a permission from the app "OpenPGP Keychain"
> to do this (see
> https://github.com/dschuermann/openpgp-keychain/blob/master/README.md).
> Thus, even when k9 mail provides a set of Intents, we also need to
> think about a uniquely named permission that every OpenPGP app
> provides and K9 mail uses.
>
> Another and more problematic idea: In OpenPGP Keychain, we introduced
> remote AIDL services to be used for encrypting/decrypting/signing
> etc. This would provide even better seamless integration without
> leaving K9mail. But I don't believe it is possible to provide an API
> from k9mail side to do that.
>
> I hope for discussion about these ideas.


I'm not sure I followed all of your points above. Let me write down my thoughts on this topic.

My requirements (for an optimal solution):
1. No hardcoded dependencies between K-9 Mail and the crypto provider (that includes permissions in the manifest)
2. Because of point 1 it's necessary to have some form of mutual authentication to make sure secret data doesn't end up in the wrong place


My ideas for an implementation:
1. Define some form of interface for the crypto provider (intents, AIDL service, whatever you need)

2. Crypto app: add an intent filter and some meta data to the activity/service that is part of the crypto provider interface.
Example:
  <service
      android:name="com.example.your.conrete.Implementation"
      android:icon="@drawable/ic_my_crypto_provider"
      android:label="@string/my_crypto_provider_title" >
      <intent-filter>
          <action android:name="org.openintents.cryptoprovider" />
      </intent-filter>

      <meta-data
          android:name="protocolVersion"
          android:value="1" />
      <meta-data
          android:name="description"
          android:value="@string/my_crypto_provider_description" />
  </service>

3. The app that wants to use the crypto provider needs to have a way to let the user select a specfic crypto provider (e.g. in settings). To get a list of available crypto providers the package manager is used to get a list of apps that provide the crypto provider "action" ("org.openintents.cryptoprovider" in the example). Once the crypto provider is selected the app will remember the package name and signature.

4. The first time an app uses one of the (protected) functions of the crypto provider the crypto app will prompt the user to allow access to the crypto provider (display app name + package name). If the user allows access, the package name and signature of the calling app is saved and further access is granted without prompting the user.

cketti

unread,
May 12, 2013, 10:23:19 PM5/12/13
to k-9...@googlegroups.com
On 13.05.2013 03:34, John F. Eldredge wrote:
I think the logic to prompt a first-time user to accept or reject allowing a crypto app to be used with K-9, and the storage of this decision, needs to be done by K-9, not by the crypto app. Otherwise, a malicious app could be written to automatically give the OK, without consulting the user.


The user has to select which crypto app to use with K-9 Mail. See step 3 (quoted below). The proposed authentication is mutual!

Dominik Schürmann

unread,
May 13, 2013, 5:44:35 AM5/13/13
to k-9...@googlegroups.com
Hi cketti,

your proposals go into the right direction, but I have prejudices
against coding our "own" mutual authentication without using Android's
security/permission model.

I thought about another idea, which could also provide better usability
as it will be based on remote services. I hope that this is possible (I
have to test it):

- K9Mail provides AIDL classes that are used like interfaces that have
to be implemented by crpyto providers (implement the stubs). They
contain method declarations for encrypt/decrypt/sign/verify etc. This is
K9Mail's API.

- Most methods are "oneway" methods (see android docs), meaning they are
async. We need also some callback stubs that will be implemented by k9mail.

- These oneway methods are implemented by a crypto provider. K9Mail
connects to the crypto provider with a service connection and uses the
methods directly. While encrypting via this remote service, K9Mail can
show some kind of progressbar to show the background process. After it
finishes, K9Mail gets back the result with an implemented callback. (I
have done similar things with OpenPGP Keychain).

- Other code that has to be on K9Mail's side: A preference drop down to
choose the crypto provider package (I would not provide an automatic
integration, so K9Mail devs can choose which crypto providers to allow).
This is not much extra code for every new provider.

- K9Mail declares a permission "be a crypto provider for k9mail" that
has to be used from the crypto providers side.

What do you think of this approach?

Regards
Dominik
signature.asc

Dominik Schürmann

unread,
May 13, 2013, 7:22:22 AM5/13/13
to k-9...@googlegroups.com
I discussed this proposal with Ash Hughes who also contributes to
OpenPGP Keychain and he found an obvious flaw: We also need to check
that no other app can connect to these crypto services. Thus we need to
check a permission from the crypto side when connecting to the service.
I think we can use the same permission for k9mail and the crypto app and
declare it in K9mail. Then using enforcePermission() to check in the
service.

Regards
Dominik
signature.asc

cketti

unread,
May 14, 2013, 12:14:23 PM5/14/13
to k-9...@googlegroups.com
If you read my proposal again, you will notice that I already considered that.

I can understand that you are reluctant not to use the Android permission system. But using it for a generic plugin interface is very painful (see e.g. [1]).
Users tend to accept all permissions anyway, so prompting the user on first access is maybe not the worst idea.

Let me explain why requirement 1 ("no hardcoded dependencies") is important to me:
1. I don't like changing K-9 Mail every time someone comes up with a new app to provide crypto services, especially if it's a closed source app. Even if the change consists only in requesting another permission. The idea of a generic interface is that you don't care what app exactly the user wants to use.
2. Likewise, there is no reason why a crypto app should have a dependency to K-9 Mail. There are lots of email clients around and they should all be able benefit from a good crypto app. Disclosure: I am working on Kaiten Mail.

What you could do, is define one permission that all crypto apps declare and that all apps that want to use a crypto provider request. This is messy because of the install-order issue and the fact that when you install more than one crypto provider there is no way to limit access of an app to only one of them.

My conclusion is that the Android permission system shouldn't be used in this case.

-cketti


[1]: https://code.google.com/p/android/issues/detail?id=25906

Dominik Schürmann

unread,
May 14, 2013, 12:44:16 PM5/14/13
to k-9...@googlegroups.com
Hi,

thanks for your viable input. You convinced me not to use permissions.

One thing remains: Why defining a cryptoprovider API that should be used
by different email programs and different Crypto Providers? I think this
will not work due to different requirements by the email apps.

Why not defining the "one and only" K9mail PGP crypto API that can be
implemented by different pgp apps. So user interface implementation is
done on k9mail's side and only key management
encryption/decryption/verification and so on are done by remote services
implementing AIDL?

Then I would also define no "openintents", but k9mail based intent
"com.fsck.k9.pgpservice".
So if an crypto app wants to support kaiten mail, it can implement
kaiten mail's pgp api with it's intent.

I don't think we can find an api that satisfies all email apps.

Regards
Dominik
signature.asc

Hans-Christoph Steiner

unread,
May 14, 2013, 4:53:56 PM5/14/13
to k-9...@googlegroups.com

There is a parallel conversation happening here:
https://lists.mayfirst.org/pipermail/guardian-dev/2013-May/001663.html

I thought I'd post my response here also:


I think we can definitely make a generic, reusable crypto API. GPGME is one
such example of an API (not to say it doesn't have limitations).

I also agree with cketti from the k9-dev thread that each mail and crypto app
should not need to depend on any other in order for this to work. The Android
permissions model assumes that you trust the apps that you send intents to, so
if we want to take extra precautions then we can't rely on the Android
permissions model. It seems to me that having a two-way TOFU/POP verification
process makes sense. Then each mail and crypto app can have an Activity that
displays which apps are trusted, and allow the user to view and manage those
relationships.

On that note, not using the Android permissions at all means that the apps in
question cannot be easily audited in the standard Android tools and UI, which
is bad. I could see making two generic permissions, something like
android.permission.CRYPTO_CONSUMER and android.permission.CRYPTO_PROVIDER.
These would then also match the generic APIs for each side of the
conversation, if using something like AIDL.

One thing about OpenPGP-Keychain's API that I complicates thing is that it
exposes too much, like generating new keys. Instead, we're thinking our
GnuPG-For-Android (GFA) app will handle as much as possible itself, and only
expose what apps need to use PGP, while not exposing things needed only manage
the process. So GFA will provide Activities for:

- generating keys
- prompting for the passphrase
- selecting a key from the keychain
- importing/exporting keys
- manage the trust db
- sign other keys
- syncing with keyservers

Then the API is just needed for:
- encrypting files/emails
- decrypting files/emails
- signing files/emails
- verifying files/emails
- querying trust status of a key
- querying whether an email address is in the keyring

Here's an old outline of how we see it:
http://guardianproject.info/wiki/GnuPrivacyGuard_for_Android

.hc


> Hi,
>
> thanks for your viable input. You convinced me not to use permissions.
>
> One thing remains: Why defining a cryptoprovider API that should be used
> by different email programs and different Crypto Providers? I think this
> will not work due to different requirements by the email apps.
>
> Why not defining the "one and only" K9mail PGP crypto API that can be
> implemented by different pgp apps. So user interface implementation is
> done on k9mail's side and only key management
> encryption/decryption/verification and so on are done by remote services
> implementing AIDL?
>
> Then I would also define no "openintents", but k9mail based intent
> "com.fsck.k9.pgpservice".
> So if an crypto app wants to support kaiten mail, it can implement
> kaiten mail's pgp api with it's intent.
>
> I don't think we can find an api that satisfies all email apps.
>
> Regards
> Dominik
> - hide quoted text -

Dominik Schürmann

unread,
May 28, 2013, 9:04:45 AM5/28/13
to k-9...@googlegroups.com
Hey k9-mail devs,

I am currently implementing first ideas into k9mail and OpenPGP Keychain.
What is your standpoint regarding the old crypto implementations in k9mail?
Should I try to preserve its functionality or is it okay to remove it?

Regards
Dominik
signature.asc

Bernhard Redl

unread,
May 28, 2013, 1:29:12 PM5/28/13
to k-9...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

hi

working: (integraion with apg (android privacy guard)
GPG/INLINE encrypt decrypt + sign

not working (and "broken" by architecture of k9)
GPG/MIME PGP/MIME etc.
(reason: original mime parts are not preserved)

i have recently done some work on the gpg part (only cosmetic parts
but afik the original developer is not hanging around at this
maillinglist)

you can contact me here or per mail if you have any questions.


On 05/28/2013 03:04 PM, Dominik Schürmann wrote:
> Hey k9-mail devs,
>
> I am currently implementing first ideas into k9mail and OpenPGP
> Keychain. What is your standpoint regarding the old crypto
> implementations in k9mail? Should I try to preserve its
> functionality or is it okay to remove it?
>
> Regards Dominik

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.20 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iEYEARECAAYFAlGk6WgACgkQ9wU+3S/MK7S6twCfewuIYB95kYbt9tgBSHs+ohId
XPEAn07H/tTM5kJcPSd7h+algLC36SPp
=wELx
-----END PGP SIGNATURE-----

cketti

unread,
May 28, 2013, 2:32:52 PM5/28/13
to k-9...@googlegroups.com
On 28.05.2013 15:04, Dominik Schürmann wrote:
> I am currently implementing first ideas into k9mail and OpenPGP Keychain.
> What is your standpoint regarding the old crypto implementations in k9mail?
> Should I try to preserve its functionality or is it okay to remove it?

Users won't abandon APG right away. So we should support it in addition
to the "new way of doing things" for some time.

Personally, I don't care if K-9 Mail talks directly to APG (like it is
now) or if the user needs to install an APG <-> K-9 Mail "bridge" that
uses the new interface to talk to K-9 Mail and the APG interface to talk
to APG.

Jesse Vincent

unread,
May 28, 2013, 3:14:54 PM5/28/13
to k-9...@googlegroups.com
In an ideal world, we'd be able to keep supporting APG for a while, but if it's going to make it significantly more difficult to implement a new standard that supports a bunch of implementations, I'd vote to yank it. 

(Like cketti, I'm fine with an APG-K-9 bridge app. Or an APG update ;)



--
--
You received this message because you are subscribed to the K9 Mail Dev List.
To post to this group, send email to k-9...@googlegroups.com
To post an issue, go to http://code.google.com/p/k9mail/issues/list
To unsubscribe, email k-9-dev+u...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/k-9-dev

---
You received this message because you are subscribed to the Google Groups "K9 Mail Developers List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to k-9-dev+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



Hans-Christoph Steiner

unread,
May 28, 2013, 3:22:18 PM5/28/13
to k-9...@googlegroups.com
We're also working full tilt right now on getting GnuPG fully functional, so
I'd love to nail down a common API here. I've been documenting existing APIs
and my idea for a common API on our wiki. I'm currently only working on an
Intent-based API. I think it would authenticate based on cketti's idea of
TOFU/POP with a shared secret and a confirmation dialog. I would love feedback
on it:

https://dev.guardianproject.info/projects/gpgandroid/wiki/API_Sketch

I think what's currently in APG is somewhat limited, so it needs to be
changed. The OpenPGP Keychain Intent API seems unneccesarily complicated and
not very Android-ish. We think that the OpenPGP app should provide all of the
common Activities needed for managing the keys, passphrases, and keychains,
therefore that stuff should be handled within the OpenPGP app and not exposed
to the apps that just need to use OpenPGP.

For example, I don't see a need for IMPORT* intents, that can be done with
file associations or .asc, .gpg, .pem, etc. files. If a user wants to
initiate a key exchange with another person, i.e IMPORT_FROM_NFC, that should
happen within the OpenPGP app. Same goes with EDIT_KEYRING and
CREATE_KEYRING. If K-9 sends an ENCRYPT Intent to the OpenPGP app, it should
prompt the user to create a key if one doesn't exist. K-9 should not need to
know whether

Also, I don't think we need four separate encrypt Intents (ENCRYPT,
ENCRYPT_AND_RETURN, ENCRYPT_FILE, ENCRYPT_STREAM_AND_RETURN). Instead there
should be one, and the OpenPGP app knows how to handle it based on the data
that is included in the Intent. For example, if there is a Content URI to a
file, then it'll do a file-based encryption and return a Content URI.

.hc

signature.asc

Dominik Schürmann

unread,
May 28, 2013, 5:38:20 PM5/28/13
to k-9...@googlegroups.com, Ash Hughes
Hi Hans, hi k9mail devs,

I am fully with you that there are too much Intents. Most Intents are
coming from APG. The IMPORT and CREATE_KEYRING Intent are designed by me
to provide a first-time-wizard and import functionality from another app
(side project of me).

That said I don't like the Intent approach.
I now have some code to show. This AIDL based API is based on similar
APIs seen in other Android code.
The idea is that most functionality is implemented in the crypto app,
while user interaction is _mostly_ implemented in K9mail.
If further user interaction is required at one point an Intent is send
back to a callback implemented in k9mail (This is similar to
AccountManager that also returns an intent when user interaction is
required to get a new authToken. Also similar to Google's Play Store
in-app billing).

The following package needs to be included on both sides. It includes
the service AIDL definition, callback definition, parceable objects and
a helper class to connect to the service. It is just a first idea how to
do it, it is not final in any sense:

https://github.com/dschuermann/openpgp-keychain/tree/k9mail/OpenPGP-Keychain/src/com/android/crypto

For a small first test I implemented decrypt in k9mail:
https://github.com/dschuermann/k-9/blob/7b3e53e1ef3c3b542abcb0744a50de75a00ba087/src/com/fsck/k9/view/MessageCryptoView.java

Obviously there are many things missing.

A test implementation on Keychains side:
https://github.com/dschuermann/openpgp-keychain/blob/k9mail/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java

One example of a flow:
0. MessageCryptoView has a service connection using our helper to
prefered crypto provider
1. User clicks decrypt (decryptOnClick)
2. mCryptoServiceConnection.getService().decryptAndVerify(data.getBytes(),
callback); will send data to keychains service implementation
3. When private key is in keychains database and passphrase is currently
cached, there is no user interaction -> callback's onSuccess will be called
4. When passphrase is not cached in keychain -> callback's
onActivityRequired() is called with required intent.
Then k9mail will start this activity and tries to decrypt again when it
returns.


Regarding registration of crypto provider:
1. open intent com.android.crypto.REGISTER from k9mail with intent
chooser -> all apps with this intent action will be listed there
2. keychain's crypto_provider.RegisterActivity will be called and asks
to allow access.
3. keychain will save packagename of app that called this intent if
allowed by user. Later in the service, only this app will be allowed to
use the service.



I have one request to the k9mail devs:

-As I am not that deep in the sourcecode of k9mail, could someone add a
seperated preference for the new creypto providers? Currently I added a
stub implementation of OpenPGP Keychain implementing the old crypto
interface.

- What is also out of my scope: Start com.android.crypto.REGISTER and
save a list of allowed crypto providers in k9mail after successfull
return of that activity.

Please: Criticize and provide feedback as usual.

@Hans: Why do you want to use a shared secret in the registration process?

Regards
Dominik
signature.asc

Hans-Christoph Steiner

unread,
May 28, 2013, 6:16:58 PM5/28/13
to k-9...@googlegroups.com
Why would k9mail need to be aware at all of the passphrase prompt, or am I
misunderstanding? Abel implemented the GnuPG pinentry for Android to just pop
over whatever app is on top at the time. The prompting logic is entirely in
GnuPG (gpg-agent really). I think this is the way it should work in general.
The app using OpenPGP should only be aware of the things it cares about:
selecting keys, decrypting, encrypting, signing, and verifying. Everything
else can be transparently handled by the OpenPGP provider.


> Regarding registration of crypto provider:
> 1. open intent com.android.crypto.REGISTER from k9mail with intent
> chooser -> all apps with this intent action will be listed there
> 2. keychain's crypto_provider.RegisterActivity will be called and asks
> to allow access.
> 3. keychain will save packagename of app that called this intent if
> allowed by user. Later in the service, only this app will be allowed to
> use the service.

Why make a special Intent for registering? Why not just do this with any of
the standard crypto Intents? Then an individual app could decide to query
ENCRYPT and use the reply for every crypto operation, while another app could
query ENCRYPT, DECRYPT, VERIFY, SIGN, SELECT, etc. and register a separate app
to handle each operation. I think this would make for a simpler yet more
flexible API. I suppose having a REGISTER Intent would make it clear that
registration is required.

I imagine you're using this to implement this.
http://developer.android.com/reference/android/content/Intent.html#ACTION_PICK_ACTIVITY


> I have one request to the k9mail devs:
>
> -As I am not that deep in the sourcecode of k9mail, could someone add a
> seperated preference for the new creypto providers? Currently I added a
> stub implementation of OpenPGP Keychain implementing the old crypto
> interface.
>
> - What is also out of my scope: Start com.android.crypto.REGISTER and
> save a list of allowed crypto providers in k9mail after successfull
> return of that activity.
>
> Please: Criticize and provide feedback as usual.
>
> @Hans: Why do you want to use a shared secret in the registration process?

As a way to validate an approved connection. Perhaps there is a better way.
Maybe it could just be based on a ACTION_PICK_ACTIVITY query that is cached,
then reused for all future crypto Intents. Sounds like that's what you're
planning based on the requests above.

.hc
signature.asc

Dominik Schürmann

unread,
May 28, 2013, 6:29:34 PM5/28/13
to k-9...@googlegroups.com, Ash Hughes


On 29.05.2013 00:16, Hans-Christoph Steiner wrote:
> Why would k9mail need to be aware at all of the passphrase prompt, or am I
> misunderstanding? Abel implemented the GnuPG pinentry for Android to just pop
> over whatever app is on top at the time. The prompting logic is entirely in
> GnuPG (gpg-agent really). I think this is the way it should work in general.
> The app using OpenPGP should only be aware of the things it cares about:
> selecting keys, decrypting, encrypting, signing, and verifying. Everything
> else can be transparently handled by the OpenPGP provider.

A service (in keychain) can start Activities with startActivity() but it
never knows when these activities are finished as there is no
startActivityForResult() in services. Thus you need to delegate the
starting to the current active Activity, which is on k9mail's side. As
said, this is done similar in AccountManager and Google's in-app billing
API.
We need to know when the activity finishes to restart decrypting with
the service.

If you know another way, please tell me exactly how to do it. Then we
can throw away the onActivityRequired in the CryptoCallback.


>
>
>> Regarding registration of crypto provider:
>> 1. open intent com.android.crypto.REGISTER from k9mail with intent
>> chooser -> all apps with this intent action will be listed there
>> 2. keychain's crypto_provider.RegisterActivity will be called and asks
>> to allow access.
>> 3. keychain will save packagename of app that called this intent if
>> allowed by user. Later in the service, only this app will be allowed to
>> use the service.
>
> Why make a special Intent for registering? Why not just do this with any of
> the standard crypto Intents? Then an individual app could decide to query
> ENCRYPT and use the reply for every crypto operation, while another app could
> query ENCRYPT, DECRYPT, VERIFY, SIGN, SELECT, etc. and register a separate app
> to handle each operation. I think this would make for a simpler yet more
> flexible API. I suppose having a REGISTER Intent would make it clear that
> registration is required.

I think you misunderstood something. I don't want to use any of the old
intents. There is just _one_ Intent for other apps to use:
com.android.crypto.REGISTER. After that you need to use the service.
I meant
http://developer.android.com/reference/android/content/Intent.html#createChooser(android.content.Intent,%20java.lang.CharSequence)
to start com.android.crypto.REGISTER, but that similar to PICK_ACTIVITY.
Then all apps having it in their intent filter will show up. The
activity on keychain's side has two buttons for allow and disallow access.

>
>
>> I have one request to the k9mail devs:
>>
>> -As I am not that deep in the sourcecode of k9mail, could someone add a
>> seperated preference for the new creypto providers? Currently I added a
>> stub implementation of OpenPGP Keychain implementing the old crypto
>> interface.
>>
>> - What is also out of my scope: Start com.android.crypto.REGISTER and
>> save a list of allowed crypto providers in k9mail after successfull
>> return of that activity.
>>
>> Please: Criticize and provide feedback as usual.
>>
>> @Hans: Why do you want to use a shared secret in the registration process?
>
> As a way to validate an approved connection. Perhaps there is a better way.
> Maybe it could just be based on a ACTION_PICK_ACTIVITY query that is cached,
> then reused for all future crypto Intents. Sounds like that's what you're
> planning based on the requests above.

Yes.
signature.asc

cketti

unread,
May 28, 2013, 8:31:05 PM5/28/13
to k-9...@googlegroups.com
On 29.05.2013 00:29, Dominik Schürmann wrote:
There is just _one_ Intent for other apps to use:
com.android.crypto.REGISTER.

Please don't use namespaces you don't control without permission.
I'd be fine with any namespace. But other people might be hesistant to use a "branded" intent. That's why I originally suggested org.openintents.<something>. Of course we'd have to ask the OpenIntents folks for permission before making this final. If you like the idea let me know and I'll talk to them.

Dominik Schürmann

unread,
May 29, 2013, 3:33:07 AM5/29/13
to k-9...@googlegroups.com
Hi cketti,

you are right. I should switch to openintents. But before taklking to
them, we should find an API that satisfies all.
What do you think of my current proposal?

Regards
DOminik
signature.asc

Dominik Schürmann

unread,
May 29, 2013, 7:35:54 AM5/29/13
to k-9...@googlegroups.com
I thought I explain more why I want to get away from Intents for crucial
operations like encrypt/decrypt/sign/verify:

- Before Android 4.1.1 bundled extras can be read by any app that has
GET_TASKS permission (see
http://stackoverflow.com/questions/15501260/protecting-extra-data-in-android-intent).
This means carrying sensitive information with an Intent is a no go. If
we want to use Intents we shoudl set up a contentprovider.

- Consider a chat application using pgp for encryption: Everytime the
user sends a new message, the ENCRYPT intent has to be started and
returned. This is heavy overhead for a method that requires no further
user interaction.

- In my example if further user interaction is required, e.g., when
Alice starts a chat and uses her private key for the first time, my AIDL
service returns an intent for "passphrase entering" that needs to be
executed by k9mail. This intent carries no extras and after this the
passphrase is cached on keychains side. Afterwards there is no activity
overhead when encrypting.

Regards
Dominik
signature.asc

Hans-Christoph Steiner

unread,
May 29, 2013, 9:20:50 AM5/29/13
to k-9...@googlegroups.com


On 05/28/2013 06:29 PM, Dominik Schürmann wrote:
>
>
> On 29.05.2013 00:16, Hans-Christoph Steiner wrote:
>> Why would k9mail need to be aware at all of the passphrase prompt, or am I
>> misunderstanding? Abel implemented the GnuPG pinentry for Android to just pop
>> over whatever app is on top at the time. The prompting logic is entirely in
>> GnuPG (gpg-agent really). I think this is the way it should work in general.
>> The app using OpenPGP should only be aware of the things it cares about:
>> selecting keys, decrypting, encrypting, signing, and verifying. Everything
>> else can be transparently handled by the OpenPGP provider.
>
> A service (in keychain) can start Activities with startActivity() but it
> never knows when these activities are finished as there is no
> startActivityForResult() in services. Thus you need to delegate the
> starting to the current active Activity, which is on k9mail's side. As
> said, this is done similar in AccountManager and Google's in-app billing
> API.
> We need to know when the activity finishes to restart decrypting with
> the service.
>
> If you know another way, please tell me exactly how to do it. Then we
> can throw away the onActivityRequired in the CryptoCallback.

The Service should startActivity() for the passphrase Activity which then
connects to the Service via an IBinder. Then the passphrase Activity can
communicate everything with the Service. In this model, you make all of the
logic in the Service, like password strength metering, password checking, etc.
and have the passphrase Activity entirely a dumb slave to the Service.

There would need to be a prompting queue in case a request for a passphrase
came in while a prompt was showing, but other than that it should be pretty
straightforward since there can be only one passphrase prompt showing at a time.



>>> Regarding registration of crypto provider:
>>> 1. open intent com.android.crypto.REGISTER from k9mail with intent
>>> chooser -> all apps with this intent action will be listed there
>>> 2. keychain's crypto_provider.RegisterActivity will be called and asks
>>> to allow access.
>>> 3. keychain will save packagename of app that called this intent if
>>> allowed by user. Later in the service, only this app will be allowed to
>>> use the service.
>>
>> Why make a special Intent for registering? Why not just do this with any of
>> the standard crypto Intents? Then an individual app could decide to query
>> ENCRYPT and use the reply for every crypto operation, while another app could
>> query ENCRYPT, DECRYPT, VERIFY, SIGN, SELECT, etc. and register a separate app
>> to handle each operation. I think this would make for a simpler yet more
>> flexible API. I suppose having a REGISTER Intent would make it clear that
>> registration is required.
>
> I think you misunderstood something. I don't want to use any of the old
> intents. There is just _one_ Intent for other apps to use:
> com.android.crypto.REGISTER. After that you need to use the service.

Ah I see now. I'll have to try this idea out before I can comment much on it.
I'll try to do that today.

.hc
signature.asc

Dominik Schürmann

unread,
May 29, 2013, 9:44:56 AM5/29/13
to k-9...@googlegroups.com

@cketti: I think we could already communicate with openintents project
that we need a namespace for crypto. Better they choose the namespace
and tell us. Something like org.openintents.crypto.X would be nice.

In my model the intent actions would be:
org.openintents.crypto.REGISTER -> register app to use crypto provider
org.openintents.crypto.ICryptoService -> service name to bind to (to
choose actual crypto provider you can set package on binding with
serviceIntent.setPackage(cryptoProviderPackageName)



On 29.05.2013 15:20, Hans-Christoph Steiner wrote:
> The Service should startActivity() for the passphrase Activity which then
> connects to the Service via an IBinder. Then the passphrase Activity can
> communicate everything with the Service. In this model, you make all of the
> logic in the Service, like password strength metering, password checking, etc.
> and have the passphrase Activity entirely a dumb slave to the Service.
>
> There would need to be a prompting queue in case a request for a passphrase
> came in while a prompt was showing, but other than that it should be pretty
> straightforward since there can be only one passphrase prompt showing at a time.
>

Ah nice. You are right. Then we don't need any Intent returns.
I will try to implement that im my keychain.
signature.asc

Hans-Christoph Steiner

unread,
May 29, 2013, 11:34:53 AM5/29/13
to k-9...@googlegroups.com


On 05/29/2013 09:44 AM, Dominik Schürmann wrote:
>
> @cketti: I think we could already communicate with openintents project
> that we need a namespace for crypto. Better they choose the namespace
> and tell us. Something like org.openintents.crypto.X would be nice.
>
> In my model the intent actions would be:
> org.openintents.crypto.REGISTER -> register app to use crypto provider
> org.openintents.crypto.ICryptoService -> service name to bind to (to
> choose actual crypto provider you can set package on binding with
> serviceIntent.setPackage(cryptoProviderPackageName)

That sounds good to me. I'm still thinking that having generic Intents will
be generally useful, but this can be in addition to the AIDL/Service API that
you are developing. But I could be convinced to go only AIDL/Service and
ditch all the rest if I see that its as simple to use as an Intent-based API.
We place great importance at making the APIs we develop as simple as possible
because it helps drive adoption if its simple to get started and implement.


> On 29.05.2013 15:20, Hans-Christoph Steiner wrote:
>> The Service should startActivity() for the passphrase Activity which then
>> connects to the Service via an IBinder. Then the passphrase Activity can
>> communicate everything with the Service. In this model, you make all of the
>> logic in the Service, like password strength metering, password checking, etc.
>> and have the passphrase Activity entirely a dumb slave to the Service.
>>
>> There would need to be a prompting queue in case a request for a passphrase
>> came in while a prompt was showing, but other than that it should be pretty
>> straightforward since there can be only one passphrase prompt showing at a time.
>>
>
> Ah nice. You are right. Then we don't need any Intent returns.
> I will try to implement that im my keychain.

Our GnuPG pinentry passphrase Activity might have useful code for you. The
Android code was all written by Abel Luck as part of our PSST project, so I
think we can give it to you under whatever license you're using, if that's
useful to you. Let me double-check with Abel. The GnuPG code is of course
covered by their license, which I believe is GPL or LGPL.

https://github.com/guardianproject/gnupg-for-android/tree/master/src/info/guardianproject/gpg/pinentry
https://github.com/guardianproject/pinentry

.hc
signature.asc

Hans-Christoph Steiner

unread,
Jun 3, 2013, 8:24:37 PM6/3/13
to k-9...@googlegroups.com

Hey Dominik,

I was looking into this a bit more, comparing the AIDL vs Messenger approach
[1][2]. AIDL is so complicated but the interface you have does seem pretty
straightforward. Your demo app does not use it as an external process via the
oneway functions, so its hard to see what it would look like to the clients
who would be using that API.

Also, AIDL assumes multi-threaded operation of the Service, but I think that
compared to a queue-based Messenger Service, a setup that runs crypto
operations in parallel will probably provide a worse user experience most of
the time. Most phones are not very powerful, so having more than one
long-running crypto operation would cripple them. The queue that is automatic
when making a Messenger interaction with a Service comes for free, but maybe
the API would not be as nice since it wouldn't be Java Interfaces.

The one use case that I can think of where having a multi-threaded crypto
Service would provide a better experience is in the case of wanting very short
crypto operations while a long running crypto operation is running.

As far as I know gpg-agent uses a queue like Messenger.

[1] http://developer.android.com/guide/components/bound-services.html
[2] http://developer.android.com/reference/android/os/Messenger.html

.hc
signature.asc

Dominik Schürmann

unread,
Jun 7, 2013, 2:00:14 AM6/7/13
to k-9...@googlegroups.com
Hey Hans,

On 04.06.2013 02:24, Hans-Christoph Steiner wrote:
>
> Hey Dominik,
>
> I was looking into this a bit more, comparing the AIDL vs Messenger approach
> [1][2]. AIDL is so complicated but the interface you have does seem pretty
> straightforward. Your demo app does not use it as an external process via the
> oneway functions, so its hard to see what it would look like to the clients
> who would be using that API.

I implemented a test in
https://github.com/dschuermann/k-9/blob/crypto_provider/src/com/fsck/k9/view/MessageCryptoView.java

In onCreate you connect to the external service process and then you
implement ICryptoCallback.Stub() in that class. The onRequiredActivity
part will be removed. In decryptOnClick() you can see

mCryptoServiceConnection.getService().decryptAndVerify(data.getBytes(),
callback);

to execute decrypt remotely.

So I think, the client part is really convenient and easy as it is based
on implementing interfaces.

There is a lot to do to clean up my repo, also the Keychain Demo App
needs to be revised and updated.


>
> Also, AIDL assumes multi-threaded operation of the Service, but I think that
> compared to a queue-based Messenger Service, a setup that runs crypto
> operations in parallel will probably provide a worse user experience most of
> the time. Most phones are not very powerful, so having more than one
> long-running crypto operation would cripple them. The queue that is automatic
> when making a Messenger interaction with a Service comes for free, but maybe
> the API would not be as nice since it wouldn't be Java Interfaces.

I also need to implement threaded queues for each bound package,
currently working on this. AIDL services are not automatically thread safe.
Even though the passphrase is not entered, the apps should already queue
encrypt/decrypt operations that should be handled after entering the
passphrase.

Could you point me to the code where you start the passphrase dialog in
guardianproject's gpg and connect to your service for returning the
entered passphrase? I couldn't find this code.

I am currently time constraint, I will present more code at the end of
the next week.

Regards
Dominik
signature.asc

Hans-Christoph Steiner

unread,
Jun 12, 2013, 10:40:14 AM6/12/13
to k-9...@googlegroups.com


On 06/07/2013 02:00 AM, Dominik Schürmann wrote:
> Hey Hans,
>
> On 04.06.2013 02:24, Hans-Christoph Steiner wrote:
>>
>> Hey Dominik,
>>
>> I was looking into this a bit more, comparing the AIDL vs Messenger approach
>> [1][2]. AIDL is so complicated but the interface you have does seem pretty
>> straightforward. Your demo app does not use it as an external process via the
>> oneway functions, so its hard to see what it would look like to the clients
>> who would be using that API.
>
> I implemented a test in
> https://github.com/dschuermann/k-9/blob/crypto_provider/src/com/fsck/k9/view/MessageCryptoView.java
>
> In onCreate you connect to the external service process and then you
> implement ICryptoCallback.Stub() in that class. The onRequiredActivity
> part will be removed. In decryptOnClick() you can see
>
> mCryptoServiceConnection.getService().decryptAndVerify(data.getBytes(),
> callback);
>
> to execute decrypt remotely.
>
> So I think, the client part is really convenient and easy as it is based
> on implementing interfaces.
>
> There is a lot to do to clean up my repo, also the Keychain Demo App
> needs to be revised and updated.

My last concern with this is related to the chain of Intents and the whole
back queue and "recently used" functionality. So we're still planning on
having gpgcli handle the prompting for passphrases, and for sorting out if
there are multiple matches when searching for a key by email address.
Normally in Android, an Activity from a different app is started by launching
an Intent, so for example if K-9 requests encryption using an email address
that has multiple local keys, this is the flow (--> is an Intent):

k-9 --> gpgcli --> KeyListApp

But using AIDL there would be a broken chain:

k-9 AIDL>> gpgcli --> KeyListApp

I think that Android does not treat and AIDL call the same as an Intnet, and
this will end up causing strange behavior when switching around Activities,
like the back button will take you to the wrong place, or things like that.


>> Also, AIDL assumes multi-threaded operation of the Service, but I think that
>> compared to a queue-based Messenger Service, a setup that runs crypto
>> operations in parallel will probably provide a worse user experience most of
>> the time. Most phones are not very powerful, so having more than one
>> long-running crypto operation would cripple them. The queue that is automatic
>> when making a Messenger interaction with a Service comes for free, but maybe
>> the API would not be as nice since it wouldn't be Java Interfaces.
>
> I also need to implement threaded queues for each bound package,
> currently working on this. AIDL services are not automatically thread safe.
> Even though the passphrase is not entered, the apps should already queue
> encrypt/decrypt operations that should be handled after entering the
> passphrase.
>
> Could you point me to the code where you start the passphrase dialog in
> guardianproject's gpg and connect to your service for returning the
> entered passphrase? I couldn't find this code.
>
> I am currently time constraint, I will present more code at the end of
> the next week.

This is handled by gpg-agent for us. gpg-agent acts as the crypto engine and
also the core logic of the crypto operations. We just ask to
decrypt/verify/sign/encrypt without any thought to the passphrase, then
gpg-agent triggers the prompt if its needed. gpg-agent also handles the
caching of the passphrase.

You might be interested in our project cacheword. Its a password caching
service for android. We're tailoring it to things like SQLCipher, IOCipher,
etc. passwords but I think it could be applicable to this situation.
https://github.com/guardianproject/cacheword

Abel wrote it, so he can chime in with more details, or just ask him.

.hc
signature.asc

Abel Luck

unread,
Jun 12, 2013, 11:37:45 AM6/12/13
to k-9...@googlegroups.com
Hans-Christoph Steiner:
I don't think this is an issue, because of Tasks [0]. When K-9 calls the
AIDL method, gpgcli's service will be inside the K-9 "Task", so the
activity created with the Intent will be inside K-9's task. This can be
configured with the plethora of task attributes described on that page.

This is just conjecture though, we need to write a test app to be sure.


>> Could you point me to the code where you start the passphrase dialog in
>> guardianproject's gpg and connect to your service for returning the
>> entered passphrase? I couldn't find this code.
>>
>> I am currently time constraint, I will present more code at the end of
>> the next week.
>
> This is handled by gpg-agent for us. gpg-agent acts as the crypto engine and
> also the core logic of the crypto operations. We just ask to
> decrypt/verify/sign/encrypt without any thought to the passphrase, then
> gpg-agent triggers the prompt if its needed. gpg-agent also handles the
> caching of the passphrase.
>

A little more detail:

* gpg-agent is native daemon-like program
* when a crypto operation needs the passphrase, gpg-agent invokes pinentry
* pinentry is a native process that launches our PinentryActivity
* PinentryActivity then communicates with gog-agent via a unix domain
socket to prompt the user and show dialogs as needed

Here's the code [1] and documentation [2]. (Documentation is a bit out
of date, as I implemented a major refactor a few days ago)

> You might be interested in our project cacheword. Its a password caching
> service for android. We're tailoring it to things like SQLCipher, IOCipher,
> etc. passwords but I think it could be applicable to this situation.
> https://github.com/guardianproject/cacheword
>

Don't get confused, CacheWord is not related to GPG-for-android, it's a
parallel project that we don't need to use in GPG because we have
gpg-agent as Hans explained.

~abel

[0]:
http://developer.android.com/guide/components/tasks-and-back-stack.html#ManagingTasks
[1]:

https://github.com/guardianproject/pinentry/blob/master/android/pinentry-android.c
https://github.com/guardianproject/gnupg-for-android/tree/master/src/info/guardianproject/gpg/pinentry
https://github.com/guardianproject/gnupg-for-android/tree/master/src/info/guardianproject/gpg/pinentry

[2]:
https://github.com/guardianproject/gnupg-for-android/tree/master/docs/pinentry-implementation

Abel Luck

unread,
Jun 12, 2013, 11:40:46 AM6/12/13
to k-9...@googlegroups.com

Dominik Schürmann

unread,
Jun 17, 2013, 2:00:55 PM6/17/13
to k-9...@googlegroups.com
Hey Hans and Abel,

I got the basics working and implemented some tests in my Demo app.
I even got rid of the REGISTER intent.

I implemented a chooser that scans available intent services with
"org.openintents.crypto.ICryptoService" action. You can see
selectCryptoProvider() in
https://github.com/dschuermann/openpgp-keychain/blob/k9mail/OpenPGP-Keychain-API-Demo/src/org/sufficientlysecure/keychain/demo/CryptoProviderDemoActivity.java

I think this is a very nice generic way to retrieve available crypto
providers from client side. The selected provider can then be saved in
k9mail as default.

On Keychain's "server" side, a list of allowed packages is maintained
and when the first method is called from a bound process (from a
package) an activity is called that asks the user to allow or disallow
this package access to Keychain's API. The activity is also bound to the
service to execute callbacks. There are no problems with the activity
chain in my tests. After clicking back you get back to k9mail not Keychain.

There is much left todo for me, I keep you updated when the basic
operations are working. I now need to implement the actual methods
encrypt/decrypt etc on keychains side. This will need some time, as I am
currently constraint by my master thesis.

Regards
Dominik
signature.asc
Reply all
Reply to author
Forward
0 new messages