added file decryption, rewrote the various "Choice" derivations to us the Id structure as well

This commit is contained in:
Thialfihar 2010-04-22 15:30:19 +00:00
parent 26cf672d67
commit 78193007b2
10 changed files with 537 additions and 94 deletions

View File

@ -99,6 +99,17 @@
</activity> </activity>
<activity
android:name=".DecryptFileActivity"
android:label="@string/title_decryptFile"
android:configChanges="keyboardHidden|orientation|keyboard">
<intent-filter>
<action android:name="org.thialfihar.android.apg.intent.DECRYPT_FILE" />
</intent-filter>
</activity>
<activity <activity
android:name=".MailListActivity" android:name=".MailListActivity"
android:label="@string/title_mailInbox" android:label="@string/title_mailInbox"

122
res/layout/decrypt_file.xml Normal file
View File

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:paddingTop="5dip">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="5dip"
android:paddingRight="5dip">
<TextView
android:id="@+id/label_filename"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="50dip"
android:layout_height="wrap_content"
android:text="@string/label_file"/>
<EditText
android:id="@+id/filename"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<ImageButton
android:id="@+id/btn_browse"
android:src="@drawable/ic_launcher_folder_small"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
</LinearLayout>
<LinearLayout
android:id="@+id/layout_signature"
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="wrap_content">
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content">
<ImageView
android:id="@+id/ic_signature"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/signed_large"/>
<ImageView
android:id="@+id/ic_signature_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/overlay_error"/>
</RelativeLayout>
<LinearLayout
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingLeft="5dip">
<TextView
android:id="@+id/main_user_id"
android:text="Main User Id"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"/>
<TextView
android:id="@+id/main_user_id_rest"
android:text="Main User Id Rest"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="@android:style/ButtonBar">
<Button
android:id="@+id/btn_decrypt"
android:text="@string/btn_decrypt"
android:layout_weight="1"
android:layout_width="0dip"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>

View File

