diff options
Diffstat (limited to 'OpenPGP-Keychain-API-Demo')
9 files changed, 604 insertions, 171 deletions
diff --git a/OpenPGP-Keychain-API-Demo/res/layout/crypto_provider_demo.xml b/OpenPGP-Keychain-API-Demo/res/layout/crypto_provider_demo.xml index 447734a52..af1e345d6 100644 --- a/OpenPGP-Keychain-API-Demo/res/layout/crypto_provider_demo.xml +++ b/OpenPGP-Keychain-API-Demo/res/layout/crypto_provider_demo.xml @@ -8,65 +8,72 @@          android:layout_height="match_parent"          android:orientation="vertical" > -        <Button -            android:id="@+id/crypto_provider_demo_register" -            android:layout_width="match_parent" +        <TextView +            android:layout_width="wrap_content"              android:layout_height="wrap_content" -            android:onClick="registerCryptoProvider" -            android:text="Register crypto provider" /> +            android:text="Encrypt User Id" +            android:textAppearance="?android:attr/textAppearanceMedium" /> -        <Button -            android:id="@+id/aidl_demo_select_secret_key" +        <EditText +            android:id="@+id/crypto_provider_demo_encrypt_user_id"              android:layout_width="match_parent"              android:layout_height="wrap_content" -            android:onClick="selectSecretKeyOnClick" -            android:text="Select secret key" /> +            android:text="dominik@dominikschuermann.de" +            android:textAppearance="@android:style/TextAppearance.Small" /> -        <Button -            android:id="@+id/aidl_demo_select_encryption_key" -            android:layout_width="match_parent" +        <TextView +            android:layout_width="wrap_content"              android:layout_height="wrap_content" -            android:onClick="selectEncryptionKeysOnClick" -            android:text="Select encryption key(s)" /> +            android:text="Message" +            android:textAppearance="?android:attr/textAppearanceMedium" />          <EditText -            android:id="@+id/aidl_demo_message" +            android:id="@+id/crypto_provider_demo_message"              android:layout_width="match_parent"              android:layout_height="150dip"              android:text="message"              android:textAppearance="@android:style/TextAppearance.Small" /> +        <TextView +            android:layout_width="wrap_content" +            android:layout_height="wrap_content" +            android:text="Ciphertext" +            android:textAppearance="?android:attr/textAppearanceMedium" /> +          <EditText -            android:id="@+id/aidl_demo_ciphertext" +            android:id="@+id/crypto_provider_demo_ciphertext"              android:layout_width="match_parent"              android:layout_height="150dip"              android:text="ciphertext"              android:textAppearance="@android:style/TextAppearance.Small" />          <Button -            android:id="@+id/aidl_demo_encrypt" +            android:id="@+id/crypto_provider_demo_encrypt"              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:onClick="encryptOnClick"              android:text="Encrypt" />          <Button -            android:id="@+id/aidl_demo_decrypt" +            android:id="@+id/crypto_provider_demo_sign"              android:layout_width="match_parent"              android:layout_height="wrap_content" -            android:onClick="decryptOnClick" -            android:text="Decrypt" /> +            android:onClick="signOnClick" +            android:text="Sign" /> -        <TextView +        <Button +            android:id="@+id/crypto_provider_demo_encrypt_and_sign"              android:layout_width="match_parent" -            android:layout_height="match_parent" -            android:text="APG Data:" /> +            android:layout_height="wrap_content" +            android:onClick="encryptAndSignOnClick" +            android:text="Encrypt and Sign" /> -        <TextView -            android:id="@+id/aidl_demo_data" +        <Button +            android:id="@+id/crypto_provider_demo_decrypt"              android:layout_width="match_parent" -            android:layout_height="match_parent" -            android:minLines="10" /> +            android:layout_height="wrap_content" +            android:onClick="decryptOnClick" +            android:text="Decrypt" />      </LinearLayout>  </ScrollView>
\ No newline at end of file diff --git a/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoError.aidl b/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoError.aidl new file mode 100644 index 000000000..7b67c8995 --- /dev/null +++ b/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoError.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +  +package org.openintents.crypto; + +// Declare CryptoError so AIDL can find it and knows that it implements the parcelable protocol. +parcelable CryptoError;
\ No newline at end of file diff --git a/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoError.java b/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoError.java new file mode 100644 index 000000000..265fe2633 --- /dev/null +++ b/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoError.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.crypto; + +import android.os.Parcel; +import android.os.Parcelable; + +public class CryptoError implements Parcelable { +    int errorId; +    String message; + +    public CryptoError() { +    } + +    public CryptoError(int errorId, String message) { +        this.errorId = errorId; +        this.message = message; +    } + +    public CryptoError(CryptoError b) { +        this.errorId = b.errorId; +        this.message = b.message; +    } + +    public int getErrorId() { +        return errorId; +    } + +    public void setErrorId(int errorId) { +        this.errorId = errorId; +    } + +    public String getMessage() { +        return message; +    } + +    public void setMessage(String message) { +        this.message = message; +    } + +    public int describeContents() { +        return 0; +    } + +    public void writeToParcel(Parcel dest, int flags) { +        dest.writeInt(errorId); +        dest.writeString(message); +    } + +    public static final Creator<CryptoError> CREATOR = new Creator<CryptoError>() { +        public CryptoError createFromParcel(final Parcel source) { +            CryptoError error = new CryptoError(); +            error.errorId = source.readInt(); +            error.message = source.readString(); +            return error; +        } + +        public CryptoError[] newArray(final int size) { +            return new CryptoError[size]; +        } +    }; +} diff --git a/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoServiceConnection.java b/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoServiceConnection.java new file mode 100644 index 000000000..d9e91f772 --- /dev/null +++ b/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoServiceConnection.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.crypto; + +import org.openintents.crypto.ICryptoService; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.util.Log; + +public class CryptoServiceConnection { +    private Context mApplicationContext; + +    private ICryptoService mService; +    private boolean bound; +    private String cryptoProviderPackageName; + +    private static final String TAG = "CryptoConnection"; + +    public CryptoServiceConnection(Context context, String cryptoProviderPackageName) { +        mApplicationContext = context.getApplicationContext(); +        this.cryptoProviderPackageName = cryptoProviderPackageName; +    } + +    public ICryptoService getService() { +        return mService; +    } + +    private ServiceConnection mCryptoServiceConnection = new ServiceConnection() { +        public void onServiceConnected(ComponentName name, IBinder service) { +            mService = ICryptoService.Stub.asInterface(service); +            Log.d(TAG, "connected to service"); +            bound = true; +        } + +        public void onServiceDisconnected(ComponentName name) { +            mService = null; +            Log.d(TAG, "disconnected from service"); +            bound = false; +        } +    }; + +    /** +     * If not already bound, bind! +     *  +     * @return +     */ +    public boolean bindToService() { +        if (mService == null && !bound) { // if not already connected +            try { +                Log.d(TAG, "not bound yet"); + +                Intent serviceIntent = new Intent(); +                serviceIntent.setAction("org.openintents.crypto.ICryptoService"); +                serviceIntent.setPackage(cryptoProviderPackageName); +                mApplicationContext.bindService(serviceIntent, mCryptoServiceConnection, +                        Context.BIND_AUTO_CREATE); + +                return true; +            } catch (Exception e) { +                Log.d(TAG, "Exception", e); +                return false; +            } +        } else { // already connected +            Log.d(TAG, "already bound... "); +            return true; +        } +    } + +    public void unbindFromService() { +        mApplicationContext.unbindService(mCryptoServiceConnection); +    } + +} diff --git a/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoSignatureResult.aidl b/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoSignatureResult.aidl new file mode 100644 index 000000000..1d39bac70 --- /dev/null +++ b/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoSignatureResult.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +  +package org.openintents.crypto; + +// Declare CryptoSignatureResult so AIDL can find it and knows that it implements the parcelable protocol. +parcelable CryptoSignatureResult;
\ No newline at end of file diff --git a/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoSignatureResult.java b/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoSignatureResult.java new file mode 100644 index 000000000..e193b73b3 --- /dev/null +++ b/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/CryptoSignatureResult.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.crypto; + +import android.os.Parcel; +import android.os.Parcelable; + +public class CryptoSignatureResult implements Parcelable { +    String signatureUserId; + +    boolean signature; +    boolean signatureSuccess; +    boolean signatureUnknown; + +    public CryptoSignatureResult() { + +    } + +    public CryptoSignatureResult(String signatureUserId, boolean signature, +            boolean signatureSuccess, boolean signatureUnknown) { +        this.signatureUserId = signatureUserId; + +        this.signature = signature; +        this.signatureSuccess = signatureSuccess; +        this.signatureUnknown = signatureUnknown; +    } + +    public CryptoSignatureResult(CryptoSignatureResult b) { +        this.signatureUserId = b.signatureUserId; + +        this.signature = b.signature; +        this.signatureSuccess = b.signatureSuccess; +        this.signatureUnknown = b.signatureUnknown; +    } + +    public int describeContents() { +        return 0; +    } + +    public void writeToParcel(Parcel dest, int flags) { +        dest.writeString(signatureUserId); + +        dest.writeByte((byte) (signature ? 1 : 0)); +        dest.writeByte((byte) (signatureSuccess ? 1 : 0)); +        dest.writeByte((byte) (signatureUnknown ? 1 : 0)); +    } + +    public static final Creator<CryptoSignatureResult> CREATOR = new Creator<CryptoSignatureResult>() { +        public CryptoSignatureResult createFromParcel(final Parcel source) { +            CryptoSignatureResult vr = new CryptoSignatureResult(); +            vr.signatureUserId = source.readString(); +            vr.signature = source.readByte() == 1; +            vr.signatureSuccess = source.readByte() == 1; +            vr.signatureUnknown = source.readByte() == 1; +            return vr; +        } + +        public CryptoSignatureResult[] newArray(final int size) { +            return new CryptoSignatureResult[size]; +        } +    }; +} diff --git a/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/ICryptoCallback.aidl b/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/ICryptoCallback.aidl new file mode 100644 index 000000000..1f910d4c6 --- /dev/null +++ b/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/ICryptoCallback.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.crypto; + +import org.openintents.crypto.CryptoSignatureResult; +import org.openintents.crypto.CryptoError; + +interface ICryptoCallback { +     +    /** +     * CryptoSignatureResult is only returned if the Callback was used from decryptAndVerify +     * +     */ +    oneway void onSuccess(in byte[] outputBytes, in CryptoSignatureResult signatureResult); + + +    oneway void onError(in CryptoError error); +}
\ No newline at end of file diff --git a/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/ICryptoService.aidl b/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/ICryptoService.aidl new file mode 100644 index 000000000..c84ca28fb --- /dev/null +++ b/OpenPGP-Keychain-API-Demo/src/org/openintents/crypto/ICryptoService.aidl @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +  +package org.openintents.crypto; + +import org.openintents.crypto.ICryptoCallback; + +/** + * All methods are oneway, which means they are asynchronous and non-blocking. + * Results are returned to the callback, which has to be implemented on client side. + */ +interface ICryptoService { +        +    /** +     * Encrypt +     *  +     * @param inputBytes +     *            Byte array you want to encrypt +     * @param encryptionUserIds +     *            User Ids (emails) of recipients +     * @param callback +     *            Callback where to return results +     */ +    oneway void encrypt(in byte[] inputBytes, in String[] encryptionUserIds, in ICryptoCallback callback); +     +    /** +     * Sign +     * +     * @param inputBytes +     *            Byte array you want to encrypt +     * @param signatureUserId +     *            User Ids (email) of sender +     * @param callback +     *            Callback where to return results +     */ +    oneway void sign(in byte[] inputBytes, String signatureUserId, in ICryptoCallback callback); +     +    /** +     * Encrypt and sign +     * +     * @param inputBytes +     *            Byte array you want to encrypt +     * @param encryptionUserIds +     *            User Ids (emails) of recipients +     * @param signatureUserId +     *            User Ids (email) of sender +     * @param callback +     *            Callback where to return results +     */ +    oneway void encryptAndSign(in byte[] inputBytes, in String[] encryptionUserIds, String signatureUserId, in ICryptoCallback callback); +     +    /** +     * Decrypts and verifies given input bytes. If no signature is present this method +     * will only decrypt. +     *  +     * @param inputBytes +     *            Byte array you want to decrypt and verify +     * @param callback +     *            Callback where to return results +     */ +    oneway void decryptAndVerify(in byte[] inputBytes, in ICryptoCallback callback); +     +    /** +     * Opens setup using default parameters +     * +     */ +    oneway void setup(boolean asciiArmor, boolean newKeyring, String newKeyringUserId); +     +}
\ No newline at end of file diff --git a/OpenPGP-Keychain-API-Demo/src/org/sufficientlysecure/keychain/demo/CryptoProviderDemoActivity.java b/OpenPGP-Keychain-API-Demo/src/org/sufficientlysecure/keychain/demo/CryptoProviderDemoActivity.java index b915e2a76..319820d7c 100644 --- a/OpenPGP-Keychain-API-Demo/src/org/sufficientlysecure/keychain/demo/CryptoProviderDemoActivity.java +++ b/OpenPGP-Keychain-API-Demo/src/org/sufficientlysecure/keychain/demo/CryptoProviderDemoActivity.java @@ -1,5 +1,5 @@  /* - * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de> + * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>   *   * Licensed under the Apache License, Version 2.0 (the "License");   * you may not use this file except in compliance with the License. @@ -16,51 +16,42 @@  package org.sufficientlysecure.keychain.demo; +import java.util.ArrayList; +import java.util.List; + +import org.openintents.crypto.CryptoError; +import org.openintents.crypto.CryptoServiceConnection; +import org.openintents.crypto.CryptoSignatureResult; +import org.openintents.crypto.ICryptoCallback; +import org.openintents.crypto.ICryptoService;  import org.sufficientlysecure.keychain.demo.R;  import org.sufficientlysecure.keychain.integration.Constants; -import org.sufficientlysecure.keychain.integration.KeychainData; -import org.sufficientlysecure.keychain.integration.KeychainIntentHelper; -import org.sufficientlysecure.keychain.service.IKeychainApiService; -import org.sufficientlysecure.keychain.service.IKeychainKeyService; -import org.sufficientlysecure.keychain.service.handler.IKeychainDecryptHandler; -import org.sufficientlysecure.keychain.service.handler.IKeychainEncryptHandler; -import org.sufficientlysecure.keychain.service.handler.IKeychainGetDecryptionKeyIdHandler;  import android.app.Activity;  import android.app.AlertDialog; -import android.content.ActivityNotFoundException; -import android.content.ComponentName; -import android.content.Context; +import android.content.DialogInterface;  import android.content.Intent; -import android.content.ServiceConnection; +import android.content.pm.ResolveInfo; +import android.graphics.drawable.Drawable;  import android.os.Bundle; -import android.os.IBinder;  import android.os.RemoteException;  import android.util.Log;  import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.ListAdapter;  import android.widget.TextView; -import android.widget.Toast;  public class CryptoProviderDemoActivity extends Activity {      Activity mActivity; -    TextView mMessageTextView; -    TextView mCiphertextTextView; -    TextView mDataTextView; - -    KeychainIntentHelper mKeychainIntentHelper; -    KeychainData mKeychainData; +    EditText mMessage; +    EditText mCiphertext; +    EditText mEncryptUserId; +    EditText mSignUserId; -    private IKeychainApiService service = null; -    private ServiceConnection svcConn = new ServiceConnection() { -        public void onServiceConnected(ComponentName className, IBinder binder) { -            service = IKeychainApiService.Stub.asInterface(binder); -        } - -        public void onServiceDisconnected(ComponentName className) { -            service = null; -        } -    }; +    private CryptoServiceConnection mCryptoServiceConnection;      @Override      public void onCreate(Bundle icicle) { @@ -69,170 +60,208 @@ public class CryptoProviderDemoActivity extends Activity {          mActivity = this; -        mMessageTextView = (TextView) findViewById(R.id.aidl_demo_message); -        mCiphertextTextView = (TextView) findViewById(R.id.aidl_demo_ciphertext); -        mDataTextView = (TextView) findViewById(R.id.aidl_demo_data); - -        mKeychainIntentHelper = new KeychainIntentHelper(mActivity); -        mKeychainData = new KeychainData(); +        mMessage = (EditText) findViewById(R.id.crypto_provider_demo_message); +        mCiphertext = (EditText) findViewById(R.id.crypto_provider_demo_ciphertext); +        mEncryptUserId = (EditText) findViewById(R.id.crypto_provider_demo_encrypt_user_id); -        bindService(new Intent(IKeychainApiService.class.getName()), svcConn, -                Context.BIND_AUTO_CREATE); +        selectCryptoProvider();      } -    public void registerCryptoProvider(View view) { -        try { -            startActivityForResult(Intent.createChooser(new Intent("com.android.crypto.REGISTER"), -                    "select crypto provider"), 123); -        } catch (ActivityNotFoundException e) { -            Toast.makeText(mActivity, "No app that handles com.android.crypto.REGISTER!", -                    Toast.LENGTH_LONG).show(); -            Log.e(Constants.TAG, "No app that handles com.android.crypto.REGISTER!"); +    /** +     * Callback from remote crypto service +     */ +    final ICryptoCallback.Stub encryptCallback = new ICryptoCallback.Stub() { + +        @Override +        public void onSuccess(final byte[] outputBytes, CryptoSignatureResult signatureResult) +                throws RemoteException { +            Log.d(Constants.TAG, "onEncryptSignSuccess"); + +            runOnUiThread(new Runnable() { + +                @Override +                public void run() { +                    mCiphertext.setText(new String(outputBytes)); + +                } +            });          } -    } -    @Override -    protected void onActivityResult(int requestCode, int resultCode, Intent data) { -        if (requestCode == 123) { -            if (resultCode == RESULT_OK) { -                String packageName = data.getStringExtra("packageName"); -                Log.d(Constants.TAG, "packageName: " + packageName); -            } +        @Override +        public void onError(CryptoError error) throws RemoteException { +            Log.e(Constants.TAG, "onError getErrorId:" + error.getErrorId()); +            Log.e(Constants.TAG, "onError getMessage:" + error.getMessage());          } -        // boolean result = mKeychainIntentHelper.onActivityResult(requestCode, resultCode, data, -        // mKeychainData); -        // if (result) { -        // updateView(); -        // } +    }; -        // continue with other activity results -        super.onActivityResult(requestCode, resultCode, data); -    } +    final ICryptoCallback.Stub decryptCallback = new ICryptoCallback.Stub() { + +        @Override +        public void onSuccess(final byte[] outputBytes, final CryptoSignatureResult signatureResult) +                throws RemoteException { +            Log.d(Constants.TAG, "onDecryptVerifySuccess"); + +            runOnUiThread(new Runnable() { + +                @Override +                public void run() { +                    mMessage.setText(new String(outputBytes) + "\n\n" + signatureResult.toString()); + +                } +            }); + +        } + +        @Override +        public void onError(CryptoError error) throws RemoteException { +            Log.e(Constants.TAG, "onError getErrorId:" + error.getErrorId()); +            Log.e(Constants.TAG, "onError getMessage:" + error.getMessage()); +        } + +    };      public void encryptOnClick(View view) { -        byte[] inputBytes = mMessageTextView.getText().toString().getBytes(); +        byte[] inputBytes = mMessage.getText().toString().getBytes();          try { -            service.encryptAsymmetric(inputBytes, null, true, 0, mKeychainData.getPublicKeys(), 7, -                    encryptHandler); +            mCryptoServiceConnection.getService().encrypt(inputBytes, +                    new String[] { mEncryptUserId.getText().toString() }, encryptCallback);          } catch (RemoteException e) { -            exceptionImplementation(-1, e.toString()); +            Log.e(Constants.TAG, "CryptoProviderDemo", e);          }      } -    public void decryptOnClick(View view) { -        byte[] inputBytes = mCiphertextTextView.getText().toString().getBytes(); +    public void signOnClick(View view) { +        byte[] inputBytes = mMessage.getText().toString().getBytes();          try { -            service.decryptAndVerifyAsymmetric(inputBytes, null, null, decryptHandler); +            mCryptoServiceConnection.getService().sign(inputBytes, +                    mSignUserId.getText().toString(), encryptCallback);          } catch (RemoteException e) { -            exceptionImplementation(-1, e.toString()); +            Log.e(Constants.TAG, "CryptoProviderDemo", e);          }      } -    private void updateView() { -        if (mKeychainData.getDecryptedData() != null) { -            mMessageTextView.setText(mKeychainData.getDecryptedData()); +    public void encryptAndSignOnClick(View view) { +        byte[] inputBytes = mMessage.getText().toString().getBytes(); + +        try { +            mCryptoServiceConnection.getService().encryptAndSign(inputBytes, +                    new String[] { mEncryptUserId.getText().toString() }, +                    mSignUserId.getText().toString(), encryptCallback); +        } catch (RemoteException e) { +            Log.e(Constants.TAG, "CryptoProviderDemo", e);          } -        if (mKeychainData.getEncryptedData() != null) { -            mCiphertextTextView.setText(mKeychainData.getEncryptedData()); +    } + +    public void decryptOnClick(View view) { +        byte[] inputBytes = mCiphertext.getText().toString().getBytes(); + +        try { +            mCryptoServiceConnection.getService().decryptAndVerify(inputBytes, decryptCallback); +        } catch (RemoteException e) { +            Log.e(Constants.TAG, "CryptoProviderDemo", e);          } -        mDataTextView.setText(mKeychainData.toString());      }      @Override      public void onDestroy() {          super.onDestroy(); -        unbindService(svcConn); -    } - -    private void exceptionImplementation(int exceptionId, String error) { -        AlertDialog.Builder builder = new AlertDialog.Builder(this); -        builder.setTitle("Exception!").setMessage(error).setPositiveButton("OK", null).show(); +        if (mCryptoServiceConnection != null) { +            mCryptoServiceConnection.unbindFromService(); +        }      } -    private final IKeychainEncryptHandler.Stub encryptHandler = new IKeychainEncryptHandler.Stub() { +    private static class CryptoProviderElement { +        private String packageName; +        private String simpleName; +        private Drawable icon; -        @Override -        public void onException(final int exceptionId, final String message) throws RemoteException { -            runOnUiThread(new Runnable() { -                public void run() { -                    exceptionImplementation(exceptionId, message); -                } -            }); +        public CryptoProviderElement(String packageName, String simpleName, Drawable icon) { +            this.packageName = packageName; +            this.simpleName = simpleName; +            this.icon = icon;          }          @Override -        public void onSuccess(final byte[] outputBytes, String outputUri) throws RemoteException { -            runOnUiThread(new Runnable() { -                public void run() { -                    mKeychainData.setEncryptedData(new String(outputBytes)); -                    updateView(); -                } -            }); +        public String toString() { +            return simpleName;          } +    } -    }; +    private void selectCryptoProvider() { +        Intent intent = new Intent(ICryptoService.class.getName()); -    private final IKeychainDecryptHandler.Stub decryptHandler = new IKeychainDecryptHandler.Stub() { +        final ArrayList<CryptoProviderElement> providerList = new ArrayList<CryptoProviderElement>(); -        @Override -        public void onException(final int exceptionId, final String message) throws RemoteException { -            runOnUiThread(new Runnable() { -                public void run() { -                    exceptionImplementation(exceptionId, message); -                } -            }); -        } +        List<ResolveInfo> resInfo = getPackageManager().queryIntentServices(intent, 0); +        if (!resInfo.isEmpty()) { +            for (ResolveInfo resolveInfo : resInfo) { +                if (resolveInfo.serviceInfo == null) +                    continue; -        @Override -        public void onSuccess(final byte[] outputBytes, String outputUri, boolean signature, -                long signatureKeyId, String signatureUserId, boolean signatureSuccess, -                boolean signatureUnknown) throws RemoteException { -            runOnUiThread(new Runnable() { -                public void run() { -                    mKeychainData.setDecryptedData(new String(outputBytes)); -                    updateView(); -                } -            }); +                String packageName = resolveInfo.serviceInfo.packageName; +                String simpleName = String.valueOf(resolveInfo.serviceInfo +                        .loadLabel(getPackageManager())); +                Drawable icon = resolveInfo.serviceInfo.loadIcon(getPackageManager()); +                providerList.add(new CryptoProviderElement(packageName, simpleName, icon)); +            } -        } +            AlertDialog.Builder alert = new AlertDialog.Builder(this); +            alert.setTitle("Select Crypto Provider!"); +            alert.setCancelable(false); -    }; +            if (!providerList.isEmpty()) { -    private final IKeychainGetDecryptionKeyIdHandler.Stub helperHandler = new IKeychainGetDecryptionKeyIdHandler.Stub() { +                // Init ArrayAdapter with Crypto Providers +                ListAdapter adapter = new ArrayAdapter<CryptoProviderElement>(this, +                        android.R.layout.select_dialog_item, android.R.id.text1, providerList) { +                    public View getView(int position, View convertView, ViewGroup parent) { +                        // User super class to create the View +                        View v = super.getView(position, convertView, parent); +                        TextView tv = (TextView) v.findViewById(android.R.id.text1); -        @Override -        public void onException(final int exceptionId, final String message) throws RemoteException { -            runOnUiThread(new Runnable() { -                public void run() { -                    exceptionImplementation(exceptionId, message); -                } -            }); -        } +                        // Put the image on the TextView +                        tv.setCompoundDrawablesWithIntrinsicBounds(providerList.get(position).icon, +                                null, null, null); -        @Override -        public void onSuccess(long arg0, boolean arg1) throws RemoteException { -            // TODO Auto-generated method stub +                        // Add margin between image and text (support various screen densities) +                        int dp5 = (int) (5 * getResources().getDisplayMetrics().density + 0.5f); +                        tv.setCompoundDrawablePadding(dp5); -        } +                        return v; +                    } +                }; -    }; +                alert.setSingleChoiceItems(adapter, -1, new DialogInterface.OnClickListener() { -    /** -     * Selection is done with Intents, not AIDL! -     *  -     * @param view -     */ -    public void selectSecretKeyOnClick(View view) { -        mKeychainIntentHelper.selectSecretKey(); -    } +                    public void onClick(DialogInterface dialog, int position) { +                        String packageName = providerList.get(position).packageName; -    public void selectEncryptionKeysOnClick(View view) { -        mKeychainIntentHelper.selectPublicKeys("user@example.com"); +                        // bind to service +                        mCryptoServiceConnection = new CryptoServiceConnection( +                                CryptoProviderDemoActivity.this, packageName); +                        mCryptoServiceConnection.bindToService(); -    } +                        dialog.dismiss(); +                    } +                }); +            } else { +                alert.setMessage("No Crypto Provider installed!"); +            } +            alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + +                public void onClick(DialogInterface dialog, int id) { +                    dialog.cancel(); +                    finish(); +                } +            }); + +            AlertDialog ad = alert.create(); +            ad.show(); +        } +    }  }  | 
