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