@ -275,14 +275,10 @@ public class Apg {
return mPassPhrase; return mPassPhrase;
} }
public static PGPSecretKey createKey(KeyEditor.AlgorithmChoice algorithmChoice, int keySize, public static PGPSecretKey createKey(int algorithmChoice, int keySize, String passPhrase)
String passPhrase)
throws NoSuchAlgorithmException, PGPException, NoSuchProviderException, throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
GeneralException, InvalidAlgorithmParameterException { GeneralException, InvalidAlgorithmParameterException {
if (algorithmChoice == null) {
throw new GeneralException("unknown algorithm choice");
}
if (keySize < 512) { if (keySize < 512) {
throw new GeneralException("key size must be at least 512bit"); throw new GeneralException("key size must be at least 512bit");
} }
@ -296,15 +292,15 @@ public class Apg {
int algorithm = 0; int algorithm = 0;
KeyPairGenerator keyGen = null; KeyPairGenerator keyGen = null;
switch (algorithmChoice.getId()) { switch (algorithmChoice) {
case KeyEditor.AlgorithmChoice.DSA: { case Id.choice.algorithm.dsa: {
keyGen = KeyPairGenerator.getInstance("DSA", new BouncyCastleProvider()); keyGen = KeyPairGenerator.getInstance("DSA", new BouncyCastleProvider());
keyGen.initialize(keySize, new SecureRandom()); keyGen.initialize(keySize, new SecureRandom());
algorithm = PGPPublicKey.DSA; algorithm = PGPPublicKey.DSA;
break; break;
} }
case KeyEditor.AlgorithmChoice.ELGAMAL: { case Id.choice.algorithm.elgamal: {
if (keySize != 2048) { if (keySize != 2048) {
throw new GeneralException("ElGamal currently requires 2048bit"); throw new GeneralException("ElGamal currently requires 2048bit");
} }
@ -323,7 +319,7 @@ public class Apg {
break; break;
} }
case KeyEditor.AlgorithmChoice.RSA: { case Id.choice.algorithm.rsa: {
keyGen = KeyPairGenerator.getInstance("RSA", new BouncyCastleProvider()); keyGen = KeyPairGenerator.getInstance("RSA", new BouncyCastleProvider());
keyGen.initialize(keySize, new SecureRandom()); keyGen.initialize(keySize, new SecureRandom());
@ -429,11 +425,11 @@ public class Apg {
progress.setProgress("preparing master key...", 10, 100); progress.setProgress("preparing master key...", 10, 100);
KeyEditor keyEditor = (KeyEditor) keyEditors.getChildAt(0); KeyEditor keyEditor = (KeyEditor) keyEditors.getChildAt(0);
int usageId = keyEditor.getUsage().getId(); int usageId = keyEditor.getUsage();
boolean canSign = (usageId == KeyEditor.UsageChoice.SIGN_ONLY || boolean canSign = (usageId == Id.choice.usage.sign_only ||
usageId == KeyEditor.UsageChoice.SIGN_AND_ENCRYPT); usageId == Id.choice.usage.sign_and_encrypt);
boolean canEncrypt = (usageId == KeyEditor.UsageChoice.ENCRYPT_ONLY || boolean canEncrypt = (usageId == Id.choice.usage.encrypt_only ||
usageId == KeyEditor.UsageChoice.SIGN_AND_ENCRYPT); usageId == Id.choice.usage.sign_and_encrypt);
String mainUserId = userIds.get(0); String mainUserId = userIds.get(0);
@ -517,11 +513,11 @@ public class Apg {
unhashedPacketsGen = new PGPSignatureSubpacketGenerator(); unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
keyFlags = 0; keyFlags = 0;
usageId = keyEditor.getUsage().getId(); usageId = keyEditor.getUsage();
canSign = (usageId == KeyEditor.UsageChoice.SIGN_ONLY || canSign = (usageId == Id.choice.usage.sign_only ||
usageId == KeyEditor.UsageChoice.SIGN_AND_ENCRYPT); usageId == Id.choice.usage.sign_and_encrypt);
canEncrypt = (usageId == KeyEditor.UsageChoice.ENCRYPT_ONLY || canEncrypt = (usageId == Id.choice.usage.encrypt_only ||
usageId == KeyEditor.UsageChoice.SIGN_AND_ENCRYPT); usageId == Id.choice.usage.sign_and_encrypt);
if (canSign) { if (canSign) {
keyFlags |= KeyFlags.SIGN_DATA; keyFlags |= KeyFlags.SIGN_DATA;
} }

View File

@ -0,0 +1,319 @@
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* 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.thialfihar.android.apg;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Security;
import java.security.SignatureException;
import org.bouncycastle2.jce.provider.BouncyCastleProvider;
import org.bouncycastle2.openpgp.PGPException;
import org.openintents.intents.FileManager;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class DecryptFileActivity extends BaseActivity {
private EditText mFilename = null;
private ImageButton mBrowse = null;
private Button mDecryptButton = null;
private LinearLayout mSignatureLayout = null;
private ImageView mSignatureStatusImage = null;
private TextView mUserId = null;
private TextView mUserIdRest = null;
private String mInputFilename = null;
private String mOutputFilename = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.decrypt_file);
mFilename = (EditText) findViewById(R.id.filename);
mBrowse = (ImageButton) findViewById(R.id.btn_browse);
mBrowse.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openFile();
}
});
mDecryptButton = (Button) findViewById(R.id.btn_decrypt);
mDecryptButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
decryptClicked();
}
});
mSignatureLayout = (LinearLayout) findViewById(R.id.layout_signature);
mSignatureStatusImage = (ImageView) findViewById(R.id.ic_signature_status);
mUserId = (TextView) findViewById(R.id.main_user_id);
mUserIdRest = (TextView) findViewById(R.id.main_user_id_rest);
mSignatureLayout.setVisibility(View.INVISIBLE);
}
private void openFile() {
String filename = mFilename.getText().toString();
Intent intent = new Intent(FileManager.ACTION_PICK_FILE);
intent.setData(Uri.parse("file://" + filename));
intent.putExtra(FileManager.EXTRA_TITLE, "Select file to decrypt...");
intent.putExtra(FileManager.EXTRA_BUTTON_TEXT, "Open");
try {
startActivityForResult(intent, Id.request.filename);
} catch (ActivityNotFoundException e) {
// No compatible file manager was found.
Toast.makeText(this, R.string.no_filemanager_installed, Toast.LENGTH_SHORT).show();
}
}
private void decryptClicked() {
String error = null;
String currentFilename = mFilename.getText().toString();
if (mInputFilename == null || !mInputFilename.equals(currentFilename)) {
mInputFilename = mFilename.getText().toString();
File file = new File(mInputFilename);
String filename = file.getName();
if (filename.endsWith(".asc") || filename.endsWith(".gpg")) {
filename = filename.substring(0, filename.length() - 4);
}
mOutputFilename = Constants.path.app_dir + "/" + filename;
}
if (mInputFilename.equals("")) {
Toast.makeText(this, "Select a file first.", Toast.LENGTH_SHORT).show();
return;
}
try {
InputStream in = new FileInputStream(mInputFilename);
setSecretKeyId(Apg.getDecryptionKeyId(in));
showDialog(Id.dialog.pass_phrase);
} catch (FileNotFoundException e) {
error = "file not found: " + e.getLocalizedMessage();
} catch (IOException e) {
error = e.getLocalizedMessage();
} catch (Apg.GeneralException e) {
error = e.getLocalizedMessage();
}
if (error != null) {
Toast.makeText(this, "Error: " + error, Toast.LENGTH_SHORT).show();
}
}
@Override
public void passPhraseCallback(String passPhrase) {
super.passPhraseCallback(passPhrase);
askForOutputFilename();
}
private void askForOutputFilename() {
showDialog(Id.dialog.output_filename);
}
private void decryptStart() {
showDialog(Id.dialog.decrypting);
startThread();
}
@Override
public void run() {
String error = null;
Security.addProvider(new BouncyCastleProvider());
Bundle data = new Bundle();
Message msg = new Message();
try {
InputStream in = new FileInputStream(mInputFilename);
ByteArrayOutputStream out = new ByteArrayOutputStream();
data = Apg.decrypt(in, out, Apg.getPassPhrase(), this);
out.close();
OutputStream fileOut = new FileOutputStream(mOutputFilename);
fileOut.write(out.toByteArray());
fileOut.close();
} catch (PGPException e) {
error = e.getMessage();
} catch (IOException e) {
error = e.getMessage();
} catch (SignatureException e) {
error = e.getMessage();
e.printStackTrace();
} catch (Apg.GeneralException e) {
error = e.getMessage();
}
data.putInt("type", Id.message.done);
if (error != null) {
data.putString("error", error);
}
msg.setData(data);
sendMessage(msg);
}
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case Id.dialog.output_filename: {
return FileDialog.build(this, "Decrypt to file",
"Please specify which file to decrypt to.\n" +
"WARNING! File will be overwritten if it exists.",
mOutputFilename,
new FileDialog.OnClickListener() {
@Override
public void onOkClick(String filename) {
removeDialog(Id.dialog.output_filename);
mOutputFilename = filename;
decryptStart();
}
@Override
public void onCancelClick() {
removeDialog(Id.dialog.output_filename);
}
},
getString(R.string.filemanager_title_save),
getString(R.string.filemanager_btn_save),
Id.request.output_filename);
}
default: {
break;
}
}
return super.onCreateDialog(id);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case Id.request.filename: {
if (resultCode == RESULT_OK && data != null) {
String filename = data.getDataString();
if (filename != null) {
// Get rid of URI prefix:
if (filename.startsWith("file://")) {
filename = filename.substring(7);
}
// replace %20 and so on
filename = Uri.decode(filename);
mFilename.setText(filename);
}
}
return;
}
case Id.request.output_filename: {
if (resultCode == RESULT_OK && data != null) {
String filename = data.getDataString();
if (filename != null) {
// Get rid of URI prefix:
if (filename.startsWith("file://")) {
filename = filename.substring(7);
}
// replace %20 and so on
filename = Uri.decode(filename);
FileDialog.setFilename(filename);
}
}
return;
}
default: {
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public void doneCallback(Message msg) {
super.doneCallback(msg);
Bundle data = msg.getData();
removeDialog(Id.dialog.decrypting);
String error = data.getString("error");
if (error != null) {
Toast.makeText(DecryptFileActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(DecryptFileActivity.this,
"Successfully decrypted.",
Toast.LENGTH_SHORT).show();
}
mSignatureLayout.setVisibility(View.INVISIBLE);
if (data.getBoolean("signature")) {
String userId = data.getString("signatureUserId");
long signatureKeyId = data.getLong("signatureKeyId");
mUserIdRest.setText("id: " + Long.toHexString(signatureKeyId & 0xffffffffL));
if (userId == null) {
userId = getResources().getString(R.string.unknown_user_id);
}
String chunks[] = userId.split(" <", 2);
userId = chunks[0];
if (chunks.length > 1) {
mUserIdRest.setText("<" + chunks[1]);
}
mUserId.setText(userId);
if (data.getBoolean("signatureSuccess")) {
mSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
} else if (data.getBoolean("signatureUnknown")) {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
} else {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
}
mSignatureLayout.setVisibility(View.VISIBLE);
}
}
}

View File

@ -147,9 +147,8 @@ public class DecryptMessageActivity extends BaseActivity {
// else treat it as an encrypted message // else treat it as an encrypted message
mSignedOnly = false; mSignedOnly = false;
ByteArrayInputStream in =
new ByteArrayInputStream(messageData.getBytes());
try { try {
ByteArrayInputStream in = new ByteArrayInputStream(messageData.getBytes());
setSecretKeyId(Apg.getDecryptionKeyId(in)); setSecretKeyId(Apg.getDecryptionKeyId(in));
showDialog(Id.dialog.pass_phrase); showDialog(Id.dialog.pass_phrase);
} catch (IOException e) { } catch (IOException e) {
@ -198,15 +197,18 @@ public class DecryptMessageActivity extends BaseActivity {
String messageData = mMessage.getText().toString(); String messageData = mMessage.getText().toString();
try {
ByteArrayInputStream in = new ByteArrayInputStream(messageData.getBytes()); ByteArrayInputStream in = new ByteArrayInputStream(messageData.getBytes());
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
if (mSignedOnly) { if (mSignedOnly) {
data = Apg.verifyText(in, out, this); data = Apg.verifyText(in, out, this);
} else { } else {
data = Apg.decrypt(in, out, Apg.getPassPhrase(), this); data = Apg.decrypt(in, out, Apg.getPassPhrase(), this);
} }
out.close();
data.putString("decryptedMessage", Strings.fromUTF8ByteArray(out.toByteArray()));
} catch (PGPException e) { } catch (PGPException e) {
error = e.getMessage(); error = e.getMessage();
} catch (IOException e) { } catch (IOException e) {
@ -222,8 +224,6 @@ public class DecryptMessageActivity extends BaseActivity {
if (error != null) { if (error != null) {
data.putString("error", error); data.putString("error", error);
} else {
data.putString("decryptedMessage", Strings.fromUTF8ByteArray(out.toByteArray()));
} }
msg.setData(data); msg.setData(data);
@ -258,13 +258,9 @@ public class DecryptMessageActivity extends BaseActivity {
if (data.getBoolean("signature")) { if (data.getBoolean("signature")) {
String userId = data.getString("signatureUserId"); String userId = data.getString("signatureUserId");
mSignatureKeyId = data.getLong("signatureKeyId"); mSignatureKeyId = data.getLong("signatureKeyId");
mUserIdRest.setText("id: " + mUserIdRest.setText("id: " + Long.toHexString(mSignatureKeyId & 0xffffffffL));
Long.toHexString(mSignatureKeyId & 0xffffffffL));
if (userId == null) { if (userId == null) {
userId = userId = getResources().getString(R.string.unknown_user_id);
getResources()
.getString(
R.string.unknown_user_id);
} }
String chunks[] = userId.split(" <", 2); String chunks[] = userId.split(" <", 2);
userId = chunks[0]; userId = chunks[0];

View File

@ -16,6 +16,7 @@
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -267,7 +268,7 @@ public class EncryptFileActivity extends BaseActivity {
} }
InputStream in = new FileInputStream(mInputFilename); InputStream in = new FileInputStream(mInputFilename);
OutputStream out = new FileOutputStream(mOutputFilename); ByteArrayOutputStream out = new ByteArrayOutputStream();
if (mTabHost.getCurrentTabTag().equals(TAB_ASYMMETRIC)) { if (mTabHost.getCurrentTabTag().equals(TAB_ASYMMETRIC)) {
boolean encryptIt = mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0; boolean encryptIt = mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0;
@ -284,6 +285,9 @@ public class EncryptFileActivity extends BaseActivity {
} }
out.close(); out.close();
OutputStream fileOut = new FileOutputStream(mOutputFilename);
fileOut.write(out.toByteArray());
fileOut.close();
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
error = "file not found: " + e.getMessage(); error = "file not found: " + e.getMessage();
} }

View File

@ -80,5 +80,18 @@ public final class Id {
public static final int public_key = 0x21070001; public static final int public_key = 0x21070001;
public static final int secret_key = 0x21070002; public static final int secret_key = 0x21070002;
} }
}
public static final class choice {
public static final class algorithm {
public static final int dsa = 0x21070001;
public static final int elgamal = 0x21070002;
public static final int rsa = 0x21070003;
}
public static final class usage {
public static final int sign_only = 0x21070001;
public static final int encrypt_only = 0x21070002;
public static final int sign_and_encrypt = 0x21070003;
}
}
}

View File

@ -360,7 +360,7 @@ public class MainActivity extends BaseActivity {
} }
public void startDecryptFileActivity() { public void startDecryptFileActivity() {
//startActivity(new Intent(this, DecryptFileActivity.class)); startActivity(new Intent(this, DecryptFileActivity.class));
} }
public void startMailListActivity(String account) { public void startMailListActivity(String account) {

View File

@ -24,7 +24,9 @@ import java.util.Vector;
import org.bouncycastle2.openpgp.PGPSecretKey; import org.bouncycastle2.openpgp.PGPSecretKey;
import org.thialfihar.android.apg.Apg; import org.thialfihar.android.apg.Apg;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.R.id;
import org.thialfihar.android.apg.utils.Choice; import org.thialfihar.android.apg.utils.Choice;
import android.app.DatePickerDialog; import android.app.DatePickerDialog;
@ -65,26 +67,6 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
} }
}; };
public static class AlgorithmChoice extends Choice {
public static final int DSA = 1;
public static final int ELGAMAL = 2;
public static final int RSA = 3;
public AlgorithmChoice(int id, String name) {
super(id, name);
}
}
public static class UsageChoice extends Choice {
public static final int SIGN_ONLY = 1;
public static final int ENCRYPT_ONLY = 2;
public static final int SIGN_AND_ENCRYPT = 3;
public UsageChoice(int id, String name) {
super(id, name);
}
}
public KeyEditor(Context context) { public KeyEditor(Context context) {
super(context); super(context);
} }
@ -103,18 +85,17 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
mCreationDate = (TextView) findViewById(R.id.creation); mCreationDate = (TextView) findViewById(R.id.creation);
mExpiryDateButton = (Button) findViewById(R.id.expiry); mExpiryDateButton = (Button) findViewById(R.id.expiry);
mUsage = (Spinner) findViewById(R.id.usage); mUsage = (Spinner) findViewById(R.id.usage);
KeyEditor.UsageChoice choices[] = { Choice choices[] = {
new KeyEditor.UsageChoice(KeyEditor.UsageChoice.SIGN_ONLY, new Choice(Id.choice.usage.sign_only,
getResources().getString(R.string.sign_only)), getResources().getString(R.string.sign_only)),
new KeyEditor.UsageChoice(KeyEditor.UsageChoice.ENCRYPT_ONLY, new Choice(Id.choice.usage.encrypt_only,
getResources().getString(R.string.encrypt_only)), getResources().getString(R.string.encrypt_only)),
new KeyEditor.UsageChoice(KeyEditor.UsageChoice.SIGN_AND_ENCRYPT, new Choice(Id.choice.usage.sign_and_encrypt,
getResources().getString(R.string.sign_and_encrypt)), getResources().getString(R.string.sign_and_encrypt)),
}; };
ArrayAdapter<KeyEditor.UsageChoice> adapter = ArrayAdapter<Choice> adapter =
new ArrayAdapter<KeyEditor.UsageChoice>(getContext(), new ArrayAdapter<Choice>(getContext(),
android.R.layout.simple_spinner_item, android.R.layout.simple_spinner_item, choices);
choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mUsage.setAdapter(adapter); mUsage.setAdapter(adapter);
@ -169,18 +150,18 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
} }
mKeyId.setText(keyId1Str + " " + keyId2Str); mKeyId.setText(keyId1Str + " " + keyId2Str);
Vector<KeyEditor.UsageChoice> choices = new Vector<KeyEditor.UsageChoice>(); Vector<Choice> choices = new Vector<Choice>();
choices.add(new KeyEditor.UsageChoice(KeyEditor.UsageChoice.SIGN_ONLY, choices.add(new Choice(Id.choice.usage.sign_only,
getResources().getString(R.string.sign_only))); getResources().getString(R.string.sign_only)));
if (!mIsMasterKey) { if (!mIsMasterKey) {
choices.add(new KeyEditor.UsageChoice(KeyEditor.UsageChoice.ENCRYPT_ONLY, choices.add(new Choice(Id.choice.usage.encrypt_only,
getResources().getString(R.string.encrypt_only))); getResources().getString(R.string.encrypt_only)));
} }
choices.add(new KeyEditor.UsageChoice(KeyEditor.UsageChoice.SIGN_AND_ENCRYPT, choices.add(new Choice(Id.choice.usage.sign_and_encrypt,
getResources().getString(R.string.sign_and_encrypt))); getResources().getString(R.string.sign_and_encrypt)));
ArrayAdapter<KeyEditor.UsageChoice> adapter = ArrayAdapter<Choice> adapter =
new ArrayAdapter<KeyEditor.UsageChoice>(getContext(), new ArrayAdapter<Choice>(getContext(),
android.R.layout.simple_spinner_item, android.R.layout.simple_spinner_item,
choices); choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@ -242,7 +223,7 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
return mExpiryDate; return mExpiryDate;
} }
public UsageChoice getUsage() { public int getUsage() {
return (UsageChoice) mUsage.getSelectedItem(); return ((Choice) mUsage.getSelectedItem()).getId();
} }
} }

