From e98da44612618fdff3c1d98091d6cbc66294b3b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 5 May 2015 21:58:56 +0200 Subject: [PATCH] Destroyed OpenPGP API (markdown) --- OpenPGP-API.md | 161 ------------------------------------------------- 1 file changed, 161 deletions(-) delete mode 100644 OpenPGP-API.md diff --git a/OpenPGP-API.md b/OpenPGP-API.md deleted file mode 100644 index 5e94789..0000000 --- a/OpenPGP-API.md +++ /dev/null @@ -1,161 +0,0 @@ -The OpenPGP API provides methods to execute OpenPGP operations, such as sign, encrypt, decrypt, verify, and more without user interaction from background threads. -This is done by connecting your client application to a remote service provided by OpenKeychain. -To get an idea how this API works from a user's perspective install [OpenKeychain](https://play.google.com/store/apps/details?id=org.sufficientlysecure.keychain) and the [API Demo](https://play.google.com/store/apps/details?id=org.sufficientlysecure.keychain.demo) - -## License -While OpenKeychain itself is GPLv3+, the API library is licensed under Apache License v2. -Thus, you are allowed to also use it in closed source applications as long as you respect the [Apache License v2](https://github.com/open-keychain/openpgp-api-lib/blob/master/LICENSE). - -## Complete example -A complete working example is available in the [api-example project](https://github.com/open-keychain/api-example). The [``OpenPgpApiActivity.java``](https://github.com/open-keychain/api-example/blob/master/example-app/src/main/java/org/sufficientlysecure/keychain/demo/OpenPgpApiActivity.java) contains most relevant sourcecode. - -## 1. Add the API library to your project -Clone the git repository [https://github.com/open-keychain/openpgp-api-lib](https://github.com/open-keychain/openpgp-api-lib) into a subfolder of your projects directory. - -### Gradle/Android Studio -1. Reference the library by including the library project in your ``settings.gradle`` file (adjust the path to your folder layout): - - ``` - include ':libraries:openpgp-api-lib' - ``` -2. Add the new include as a dependency to your ``build.gradle`` file: - - ``` - compile project(':libraries:openpgp-api-lib') - ``` - -### Eclipse -Please read ["Referencing a library project"](http://developer.android.com/tools/projects/projects-eclipse.html#ReferencingLibraryProject) how this can be done with Eclipse. - - -## 2. Understand the basic design of the OpenPGP API -The API is **not** designed around ``Intents`` which are started via ``startActivityForResult``. These Intent actions typically start an activity for user interaction, so they are not suitable for background tasks. Most API design decisions are explained at [the bottom of this wiki page](https://github.com/open-keychain/open-keychain/wiki/OpenPGP-API#internal-design-decisions). - -We will go through the basic steps to understand how this API works, following this (greatly simplified) sequence diagram: -![](https://github.com/open-keychain/open-keychain/raw/master/Resources/docs/openpgp_api_1.jpg) - -In this diagram the client app is depicted on the left side, the OpenPGP provider (in this case OpenKeychain) is depicted on the right. -The remote service is defined via the [AIDL](http://developer.android.com/guide/components/aidl.html) file [``IOpenPgpService``](https://github.com/open-keychain/openpgp-api-lib/blob/master/src/org/openintents/openpgp/IOpenPgpService.aidl). -It contains only one exposed method which can be invoked remotely: -```java -interface IOpenPgpService { - Intent execute(in Intent data, in ParcelFileDescriptor input, in ParcelFileDescriptor output); -} -``` -The interaction between the apps is done by binding from your client app to the remote service of OpenKeychain. -``OpenPgpServiceConnection`` is a helper class from the library to ease this step: -```java -OpenPgpServiceConnection mServiceConnection; - -public void onCreate(Bundle savedInstance) { - [...] - mServiceConnection = new OpenPgpServiceConnection(this, "org.sufficientlysecure.keychain"); - mServiceConnection.bindToService(); -} - -public void onDestroy() { - [...] - if (mServiceConnection != null) { - mServiceConnection.unbindFromService(); - } -} -``` - -Following the sequence diagram, these steps are executed: - -1. Define an ``Intent`` containing the actual PGP instructions which should be done, e.g. - ```java -Intent data = new Intent(); -data.setAction(OpenPgpApi.ACTION_ENCRYPT); -data.putExtra(OpenPgpApi.EXTRA_USER_IDS, new String[]{"dominik@dominikschuermann.de"}); -data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); - ``` - Define an ``InputStream`` currently holding the plaintext, and an ``OutputStream`` where you want the ciphertext to be written by OpenKeychain's remote service: - ```java -InputStream is = new ByteArrayInputStream("Hello world!".getBytes("UTF-8")); -ByteArrayOutputStream os = new ByteArrayOutputStream(); - ``` - Using a helper class from the library, ``is`` and ``os`` are passed via ``ParcelFileDescriptors`` as ``input`` and ``output`` together with ``Intent data``, as depicted in the sequence diagram, from the client to the remote service. - Programmatically, this can be done with: - ```java -OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService()); -Intent result = api.executeApi(data, is, os); - ``` - -2. The PGP operation is executed by OpenKeychain and the produced ciphertext is written into ``os`` which can then be accessed by the client app. - -3. A result Intent is returned containing one of these result codes: - * ``OpenPgpApi.RESULT_CODE_ERROR`` - * ``OpenPgpApi.RESULT_CODE_SUCCESS`` - * ``OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED`` - - If ``RESULT_CODE_USER_INTERACTION_REQUIRED`` is returned, an additional ``PendingIntent`` is returned to the client, which must be used to get user input required to process the request. - A ``PendingIntent`` is executed with ``startIntentSenderForResult``, which starts a activity, originally belonging to OpenKeychain, on the [task stack](http://developer.android.com/guide/components/tasks-and-back-stack.html) of the client. - Only if ``RESULT_CODE_SUCCESS`` is returned, ``os`` actually contains data. - A nearly complete example looks like this: - ```java - switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { - case OpenPgpApi.RESULT_CODE_SUCCESS: { - try { - Log.d(OpenPgpApi.TAG, "output: " + os.toString("UTF-8")); - } catch (UnsupportedEncodingException e) { - Log.e(Constants.TAG, "UnsupportedEncodingException", e); - } - - if (result.hasExtra(OpenPgpApi.RESULT_SIGNATURE)) { - OpenPgpSignatureResult sigResult - = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE); - [...] - } - break; - } - case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: { - PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); - try { - startIntentSenderForResult(pi.getIntentSender(), 42, null, 0, 0, 0); - } catch (IntentSender.SendIntentException e) { - Log.e(Constants.TAG, "SendIntentException", e); - } - break; - } - case OpenPgpApi.RESULT_CODE_ERROR: { - OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); - [...] - break; - } - } - ``` - -4. Results from a ``PendingIntent`` are returned in ``onActivityResult`` of the activity, which executed ``startIntentSenderForResult``. - The returned ``Intent data`` in ``onActivityResult`` contains the original PGP operation definition and new values acquired from the user interaction. - Thus, you can now execute the ``Intent`` again, like done in step 1. - This time it should return with ``RESULT_CODE_SUCCESS`` because all required information has been obtained by the previous user interaction stored in this ``Intent``. - ```java - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - [...] - // try again after user interaction - if (resultCode == RESULT_OK) { - switch (requestCode) { - case 42: { - encrypt(data); // defined like in step 1 - break; - } - } - } - } - ``` - - -## 3. Tipps -* ``api.executeApi(data, is, os);`` is a blocking call. If you want a convenient asynchronous call, use ``api.executeApiAsync(data, is, os, new MyCallback([... ]));``, where ``MyCallback`` is an private class implementing ``OpenPgpApi.IOpenPgpCallback``. - See [``OpenPgpApiActivity.java``](https://github.com/open-keychain/api-example/blob/master/example-app/src/main/java/org/sufficientlysecure/keychain/demo/OpenPgpApiActivity.java) for an example. -* Using - - ```java - mServiceConnection = new OpenPgpServiceConnection(this, "org.sufficientlysecure.keychain"); - ``` - connects to OpenKeychain directly. - If you want to let the user choose between OpenPGP providers, you can implement the [``OpenPgpAppPreference.java``](https://github.com/open-keychain/openpgp-api-lib/blob/master/src/main/java/org/openintents/openpgp/util/OpenPgpAppPreference.java) like done in the example app. - -## Internal Design Decisions -Go to [[API-Design|API-Design]] \ No newline at end of file