1package de.gultsch.chat.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;
10import org.openintents.openpgp.util.OpenPgpConstants;
11
12import android.app.PendingIntent;
13import android.os.Bundle;
14import android.util.Log;
15
16public class PgpEngine {
17 private OpenPgpApi api;
18
19 public PgpEngine(OpenPgpApi api) {
20 this.api = api;
21 }
22
23 public String decrypt(String message) throws UserInputRequiredException,
24 OpenPgpException {
25 InputStream is = new ByteArrayInputStream(message.getBytes());
26 ByteArrayOutputStream os = new ByteArrayOutputStream();
27 Bundle result = api.decryptAndVerify(is, os);
28 switch (result.getInt(OpenPgpConstants.RESULT_CODE)) {
29 case OpenPgpConstants.RESULT_CODE_SUCCESS:
30 return os.toString();
31 case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED:
32 throw new UserInputRequiredException(
33 (PendingIntent) result
34 .getParcelable(OpenPgpConstants.RESULT_INTENT));
35 case OpenPgpConstants.RESULT_CODE_ERROR:
36 throw new OpenPgpException(
37 (OpenPgpError) result
38 .getParcelable(OpenPgpConstants.RESULT_ERRORS));
39 default:
40 return null;
41 }
42 }
43
44 public String encrypt(long keyId, String message) {
45 Bundle params = new Bundle();
46 params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
47 long[] keyIds = { keyId };
48 params.putLongArray(OpenPgpConstants.PARAMS_KEY_IDS, keyIds);
49
50 InputStream is = new ByteArrayInputStream(message.getBytes());
51 ByteArrayOutputStream os = new ByteArrayOutputStream();
52 Bundle result = api.encrypt(params, is, os);
53 StringBuilder encryptedMessageBody = new StringBuilder();
54 String[] lines = os.toString().split("\n");
55 for (int i = 3; i < lines.length - 1; ++i) {
56 encryptedMessageBody.append(lines[i].trim());
57 }
58 return encryptedMessageBody.toString();
59 }
60
61 public long fetchKeyId(String status, String signature)
62 throws OpenPgpException {
63 StringBuilder pgpSig = new StringBuilder();
64 pgpSig.append("-----BEGIN PGP SIGNED MESSAGE-----");
65 pgpSig.append('\n');
66 pgpSig.append("Hash: SHA1");
67 pgpSig.append('\n');
68 pgpSig.append('\n');
69 pgpSig.append(status);
70 pgpSig.append('\n');
71 pgpSig.append("-----BEGIN PGP SIGNATURE-----");
72 pgpSig.append('\n');
73 pgpSig.append('\n');
74 pgpSig.append(signature.replace("\n", "").trim());
75 pgpSig.append('\n');
76 pgpSig.append("-----END PGP SIGNATURE-----");
77 Bundle params = new Bundle();
78 params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
79 InputStream is = new ByteArrayInputStream(pgpSig.toString().getBytes());
80 ByteArrayOutputStream os = new ByteArrayOutputStream();
81 Bundle result = api.decryptAndVerify(params, is, os);
82 switch (result.getInt(OpenPgpConstants.RESULT_CODE)) {
83 case OpenPgpConstants.RESULT_CODE_SUCCESS:
84 OpenPgpSignatureResult sigResult = result
85 .getParcelable(OpenPgpConstants.RESULT_SIGNATURE);
86 return sigResult.getKeyId();
87 case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED:
88 break;
89 case OpenPgpConstants.RESULT_CODE_ERROR:
90 throw new OpenPgpException(
91 (OpenPgpError) result
92 .getParcelable(OpenPgpConstants.RESULT_ERRORS));
93 }
94 return 0;
95 }
96
97 public String generateSignature(String status)
98 throws UserInputRequiredException {
99 Bundle params = new Bundle();
100 params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
101 InputStream is = new ByteArrayInputStream(status.getBytes());
102 ByteArrayOutputStream os = new ByteArrayOutputStream();
103 Bundle result = api.sign(params, is, os);
104 StringBuilder signatureBuilder = new StringBuilder();
105 switch (result.getInt(OpenPgpConstants.RESULT_CODE)) {
106 case OpenPgpConstants.RESULT_CODE_SUCCESS:
107 String[] lines = os.toString().split("\n");
108 for (int i = 7; i < lines.length - 1; ++i) {
109 signatureBuilder.append(lines[i].trim());
110 }
111 break;
112 case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED:
113 UserInputRequiredException exception = new UserInputRequiredException(
114 (PendingIntent) result
115 .getParcelable(OpenPgpConstants.RESULT_INTENT));
116 throw exception;
117 case OpenPgpConstants.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}