View File

@ -25,8 +25,10 @@ import java.util.Vector;
import org.bouncycastle2.openpgp.PGPException; import org.bouncycastle2.openpgp.PGPException;
import org.bouncycastle2.openpgp.PGPSecretKey; import org.bouncycastle2.openpgp.PGPSecretKey;
import org.thialfihar.android.apg.Apg; import org.thialfihar.android.apg.Apg;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.ui.widget.Editor.EditorListener; import org.thialfihar.android.apg.ui.widget.Editor.EditorListener;
import org.thialfihar.android.apg.utils.Choice;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
@ -57,7 +59,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
private TextView mTitle; private TextView mTitle;
private int mType = 0; private int mType = 0;
private KeyEditor.AlgorithmChoice mNewKeyAlgorithmChoice; private Choice mNewKeyAlgorithmChoice;
private int mNewKeySize; private int mNewKeySize;
volatile private PGPSecretKey mNewKey; volatile private PGPSecretKey mNewKey;
@ -181,24 +183,23 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
dialog.setTitle("Create Key"); dialog.setTitle("Create Key");
final Spinner algorithm = (Spinner) view.findViewById(R.id.algorithm); final Spinner algorithm = (Spinner) view.findViewById(R.id.algorithm);
KeyEditor.AlgorithmChoice choices[] = { Choice choices[] = {
new KeyEditor.AlgorithmChoice(KeyEditor.AlgorithmChoice.DSA, new Choice(Id.choice.algorithm.dsa,
getResources().getString(R.string.dsa)), getResources().getString(R.string.dsa)),
/*new KeyEditor.AlgorithmChoice(KeyEditor.AlgorithmChoice.ELGAMAL, /*new Choice(Id.choice.algorithm.elgamal,
getResources().getString(R.string.elgamal)),*/ getResources().getString(R.string.elgamal)),*/
new KeyEditor.AlgorithmChoice(KeyEditor.AlgorithmChoice.RSA, new Choice(Id.choice.algorithm.rsa,
getResources().getString(R.string.rsa)), getResources().getString(R.string.rsa)),
}; };
ArrayAdapter<KeyEditor.AlgorithmChoice> adapter = ArrayAdapter<Choice> adapter =
new ArrayAdapter<KeyEditor.AlgorithmChoice>( new ArrayAdapter<Choice>(getContext(),
getContext(),
android.R.layout.simple_spinner_item, android.R.layout.simple_spinner_item,
choices); choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
algorithm.setAdapter(adapter); algorithm.setAdapter(adapter);
// make RSA the default // make RSA the default
for (int i = 0; i < choices.length; ++i) { for (int i = 0; i < choices.length; ++i) {
if (choices[i].getId() == KeyEditor.AlgorithmChoice.RSA) { if (choices[i].getId() == Id.choice.algorithm.rsa) {
algorithm.setSelection(i); algorithm.setSelection(i);
break; break;
} }
@ -217,8 +218,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
mNewKeySize = 0; mNewKeySize = 0;
} }
mNewKeyAlgorithmChoice = mNewKeyAlgorithmChoice = (Choice) algorithm.getSelectedItem();
(KeyEditor.AlgorithmChoice) algorithm.getSelectedItem();
createKey(); createKey();
} }
}); });
@ -294,7 +294,8 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
public void run() { public void run() {
String error = null; String error = null;
try { try {
mNewKey = Apg.createKey(mNewKeyAlgorithmChoice, mNewKeySize, Apg.getPassPhrase()); mNewKey = Apg.createKey(mNewKeyAlgorithmChoice.getId(),
mNewKeySize, Apg.getPassPhrase());
} catch (NoSuchProviderException e) { } catch (NoSuchProviderException e) {
error = e.getMessage(); error = e.getMessage();
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {