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