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_ERROR));
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 if ((signature==null)||(api==null)) {
62 return 0;
63 }
64 if (status==null) {
65 status="";
66 }
67 StringBuilder pgpSig = new StringBuilder();
68 pgpSig.append("-----BEGIN PGP SIGNED MESSAGE-----");
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 if (sigResult==null) {
90 return 0;
91 } else {
92 return sigResult.getKeyId();
93 }
94 case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
95 break;
96 case OpenPgpApi.RESULT_CODE_ERROR:
97 throw new OpenPgpException(
98 (OpenPgpError) result.getParcelableExtra(OpenPgpApi.RESULT_ERROR));
99 }
100 return 0;
101 }
102
103 public String generateSignature(String status)
104 throws UserInputRequiredException {
105 Intent params = new Intent();
106 params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
107 params.setAction(OpenPgpApi.ACTION_SIGN);
108 InputStream is = new ByteArrayInputStream(status.getBytes());
109 ByteArrayOutputStream os = new ByteArrayOutputStream();
110 Intent result = api.executeApi(params, is, os);
111 StringBuilder signatureBuilder = new StringBuilder();
112 switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
113 case OpenPgpApi.RESULT_CODE_SUCCESS:
114 String[] lines = os.toString().split("\n");
115 for (int i = 7; i < lines.length - 1; ++i) {
116 signatureBuilder.append(lines[i].trim());
117 }
118 break;
119 case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
120 throw new UserInputRequiredException((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
121 case OpenPgpApi.RESULT_CODE_ERROR:
122 break;
123 }
124 return signatureBuilder.toString();
125 }
126
127 public class UserInputRequiredException extends Exception {
128 private static final long serialVersionUID = -6913480043269132016L;
129 private PendingIntent pi;
130
131 public UserInputRequiredException(PendingIntent pi) {
132 this.pi = pi;
133 }
134
135 public PendingIntent getPendingIntent() {
136 return this.pi;
137 }
138 }
139
140 public class OpenPgpException extends Exception {
141 private static final long serialVersionUID = -7324789703473056077L;
142 private OpenPgpError error;
143
144 public OpenPgpException(OpenPgpError openPgpError) {
145 this.error = openPgpError;
146 }
147
148 public OpenPgpError getOpenPgpError() {
149 return this.error;
150 }
151 }
152}