mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-24 01:32:16 -05:00
Redefine many internals of ApgService
This helps to add new function calls easily. Some of the new enums could be exported to other files to be included by other projects later on. Next step is asymmetric encryption.
This commit is contained in:
parent
fc05dfd8b7
commit
45e4897dc7
@ -7,7 +7,9 @@ import java.io.OutputStream;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -23,23 +25,74 @@ public class ApgService extends Service {
|
|||||||
return mBinder;
|
return mBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** error status */
|
||||||
private enum error {
|
private enum error {
|
||||||
ARGUMENTS_MISSING,
|
ARGUMENTS_MISSING,
|
||||||
APG_FAILURE
|
APG_FAILURE
|
||||||
}
|
}
|
||||||
|
|
||||||
/** a map from ApgService parameters to function calls to get the default */
|
/** all arguments that can be passed by calling application */
|
||||||
static final HashMap<String, String> FUNCTIONS_DEFAULTS = new HashMap<String, String>();
|
private enum arg {
|
||||||
|
MSG, // message to encrypt or to decrypt
|
||||||
|
SYM_KEY, // key for symmetric en/decryption
|
||||||
|
PUBLIC_KEYS, // public keys for encryption
|
||||||
|
ENCRYPTION_ALGO, // encryption algorithm
|
||||||
|
HASH_ALGO, // hash algorithm
|
||||||
|
ARMORED, // whether to armor output
|
||||||
|
FORCE_V3_SIG, // whether to force v3 signature
|
||||||
|
COMPRESSION
|
||||||
|
// what compression to use for encrypted output
|
||||||
|
}
|
||||||
|
|
||||||
|
/** all things that might be returned */
|
||||||
|
private enum ret {
|
||||||
|
ERRORS,
|
||||||
|
WARNINGS,
|
||||||
|
ERROR,
|
||||||
|
RESULT
|
||||||
|
}
|
||||||
|
|
||||||
|
/** required arguments for each AIDL function */
|
||||||
|
private static final HashMap<String, Set<arg>> FUNCTIONS_REQUIRED_ARGS = new HashMap<String, Set<arg>>();
|
||||||
static {
|
static {
|
||||||
FUNCTIONS_DEFAULTS.put("ENCRYPTION_ALGO", "getDefaultEncryptionAlgorithm");
|
HashSet<arg> args = new HashSet<arg>();
|
||||||
FUNCTIONS_DEFAULTS.put("HASH_ALGO", "getDefaultHashAlgorithm");
|
args.add(arg.SYM_KEY);
|
||||||
FUNCTIONS_DEFAULTS.put("ARMORED", "getDefaultAsciiArmour");
|
args.add(arg.MSG);
|
||||||
FUNCTIONS_DEFAULTS.put("FORCE_V3_SIG", "getForceV3Signatures");
|
FUNCTIONS_REQUIRED_ARGS.put("encrypt_with_passphrase", args);
|
||||||
FUNCTIONS_DEFAULTS.put("COMPRESSION", "getDefaultMessageCompression");
|
FUNCTIONS_REQUIRED_ARGS.put("decrypt_with_passphrase", args);
|
||||||
|
|
||||||
|
args = new HashSet<arg>();
|
||||||
|
args.add(arg.PUBLIC_KEYS);
|
||||||
|
args.add(arg.MSG);
|
||||||
|
FUNCTIONS_REQUIRED_ARGS.put("encrypt_with_public_key", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** optional arguments for each AIDL function */
|
||||||
|
private static final HashMap<String, Set<arg>> FUNCTIONS_OPTIONAL_ARGS = new HashMap<String, Set<arg>>();
|
||||||
|
static {
|
||||||
|
HashSet<arg> args = new HashSet<arg>();
|
||||||
|
args.add(arg.ENCRYPTION_ALGO);
|
||||||
|
args.add(arg.HASH_ALGO);
|
||||||
|
args.add(arg.ARMORED);
|
||||||
|
args.add(arg.FORCE_V3_SIG);
|
||||||
|
args.add(arg.COMPRESSION);
|
||||||
|
FUNCTIONS_OPTIONAL_ARGS.put("encrypt_with_passphrase", args);
|
||||||
|
FUNCTIONS_OPTIONAL_ARGS.put("encrypt_with_public_key", args);
|
||||||
|
FUNCTIONS_OPTIONAL_ARGS.put("decrypt_with_passphrase", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** a map from ApgService parameters to function calls to get the default */
|
||||||
|
private static final HashMap<arg, String> FUNCTIONS_DEFAULTS = new HashMap<arg, String>();
|
||||||
|
static {
|
||||||
|
FUNCTIONS_DEFAULTS.put(arg.ENCRYPTION_ALGO, "getDefaultEncryptionAlgorithm");
|
||||||
|
FUNCTIONS_DEFAULTS.put(arg.HASH_ALGO, "getDefaultHashAlgorithm");
|
||||||
|
FUNCTIONS_DEFAULTS.put(arg.ARMORED, "getDefaultAsciiArmour");
|
||||||
|
FUNCTIONS_DEFAULTS.put(arg.FORCE_V3_SIG, "getForceV3Signatures");
|
||||||
|
FUNCTIONS_DEFAULTS.put(arg.COMPRESSION, "getDefaultMessageCompression");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** a map the default functions to their return types */
|
/** a map the default functions to their return types */
|
||||||
static final HashMap<String, Class> FUNCTIONS_DEFAULTS_TYPES = new HashMap<String, Class>();
|
private static final HashMap<String, Class<?>> FUNCTIONS_DEFAULTS_TYPES = new HashMap<String, Class<?>>();
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
FUNCTIONS_DEFAULTS_TYPES.put("getDefaultEncryptionAlgorithm", Preferences.class.getMethod("getDefaultEncryptionAlgorithm").getReturnType());
|
FUNCTIONS_DEFAULTS_TYPES.put("getDefaultEncryptionAlgorithm", Preferences.class.getMethod("getDefaultEncryptionAlgorithm").getReturnType());
|
||||||
@ -53,7 +106,7 @@ public class ApgService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** a map the default function names to their method */
|
/** a map the default function names to their method */
|
||||||
static final HashMap<String, Method> FUNCTIONS_DEFAULTS_METHODS = new HashMap<String, Method>();
|
private static final HashMap<String, Method> FUNCTIONS_DEFAULTS_METHODS = new HashMap<String, Method>();
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultEncryptionAlgorithm", Preferences.class.getMethod("getDefaultEncryptionAlgorithm"));
|
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultEncryptionAlgorithm", Preferences.class.getMethod("getDefaultEncryptionAlgorithm"));
|
||||||
@ -73,17 +126,17 @@ public class ApgService extends Service {
|
|||||||
* the bundle to add default parameters to if missing
|
* the bundle to add default parameters to if missing
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private void add_defaults(Bundle args) {
|
private void add_default_arguments(Bundle args) {
|
||||||
Preferences _mPreferences = Preferences.getPreferences(getBaseContext(), true);
|
Preferences _mPreferences = Preferences.getPreferences(getBaseContext(), true);
|
||||||
|
|
||||||
Iterator<String> _iter = FUNCTIONS_DEFAULTS.keySet().iterator();
|
Iterator<arg> _iter = FUNCTIONS_DEFAULTS.keySet().iterator();
|
||||||
while (_iter.hasNext()) {
|
while (_iter.hasNext()) {
|
||||||
String _current_key = _iter.next();
|
arg _current_arg = _iter.next();
|
||||||
|
String _current_key = _current_arg.name();
|
||||||
if (!args.containsKey(_current_key)) {
|
if (!args.containsKey(_current_key)) {
|
||||||
String _current_function_name = FUNCTIONS_DEFAULTS.get(_current_key);
|
String _current_function_name = FUNCTIONS_DEFAULTS.get(_current_arg);
|
||||||
try {
|
try {
|
||||||
@SuppressWarnings("unchecked")
|
Class<?> _ret_type = FUNCTIONS_DEFAULTS_TYPES.get(_current_function_name);
|
||||||
Class _ret_type = FUNCTIONS_DEFAULTS_TYPES.get(_current_function_name);
|
|
||||||
if (_ret_type == String.class) {
|
if (_ret_type == String.class) {
|
||||||
args.putString(_current_key, (String) FUNCTIONS_DEFAULTS_METHODS.get(_current_function_name).invoke(_mPreferences));
|
args.putString(_current_key, (String) FUNCTIONS_DEFAULTS_METHODS.get(_current_function_name).invoke(_mPreferences));
|
||||||
} else if (_ret_type == boolean.class) {
|
} else if (_ret_type == boolean.class) {
|
||||||
@ -94,74 +147,98 @@ public class ApgService extends Service {
|
|||||||
Log.e(TAG, "Unknown return type " + _ret_type.toString() + " for default option");
|
Log.e(TAG, "Unknown return type " + _ret_type.toString() + " for default option");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Exception in add_defaults " + e.getMessage());
|
Log.e(TAG, "Exception in add_default_arguments " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* updates a Bundle with default return values
|
||||||
|
*
|
||||||
|
* @param pReturn
|
||||||
|
* the Bundle to update
|
||||||
|
*/
|
||||||
|
private void add_default_returns(Bundle pReturn) {
|
||||||
|
ArrayList<String> errors = new ArrayList<String>();
|
||||||
|
ArrayList<String> warnings = new ArrayList<String>();
|
||||||
|
|
||||||
|
pReturn.putStringArrayList(ret.ERRORS.name(), errors);
|
||||||
|
pReturn.putStringArrayList(ret.WARNINGS.name(), warnings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks for required arguments and adds them to the error if missing
|
||||||
|
*
|
||||||
|
* @param function
|
||||||
|
* the functions required arguments to check for
|
||||||
|
* @param pArgs
|
||||||
|
* the Bundle of arguments to check
|
||||||
|
* @param pReturn
|
||||||
|
* the bundle to write errors to
|
||||||
|
*/
|
||||||
|
private void check_required_args(String function, Bundle pArgs, Bundle pReturn) {
|
||||||
|
Iterator<arg> _iter = FUNCTIONS_REQUIRED_ARGS.get(function).iterator();
|
||||||
|
while (_iter.hasNext()) {
|
||||||
|
String _cur_arg = _iter.next().name();
|
||||||
|
if (!pArgs.containsKey(_cur_arg)) {
|
||||||
|
pReturn.getStringArrayList(ret.ERRORS.name()).add("Argument missing: " + _cur_arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks for unknown arguments and add them to warning if found
|
||||||
|
*
|
||||||
|
* @param function
|
||||||
|
* the functions name to check against
|
||||||
|
* @param pArgs
|
||||||
|
* the Bundle of arguments to check
|
||||||
|
* @param pReturn
|
||||||
|
* the bundle to write warnings to
|
||||||
|
*/
|
||||||
|
private void check_unknown_args(String function, Bundle pArgs, Bundle pReturn) {
|
||||||
|
HashSet<arg> all_args = new HashSet<arg>(FUNCTIONS_REQUIRED_ARGS.get(function));
|
||||||
|
all_args.addAll(FUNCTIONS_OPTIONAL_ARGS.get(function));
|
||||||
|
|
||||||
|
Iterator<String> _iter = pArgs.keySet().iterator();
|
||||||
|
while (_iter.hasNext()) {
|
||||||
|
String _cur_key = _iter.next();
|
||||||
|
try {
|
||||||
|
arg.valueOf(_cur_key);
|
||||||
|
} catch (Exception e) {
|
||||||
|
pReturn.getStringArrayList(ret.WARNINGS.name()).add("Unknown argument: " + _cur_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final IApgService.Stub mBinder = new IApgService.Stub() {
|
private final IApgService.Stub mBinder = new IApgService.Stub() {
|
||||||
|
|
||||||
public boolean encrypt_with_passphrase(Bundle pArgs, Bundle pReturn) {
|
public boolean encrypt_with_passphrase(Bundle pArgs, Bundle pReturn) {
|
||||||
|
/* add default return values for all functions */
|
||||||
|
add_default_returns(pReturn);
|
||||||
|
|
||||||
ArrayList<String> errors = new ArrayList<String>();
|
/* add default arguments if missing */
|
||||||
ArrayList<String> warnings = new ArrayList<String>();
|
add_default_arguments(pArgs);
|
||||||
|
Log.d(TAG, "add_default_arguments");
|
||||||
|
|
||||||
pReturn.putStringArrayList("ERRORS", errors);
|
/* check for required arguments */
|
||||||
pReturn.putStringArrayList("WARNINGS", warnings);
|
check_required_args("encrypt_with_passphrase", pArgs, pReturn);
|
||||||
|
Log.d(TAG, "check_required_args");
|
||||||
|
|
||||||
Bundle _my_args = new Bundle(pArgs);
|
/* check for unknown arguments and add to warning if found */
|
||||||
|
check_unknown_args("encrypt_with_passphrase", pArgs, pReturn);
|
||||||
/* add default values if missing */
|
Log.d(TAG, "check_unknown_args");
|
||||||
add_defaults(_my_args);
|
|
||||||
|
|
||||||
/* required args */
|
|
||||||
String msg = _my_args.getString("MSG");
|
|
||||||
_my_args.remove("MSG");
|
|
||||||
|
|
||||||
String passphrase = _my_args.getString("SYM_KEY");
|
|
||||||
_my_args.remove("SYM_KEY");
|
|
||||||
|
|
||||||
/* optional args */
|
|
||||||
Boolean armored = _my_args.getBoolean("ARMORED");
|
|
||||||
_my_args.remove("ARMORED");
|
|
||||||
|
|
||||||
int encryption_algorithm = _my_args.getInt("ENCRYPTION_ALGO");
|
|
||||||
_my_args.remove("ENCRYPTION_ALGO");
|
|
||||||
|
|
||||||
int hash_algorithm = _my_args.getInt("HASH_ALGO");
|
|
||||||
_my_args.remove("HASH_ALGO");
|
|
||||||
|
|
||||||
int compression = _my_args.getInt("COMPRESSION");
|
|
||||||
_my_args.remove("COMPRESSION");
|
|
||||||
|
|
||||||
Boolean force_v3_signatures = _my_args.getBoolean("FORCE_V3_SIG");
|
|
||||||
_my_args.remove("FORCE_V3_SIG");
|
|
||||||
|
|
||||||
/* check required args */
|
|
||||||
if (msg == null) {
|
|
||||||
errors.add("Message to encrypt (MSG) missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (passphrase == null) {
|
|
||||||
errors.add("Symmetric key (SYM_KEY) missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check for unknown args and add to warning */
|
|
||||||
if (!_my_args.isEmpty()) {
|
|
||||||
Iterator<String> _iter = _my_args.keySet().iterator();
|
|
||||||
while (_iter.hasNext()) {
|
|
||||||
warnings.add("Unknown key: " + _iter.next());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return if errors happened */
|
/* return if errors happened */
|
||||||
if (errors.size() != 0) {
|
if (pReturn.getStringArrayList(ret.ERRORS.name()).size() != 0) {
|
||||||
pReturn.putInt("ERROR", error.ARGUMENTS_MISSING.ordinal());
|
pReturn.putInt(ret.ERROR.name(), error.ARGUMENTS_MISSING.ordinal());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Log.d(TAG, "error return");
|
||||||
|
|
||||||
InputStream _inStream = new ByteArrayInputStream(msg.getBytes());
|
InputStream _inStream = new ByteArrayInputStream(pArgs.getString(arg.MSG.name()).getBytes());
|
||||||
InputData _in = new InputData(_inStream, 0); // XXX Size second
|
InputData _in = new InputData(_inStream, 0); // XXX Size second
|
||||||
// param?
|
// param?
|
||||||
OutputStream _out = new ByteArrayOutputStream();
|
OutputStream _out = new ByteArrayOutputStream();
|
||||||
@ -171,82 +248,71 @@ public class ApgService extends Service {
|
|||||||
Apg.encrypt(getApplicationContext(), // context
|
Apg.encrypt(getApplicationContext(), // context
|
||||||
_in, // input stream
|
_in, // input stream
|
||||||
_out, // output stream
|
_out, // output stream
|
||||||
armored, // armored
|
pArgs.getBoolean(arg.ARMORED.name()), // armored
|
||||||
new long[0], // encryption keys
|
new long[0], // encryption keys
|
||||||
0, // signature key
|
0, // signature key
|
||||||
null, // signature passphrase
|
null, // signature passphrase
|
||||||
null, // progress
|
null, // progress
|
||||||
encryption_algorithm, // encryption
|
pArgs.getInt(arg.ENCRYPTION_ALGO.name()), // encryption
|
||||||
hash_algorithm, // hash
|
pArgs.getInt(arg.HASH_ALGO.name()), // hash
|
||||||
compression, // compression
|
pArgs.getInt(arg.COMPRESSION.name()), // compression
|
||||||
force_v3_signatures, // mPreferences.getForceV3Signatures(),
|
pArgs.getBoolean(arg.FORCE_V3_SIG.name()), // mPreferences.getForceV3Signatures(),
|
||||||
passphrase // passPhrase
|
pArgs.getString(arg.SYM_KEY.name()) // passPhrase
|
||||||
);
|
);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.d(TAG, "Exception in encrypt");
|
Log.d(TAG, "Exception in encrypt");
|
||||||
errors.add("Internal failure in APG when encrypting: " + e.getMessage());
|
pReturn.getStringArrayList(ret.ERRORS.name()).add("Internal failure in APG when encrypting: " + e.getMessage());
|
||||||
|
|
||||||
pReturn.putInt("ERROR", error.APG_FAILURE.ordinal());
|
pReturn.putInt(ret.ERROR.name(), error.APG_FAILURE.ordinal());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(TAG, "Encrypted");
|
Log.d(TAG, "Encrypted");
|
||||||
pReturn.putString("RESULT", _out.toString());
|
pReturn.putString(ret.RESULT.name(), _out.toString());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean decrypt_with_passphrase(Bundle pArgs, Bundle pReturn) {
|
public boolean decrypt_with_passphrase(Bundle pArgs, Bundle pReturn) {
|
||||||
ArrayList<String> errors = new ArrayList<String>();
|
/* add default return values for all functions */
|
||||||
ArrayList<String> warnings = new ArrayList<String>();
|
add_default_returns(pReturn);
|
||||||
|
|
||||||
pReturn.putStringArrayList("ERRORS", errors);
|
/* add default arguments if missing */
|
||||||
pReturn.putStringArrayList("WARNINGS", warnings);
|
add_default_arguments(pArgs);
|
||||||
|
Log.d(TAG, "add_default_arguments");
|
||||||
|
|
||||||
String encrypted_msg = pArgs.getString("MSG");
|
|
||||||
pArgs.remove("MSG");
|
|
||||||
|
|
||||||
String passphrase = pArgs.getString("SYM_KEY");
|
/* check required args */
|
||||||
pArgs.remove("SYM_KEY");
|
check_required_args("decrypt_with_passphrase", pArgs, pReturn);
|
||||||
|
Log.d(TAG, "check_required_args");
|
||||||
|
|
||||||
if (encrypted_msg == null) {
|
|
||||||
errors.add("Message to decrypt (MSG) missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (passphrase == null) {
|
/* check for unknown args and add to warning */
|
||||||
errors.add("Symmetric key (SYM_KEY) missing");
|
check_unknown_args("decrypt_with_passphrase", pArgs, pReturn);
|
||||||
}
|
Log.d(TAG, "check_unknown_args");
|
||||||
|
|
||||||
if (!pArgs.isEmpty()) {
|
|
||||||
Iterator<String> iter = pArgs.keySet().iterator();
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
warnings.add("Unknown key: " + iter.next());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errors.size() != 0) {
|
/* return if errors happened */
|
||||||
pReturn.putStringArrayList("ERROR", errors);
|
if (pReturn.getStringArrayList(ret.ERRORS.name()).size() != 0) {
|
||||||
pReturn.putInt("ERROR", error.ARGUMENTS_MISSING.ordinal());
|
pReturn.putInt(ret.ERROR.name(), error.ARGUMENTS_MISSING.ordinal());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStream inStream = new ByteArrayInputStream(encrypted_msg.getBytes());
|
InputStream inStream = new ByteArrayInputStream(pArgs.getString(arg.MSG.name()).getBytes());
|
||||||
InputData in = new InputData(inStream, 0); // XXX what size in
|
InputData in = new InputData(inStream, 0); // XXX what size in
|
||||||
// second parameter?
|
// second parameter?
|
||||||
OutputStream out = new ByteArrayOutputStream();
|
OutputStream out = new ByteArrayOutputStream();
|
||||||
try {
|
try {
|
||||||
Apg.decrypt(getApplicationContext(), in, out, passphrase, null, // progress
|
Apg.decrypt(getApplicationContext(), in, out, pArgs.getString(arg.SYM_KEY.name()), null, // progress
|
||||||
true // symmetric
|
true // symmetric
|
||||||
);
|
);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.d(TAG, "Exception in decrypt");
|
Log.d(TAG, "Exception in decrypt");
|
||||||
errors.add("Internal failure in APG when decrypting: " + e.getMessage());
|
pReturn.getStringArrayList(ret.ERRORS.name()).add("Internal failure in APG when decrypting: " + e.getMessage());
|
||||||
|
|
||||||
pReturn.putInt("ERROR", error.APG_FAILURE.ordinal());
|
pReturn.putInt(ret.ERROR.name(), error.APG_FAILURE.ordinal());
|
||||||
pReturn.putStringArrayList("ERROR", errors);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pReturn.putString("RESULT", out.toString());
|
pReturn.putString(ret.RESULT.name(), out.toString());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user