PgpEngine.java

  1package eu.siacs.conversations.crypto;
  2
  3import java.io.ByteArrayInputStream;
  4import java.io.ByteArrayOutputStream;
  5import java.io.InputStream;
  6
  7import org.openintents.openpgp.OpenPgpError;
  8import org.openintents.openpgp.OpenPgpSignatureResult;
  9import org.openintents.openpgp.util.OpenPgpApi;
 10
 11import android.app.PendingIntent;
 12import android.content.Intent;
 13
 14public class PgpEngine {
 15	private OpenPgpApi api;
 16
 17	public PgpEngine(OpenPgpApi api) {
 18		this.api = api;
 19	}
 20
 21	public String decrypt(String message) throws UserInputRequiredException,
 22			OpenPgpException {
 23		Intent params = new Intent();
 24		params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
 25		InputStream is = new ByteArrayInputStream(message.getBytes());
 26		ByteArrayOutputStream os = new ByteArrayOutputStream();
 27		Intent result = api.executeApi(params, is, os);
 28		switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
 29		case OpenPgpApi.RESULT_CODE_SUCCESS:
 30			return os.toString();
 31		case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
 32			throw new UserInputRequiredException((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
 33		case OpenPgpApi.RESULT_CODE_ERROR:
 34			throw new OpenPgpException(
 35					(OpenPgpError) result.getParcelableExtra(OpenPgpApi.RESULT_ERRORS));
 36		default:
 37			return null;
 38		}
 39	}
 40
 41	public String encrypt(long keyId, String message) {
 42		Long[] keys = {keyId};
 43		Intent params = new Intent();
 44		params.setAction(OpenPgpApi.ACTION_ENCRYPT);
 45		params.putExtra(OpenPgpApi.EXTRA_KEY_IDS,keys);
 46		params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
 47		
 48		InputStream is = new ByteArrayInputStream(message.getBytes());
 49		ByteArrayOutputStream os = new ByteArrayOutputStream();
 50		Intent result = api.executeApi(params, is, os);
 51		StringBuilder encryptedMessageBody = new StringBuilder();
 52		String[] lines = os.toString().split("\n");
 53		for (int i = 3; i < lines.length - 1; ++i) {
 54			encryptedMessageBody.append(lines[i].trim());
 55		}
 56		return encryptedMessageBody.toString();
 57	}
 58
 59	public long fetchKeyId(String status, String signature)
 60			throws OpenPgpException {
 61		StringBuilder pgpSig = new StringBuilder();
 62		pgpSig.append("-----BEGIN PGP SIGNED MESSAGE-----");
 63		pgpSig.append('\n');
 64		pgpSig.append("Hash: SHA1");
 65		pgpSig.append('\n');
 66		pgpSig.append('\n');
 67		pgpSig.append(status);
 68		pgpSig.append('\n');
 69		pgpSig.append("-----BEGIN PGP SIGNATURE-----");
 70		pgpSig.append('\n');
 71		pgpSig.append('\n');
 72		pgpSig.append(signature.replace("\n", "").trim());
 73		pgpSig.append('\n');
 74		pgpSig.append("-----END PGP SIGNATURE-----");
 75		Intent params = new Intent();
 76		params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
 77		params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
 78		InputStream is = new ByteArrayInputStream(pgpSig.toString().getBytes());
 79		ByteArrayOutputStream os = new ByteArrayOutputStream();
 80		Intent result = api.executeApi(params, is, os);
 81		switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
 82		case OpenPgpApi.RESULT_CODE_SUCCESS:
 83			OpenPgpSignatureResult sigResult
 84            = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE);
 85			return sigResult.getKeyId();
 86		case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
 87			break;
 88		case OpenPgpApi.RESULT_CODE_ERROR:
 89			throw new OpenPgpException(
 90					(OpenPgpError) result.getParcelableExtra(OpenPgpApi.RESULT_ERRORS));
 91		}
 92		return 0;
 93	}
 94
 95	public String generateSignature(String status)
 96			throws UserInputRequiredException {
 97		Intent params = new Intent();
 98		params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
 99		params.setAction(OpenPgpApi.ACTION_SIGN);
100		InputStream is = new ByteArrayInputStream(status.getBytes());
101		ByteArrayOutputStream os = new ByteArrayOutputStream();
102		Intent result = api.executeApi(params, is, os);
103		StringBuilder signatureBuilder = new StringBuilder();
104		switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
105		case OpenPgpApi.RESULT_CODE_SUCCESS:
106			String[] lines = os.toString().split("\n");
107			for (int i = 7; i < lines.length - 1; ++i) {
108				signatureBuilder.append(lines[i].trim());
109			}
110			break;
111		case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
112			throw new UserInputRequiredException((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
113		case OpenPgpApi.RESULT_CODE_ERROR:
114			break;
115		}
116		return signatureBuilder.toString();
117	}
118
119	public class UserInputRequiredException extends Exception {
120		private static final long serialVersionUID = -6913480043269132016L;
121		private PendingIntent pi;
122
123		public UserInputRequiredException(PendingIntent pi) {
124			this.pi = pi;
125		}
126
127		public PendingIntent getPendingIntent() {
128			return this.pi;
129		}
130	}
131
132	public class OpenPgpException extends Exception {
133		private static final long serialVersionUID = -7324789703473056077L;
134		private OpenPgpError error;
135
136		public OpenPgpException(OpenPgpError openPgpError) {
137			this.error = openPgpError;
138		}
139
140		public OpenPgpError getOpenPgpError() {
141			return this.error;
142		}
143	}
144}