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 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_ERROR));
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}