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