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_ERRORS));
 37		default:
 38			return null;
 39		}
 40	}
 41
 42	public String encrypt(long keyId, String message) {
 43		Log.d("xmppService","encrypt message: "+message+" for key "+keyId);
 44		long[] keys = {keyId};
 45		Intent params = new Intent();
 46		params.setAction(OpenPgpApi.ACTION_ENCRYPT);
 47		params.putExtra(OpenPgpApi.EXTRA_KEY_IDS,keys);
 48		params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
 49		
 50		InputStream is = new ByteArrayInputStream(message.getBytes());
 51		ByteArrayOutputStream os = new ByteArrayOutputStream();
 52		Intent result = api.executeApi(params, is, os);
 53		StringBuilder encryptedMessageBody = new StringBuilder();
 54		Log.d("xmppService","intent: "+result.toString());
 55		Log.d("xmppService","output: "+os.toString());
 56		String[] lines = os.toString().split("\n");
 57		for (int i = 3; i < lines.length - 1; ++i) {
 58			encryptedMessageBody.append(lines[i].trim());
 59		}
 60		return encryptedMessageBody.toString();
 61	}
 62
 63	public long fetchKeyId(String status, String signature)
 64			throws OpenPgpException {
 65		StringBuilder pgpSig = new StringBuilder();
 66		pgpSig.append("-----BEGIN PGP SIGNED MESSAGE-----");
 67		pgpSig.append('\n');
 68		pgpSig.append("Hash: SHA1");
 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			return sigResult.getKeyId();
 90		case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
 91			break;
 92		case OpenPgpApi.RESULT_CODE_ERROR:
 93			throw new OpenPgpException(
 94					(OpenPgpError) result.getParcelableExtra(OpenPgpApi.RESULT_ERRORS));
 95		}
 96		return 0;
 97	}
 98
 99	public String generateSignature(String status)
100			throws UserInputRequiredException {
101		Intent params = new Intent();
102		params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
103		params.setAction(OpenPgpApi.ACTION_SIGN);
104		InputStream is = new ByteArrayInputStream(status.getBytes());
105		ByteArrayOutputStream os = new ByteArrayOutputStream();
106		Intent result = api.executeApi(params, is, os);
107		StringBuilder signatureBuilder = new StringBuilder();
108		switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
109		case OpenPgpApi.RESULT_CODE_SUCCESS:
110			String[] lines = os.toString().split("\n");
111			for (int i = 7; i < lines.length - 1; ++i) {
112				signatureBuilder.append(lines[i].trim());
113			}
114			break;
115		case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
116			throw new UserInputRequiredException((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
117		case OpenPgpApi.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}