PgpEngine.java

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