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_ERROR));
 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		if ((signature==null)||(api==null)) {
 62			return 0;
 63		}
 64		if (status==null) {
 65			status="";
 66		}
 67		StringBuilder pgpSig = new StringBuilder();
 68		pgpSig.append("-----BEGIN PGP SIGNED MESSAGE-----");
 69		pgpSig.append('\n');
 70		pgpSig.append('\n');
 71		pgpSig.append(status);
 72		pgpSig.append('\n');
 73		pgpSig.append("-----BEGIN PGP SIGNATURE-----");
 74		pgpSig.append('\n');
 75		pgpSig.append('\n');
 76		pgpSig.append(signature.replace("\n", "").trim());
 77		pgpSig.append('\n');
 78		pgpSig.append("-----END PGP SIGNATURE-----");
 79		Intent params = new Intent();
 80		params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
 81		params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
 82		InputStream is = new ByteArrayInputStream(pgpSig.toString().getBytes());
 83		ByteArrayOutputStream os = new ByteArrayOutputStream();
 84		Intent result = api.executeApi(params, is, os);
 85		switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
 86		case OpenPgpApi.RESULT_CODE_SUCCESS:
 87			OpenPgpSignatureResult sigResult
 88            = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE);
 89			if (sigResult==null) {
 90				return 0;
 91			} else {
 92				return sigResult.getKeyId();
 93			}
 94		case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
 95			break;
 96		case OpenPgpApi.RESULT_CODE_ERROR:
 97			throw new OpenPgpException(
 98					(OpenPgpError) result.getParcelableExtra(OpenPgpApi.RESULT_ERROR));
 99		}
100		return 0;
101	}
102
103	public String generateSignature(String status)
104			throws UserInputRequiredException {
105		Intent params = new Intent();
106		params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
107		params.setAction(OpenPgpApi.ACTION_SIGN);
108		InputStream is = new ByteArrayInputStream(status.getBytes());
109		ByteArrayOutputStream os = new ByteArrayOutputStream();
110		Intent result = api.executeApi(params, is, os);
111		StringBuilder signatureBuilder = new StringBuilder();
112		switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
113		case OpenPgpApi.RESULT_CODE_SUCCESS:
114			String[] lines = os.toString().split("\n");
115			for (int i = 7; i < lines.length - 1; ++i) {
116				signatureBuilder.append(lines[i].trim());
117			}
118			break;
119		case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
120			throw new UserInputRequiredException((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
121		case OpenPgpApi.RESULT_CODE_ERROR:
122			break;
123		}
124		return signatureBuilder.toString();
125	}
126
127	public class UserInputRequiredException extends Exception {
128		private static final long serialVersionUID = -6913480043269132016L;
129		private PendingIntent pi;
130
131		public UserInputRequiredException(PendingIntent pi) {
132			this.pi = pi;
133		}
134
135		public PendingIntent getPendingIntent() {
136			return this.pi;
137		}
138	}
139
140	public class OpenPgpException extends Exception {
141		private static final long serialVersionUID = -7324789703473056077L;
142		private OpenPgpError error;
143
144		public OpenPgpException(OpenPgpError openPgpError) {
145			this.error = openPgpError;
146		}
147
148		public OpenPgpError getOpenPgpError() {
149			return this.error;
150		}
151	}
152}