PgpEngine.java

  1package eu.siacs.conversations.crypto;
  2
  3import java.io.ByteArrayInputStream;
  4import java.io.ByteArrayOutputStream;
  5import java.io.InputStream;
  6import java.io.OutputStream;
  7
  8import org.openintents.openpgp.OpenPgpError;
  9import org.openintents.openpgp.OpenPgpSignatureResult;
 10import org.openintents.openpgp.util.OpenPgpApi;
 11import org.openintents.openpgp.util.OpenPgpApi.IOpenPgpCallback;
 12
 13import eu.siacs.conversations.entities.Account;
 14import eu.siacs.conversations.entities.Contact;
 15import eu.siacs.conversations.entities.Message;
 16
 17import android.app.PendingIntent;
 18import android.content.Intent;
 19import android.util.Log;
 20
 21public class PgpEngine {
 22	private OpenPgpApi api;
 23
 24	public PgpEngine(OpenPgpApi api) {
 25		this.api = api;
 26	}
 27
 28	public void decrypt(final Message message, final OnPgpEngineResult callback) {
 29		Intent params = new Intent();
 30		params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
 31		params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, message
 32				.getConversation().getAccount().getJid());
 33		InputStream is = new ByteArrayInputStream(message.getBody().getBytes());
 34		final OutputStream os = new ByteArrayOutputStream();
 35		api.executeApiAsync(params, is, os, new IOpenPgpCallback() {
 36
 37			@Override
 38			public void onReturn(Intent result) {
 39				switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
 40						OpenPgpApi.RESULT_CODE_ERROR)) {
 41				case OpenPgpApi.RESULT_CODE_SUCCESS:
 42					message.setBody(os.toString());
 43					message.setEncryption(Message.ENCRYPTION_DECRYPTED);
 44					callback.success();
 45					return;
 46				case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
 47					callback.userInputRequried((PendingIntent) result
 48							.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
 49					return;
 50				case OpenPgpApi.RESULT_CODE_ERROR:
 51					callback.error((OpenPgpError) result
 52							.getParcelableExtra(OpenPgpApi.RESULT_ERROR));
 53					return;
 54				default:
 55					return;
 56				}
 57			}
 58		});
 59	}
 60
 61	public void encrypt(Account account, long keyId, Message message,
 62			final OnPgpEngineResult callback) {
 63		Log.d("xmppService", "called to pgpengine::encrypt");
 64		long[] keys = { keyId };
 65		Intent params = new Intent();
 66		params.setAction(OpenPgpApi.ACTION_ENCRYPT);
 67		params.putExtra(OpenPgpApi.EXTRA_KEY_IDS, keys);
 68		params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
 69		params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, account.getJid());
 70
 71		InputStream is = new ByteArrayInputStream(message.getBody().getBytes());
 72		ByteArrayOutputStream os = new ByteArrayOutputStream();
 73		Intent result = api.executeApi(params, is, os);
 74		switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
 75				OpenPgpApi.RESULT_CODE_ERROR)) {
 76		case OpenPgpApi.RESULT_CODE_SUCCESS:
 77			StringBuilder encryptedMessageBody = new StringBuilder();
 78			String[] lines = os.toString().split("\n");
 79			for (int i = 3; i < lines.length - 1; ++i) {
 80				encryptedMessageBody.append(lines[i].trim());
 81			}
 82			message.setEncryptedBody(encryptedMessageBody.toString());
 83			callback.success();
 84			return;
 85		case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
 86			callback.userInputRequried((PendingIntent) result
 87					.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
 88			return;
 89		case OpenPgpApi.RESULT_CODE_ERROR:
 90			callback.error((OpenPgpError) result
 91					.getParcelableExtra(OpenPgpApi.RESULT_ERROR));
 92			return;
 93		}
 94	}
 95
 96	public long fetchKeyId(Account account, String status, String signature) {
 97		if ((signature == null) || (api == null)) {
 98			return 0;
 99		}
100		if (status == null) {
101			status = "";
102		}
103		StringBuilder pgpSig = new StringBuilder();
104		pgpSig.append("-----BEGIN PGP SIGNED MESSAGE-----");
105		pgpSig.append('\n');
106		pgpSig.append('\n');
107		pgpSig.append(status);
108		pgpSig.append('\n');
109		pgpSig.append("-----BEGIN PGP SIGNATURE-----");
110		pgpSig.append('\n');
111		pgpSig.append('\n');
112		pgpSig.append(signature.replace("\n", "").trim());
113		pgpSig.append('\n');
114		pgpSig.append("-----END PGP SIGNATURE-----");
115		Intent params = new Intent();
116		params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
117		params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
118		params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, account.getJid());
119		InputStream is = new ByteArrayInputStream(pgpSig.toString().getBytes());
120		ByteArrayOutputStream os = new ByteArrayOutputStream();
121		Intent result = api.executeApi(params, is, os);
122		switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
123				OpenPgpApi.RESULT_CODE_ERROR)) {
124		case OpenPgpApi.RESULT_CODE_SUCCESS:
125			OpenPgpSignatureResult sigResult = result
126					.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE);
127			if (sigResult != null) {
128				return sigResult.getKeyId();
129			} else {
130				return 0;
131			}
132		case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
133			Log.d("xmppService","user interaction required");
134			return 0;
135		case OpenPgpApi.RESULT_CODE_ERROR:
136			Log.d("xmppService","pgp error");
137			return 0;
138		}
139		return 0;
140	}
141
142	public void generateSignature(final Account account, String status,
143			final OnPgpEngineResult callback) {
144		Intent params = new Intent();
145		params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
146		params.setAction(OpenPgpApi.ACTION_SIGN);
147		params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, account.getJid());
148		InputStream is = new ByteArrayInputStream(status.getBytes());
149		final OutputStream os = new ByteArrayOutputStream();
150		api.executeApiAsync(params, is, os, new IOpenPgpCallback() {
151
152			@Override
153			public void onReturn(Intent result) {
154				switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
155				case OpenPgpApi.RESULT_CODE_SUCCESS:
156					StringBuilder signatureBuilder = new StringBuilder();
157					String[] lines = os.toString().split("\n");
158					for (int i = 7; i < lines.length - 1; ++i) {
159						signatureBuilder.append(lines[i].trim());
160					}
161					account.setKey("pgp_signature", signatureBuilder.toString());
162					callback.success();
163					return;
164				case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
165					callback.userInputRequried((PendingIntent) result
166							.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
167					return;
168				case OpenPgpApi.RESULT_CODE_ERROR:
169					callback.error((OpenPgpError) result
170							.getParcelableExtra(OpenPgpApi.RESULT_ERROR));
171					return;
172				}
173			}
174		});
175	}
176	
177	public void hasKey(Account account, long keyId, final OnPgpEngineResult callback) {
178		Intent params = new Intent();
179		params.setAction(OpenPgpApi.ACTION_GET_KEY);
180		params.putExtra(OpenPgpApi.EXTRA_KEY_ID, keyId);
181		params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, account.getJid());
182		InputStream is = new ByteArrayInputStream(new byte[0]);
183		OutputStream os = new ByteArrayOutputStream();
184		api.executeApiAsync(params, is, os, new IOpenPgpCallback() {
185			
186			@Override
187			public void onReturn(Intent result) {
188				switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
189				case OpenPgpApi.RESULT_CODE_SUCCESS:
190					callback.success();
191					return;
192				case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
193					callback.userInputRequried((PendingIntent) result
194							.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
195					return;
196				case OpenPgpApi.RESULT_CODE_ERROR:
197					callback.error((OpenPgpError) result
198							.getParcelableExtra(OpenPgpApi.RESULT_ERROR));
199					return;
200				}
201			}
202		});
203	}
204}