[288126d] | 1 | package ve.gob.cenditel.tibisaymovil; |
---|
| 2 | |
---|
| 3 | import java.io.BufferedInputStream; |
---|
| 4 | import java.io.ByteArrayOutputStream; |
---|
| 5 | import java.io.File; |
---|
| 6 | import java.io.FileInputStream; |
---|
| 7 | import java.io.IOException; |
---|
| 8 | import java.io.InputStream; |
---|
| 9 | import java.security.InvalidKeyException; |
---|
| 10 | import java.security.NoSuchAlgorithmException; |
---|
| 11 | import java.security.PrivateKey; |
---|
| 12 | import java.security.Signature; |
---|
| 13 | import java.security.SignatureException; |
---|
| 14 | import java.security.cert.CertificateEncodingException; |
---|
| 15 | import java.security.cert.X509Certificate; |
---|
| 16 | import java.util.ArrayList; |
---|
| 17 | |
---|
| 18 | import javax.ws.rs.core.MediaType; |
---|
| 19 | |
---|
| 20 | import org.codehaus.jettison.json.JSONException; |
---|
| 21 | import org.codehaus.jettison.json.JSONObject; |
---|
| 22 | import org.spongycastle.asn1.ASN1StreamParser; |
---|
| 23 | import org.spongycastle.asn1.DERSequenceGenerator; |
---|
| 24 | import org.spongycastle.cert.jcajce.JcaCertStore; |
---|
| 25 | import org.spongycastle.cms.CMSException; |
---|
| 26 | import org.spongycastle.cms.CMSProcessableFile; |
---|
| 27 | import org.spongycastle.cms.CMSSignedData; |
---|
| 28 | import org.spongycastle.cms.CMSSignedDataGenerator; |
---|
| 29 | import org.spongycastle.cms.CMSTypedData; |
---|
| 30 | import org.spongycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; |
---|
| 31 | import org.spongycastle.jce.provider.BouncyCastleProvider; |
---|
| 32 | import org.spongycastle.operator.ContentSigner; |
---|
| 33 | import org.spongycastle.operator.OperatorCreationException; |
---|
| 34 | import org.spongycastle.operator.jcajce.JcaContentSignerBuilder; |
---|
| 35 | import org.spongycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; |
---|
| 36 | import org.spongycastle.util.Store; |
---|
| 37 | import org.spongycastle.util.encoders.Base64Encoder; |
---|
| 38 | |
---|
| 39 | import android.app.Activity; |
---|
| 40 | import android.content.Context; |
---|
| 41 | import android.content.SharedPreferences; |
---|
| 42 | import android.preference.PreferenceManager; |
---|
| 43 | import android.widget.Toast; |
---|
| 44 | |
---|
| 45 | import com.sun.jersey.api.client.Client; |
---|
| 46 | import com.sun.jersey.api.client.ClientHandlerException; |
---|
| 47 | import com.sun.jersey.api.client.ClientRequest; |
---|
| 48 | import com.sun.jersey.api.client.ClientResponse; |
---|
| 49 | import com.sun.jersey.api.client.WebResource; |
---|
| 50 | import com.sun.jersey.api.client.filter.ClientFilter; |
---|
| 51 | import com.sun.jersey.multipart.FormDataMultiPart; |
---|
| 52 | import com.sun.jersey.multipart.file.DefaultMediaTypePredictor; |
---|
| 53 | import com.sun.jersey.multipart.file.DefaultMediaTypePredictor.CommonMediaTypes; |
---|
| 54 | import com.sun.jersey.spi.service.ServiceFinder; |
---|
| 55 | |
---|
| 56 | /** |
---|
| 57 | * Cryptograhic utilities. |
---|
| 58 | * |
---|
| 59 | * @author José M. Prieto (jmprieto@emergya.com) |
---|
| 60 | */ |
---|
| 61 | public class CryptoUtils { |
---|
| 62 | |
---|
| 63 | /** |
---|
| 64 | * Sign a file. Generates a PKCS#7 signature in DER encoding. |
---|
| 65 | * |
---|
| 66 | * @param file the File where the data to be signed is stored |
---|
| 67 | * @param certificate certificate of the signer. The certificate is included in the resulting signature |
---|
| 68 | * @param key private key used to sign |
---|
| 69 | * @return a PKCS#7 signature with the certificate attached encoded in DER format |
---|
| 70 | * |
---|
| 71 | * @throws CertificateEncodingException if there is an error related to the certificate |
---|
| 72 | * @throws CMSException if there is an error signing the data |
---|
| 73 | * @throws IOException if there is an error encoding the signature |
---|
| 74 | * @throws OperatorCreationException if there is an error in the cryptographic library |
---|
| 75 | */ |
---|
| 76 | public static byte[] signPKCS7(File file, X509Certificate certificate, PrivateKey key) |
---|
| 77 | throws CertificateEncodingException, CMSException, IOException, OperatorCreationException { |
---|
| 78 | |
---|
| 79 | // TODO reuse CertificateUtils provider |
---|
| 80 | BouncyCastleProvider provider = new BouncyCastleProvider(); |
---|
| 81 | ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>(); |
---|
| 82 | CMSTypedData msg = new CMSProcessableFile(file); |
---|
| 83 | |
---|
| 84 | certList.add(certificate); |
---|
| 85 | |
---|
| 86 | Store certs = new JcaCertStore(certList); |
---|
| 87 | |
---|
| 88 | CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); |
---|
| 89 | ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(provider).build(key); |
---|
| 90 | |
---|
| 91 | gen.addSignerInfoGenerator( |
---|
| 92 | new JcaSignerInfoGeneratorBuilder( |
---|
| 93 | new JcaDigestCalculatorProviderBuilder().setProvider(provider).build()) |
---|
| 94 | .build(sha1Signer, certificate)); |
---|
| 95 | |
---|
| 96 | gen.addCertificates(certs); |
---|
| 97 | |
---|
| 98 | |
---|
| 99 | //TODO: Error in Android 4.2 |
---|
| 100 | CMSSignedData cmsData = gen.generate(msg, false); |
---|
| 101 | |
---|
| 102 | byte[] result = cmsData.getEncoded(); |
---|
| 103 | return result; |
---|
| 104 | } |
---|
| 105 | |
---|
| 106 | // public static InputStream signPDF(File file, X509Certificate[] chain, PrivateKey key, Context context) |
---|
| 107 | // throws IOException, CertificateEncodingException, JSONException, SignatureException, InvalidKeyException, NoSuchAlgorithmException, DocumentWritingException { |
---|
| 108 | // |
---|
| 109 | // ServiceFinder.setIteratorProvider(new AndroidServiceIteratorProvider()); |
---|
| 110 | // Client client = Client.create(); |
---|
| 111 | // client.setConnectTimeout(5000); |
---|
| 112 | // client.setReadTimeout(5000); |
---|
| 113 | // client.addFilter(new ClientFilter() { |
---|
| 114 | // private ArrayList<Object> cookies; |
---|
| 115 | // |
---|
| 116 | // @Override |
---|
| 117 | // public ClientResponse handle(ClientRequest request) throws ClientHandlerException { |
---|
| 118 | // if (cookies != null) { |
---|
| 119 | // request.getHeaders().put("Cookie", cookies); |
---|
| 120 | // } |
---|
| 121 | // ClientResponse response = getNext().handle(request); |
---|
| 122 | // if (response.getCookies() != null) { |
---|
| 123 | // if (cookies == null) { |
---|
| 124 | // cookies = new ArrayList<Object>(); |
---|
| 125 | // } |
---|
| 126 | // // simple addAll just for illustration (should probably check for duplicates and expired cookies) |
---|
| 127 | // cookies.addAll(response.getCookies()); |
---|
| 128 | // } |
---|
| 129 | // return response; |
---|
| 130 | // } |
---|
| 131 | // }); |
---|
| 132 | // |
---|
| 133 | // //TODO: SERVER URL |
---|
| 134 | // //EXTERNAL |
---|
| 135 | // //WebResource res = client.resource("http://venezuela-apps.emergya.es:51880/service/pdf"); |
---|
| 136 | // //INTERNAL |
---|
| 137 | // WebResource res = client.resource("http://venezuela-apps.emergya.es:8080/service/pdf"); |
---|
| 138 | // //LOCAL Android |
---|
| 139 | // //WebResource res = client.resource("http://10.0.2.2:8080/service/pdf"); |
---|
| 140 | // |
---|
| 141 | // ByteArrayOutputStream buf = new ByteArrayOutputStream(); |
---|
| 142 | // DERSequenceGenerator seq = new DERSequenceGenerator(buf); |
---|
| 143 | // for (X509Certificate cert : chain) { |
---|
| 144 | // seq.addObject(new ASN1StreamParser(cert.getEncoded()).readObject()); |
---|
| 145 | // } |
---|
| 146 | // seq.close(); |
---|
| 147 | // |
---|
| 148 | // FormDataMultiPart form = new FormDataMultiPart(); |
---|
| 149 | // FileInputStream inputStream = new FileInputStream(file); |
---|
| 150 | // form.field("pdf", inputStream, |
---|
| 151 | // DefaultMediaTypePredictor.CommonMediaTypes.getMediaTypeFromFile(file)); |
---|
| 152 | // form.field("chain", buf.toByteArray(), MediaType.APPLICATION_OCTET_STREAM_TYPE); |
---|
| 153 | // |
---|
| 154 | // |
---|
| 155 | // |
---|
| 156 | // //New code: Obtain configuration parameters. |
---|
| 157 | //// SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); |
---|
| 158 | //// String position = prefs.getString(ConfigurationActivity.positionKey, "3"); |
---|
| 159 | //// form.field("position", position); |
---|
| 160 | //// |
---|
| 161 | //// |
---|
| 162 | //// String imagePath = prefs.getString(ConfigurationActivity.imageKey, ""); |
---|
| 163 | //// File imageFile; |
---|
| 164 | //// InputStream imageStream; |
---|
| 165 | //// MediaType mediaType; |
---|
| 166 | //// if (imagePath.equals("")){ |
---|
| 167 | //// |
---|
| 168 | //// imageStream = context.getAssets().open("icono_app.png"); |
---|
| 169 | //// mediaType = DefaultMediaTypePredictor.CommonMediaTypes.PNG.getMediaType(); |
---|
| 170 | //// |
---|
| 171 | //// }else{ |
---|
| 172 | //// imageFile = new File(imagePath); |
---|
| 173 | //// imageStream = new FileInputStream(imageFile); |
---|
| 174 | //// mediaType = DefaultMediaTypePredictor.CommonMediaTypes.getMediaTypeFromFile(imageFile); |
---|
| 175 | //// } |
---|
| 176 | //// form.field("image", imageStream, mediaType); |
---|
| 177 | //// //---- |
---|
| 178 | // |
---|
| 179 | // |
---|
| 180 | // JSONObject json = res.type(MediaType.MULTIPART_FORM_DATA_TYPE).accept(MediaType.APPLICATION_JSON_TYPE).post(JSONObject.class, form); |
---|
| 181 | // inputStream.close(); |
---|
| 182 | // |
---|
| 183 | // |
---|
| 184 | // //TODO: ERROR CHECKS |
---|
| 185 | // String ERROR_MESSAGE = "errorMessage"; |
---|
| 186 | // String ERROR_CODE = "errorCode"; |
---|
| 187 | // |
---|
| 188 | // try{ |
---|
| 189 | // int code = json.getInt(ERROR_CODE); |
---|
| 190 | // final String message = json.getString(ERROR_MESSAGE); |
---|
| 191 | // if (message!=null && !message.equals("")){ |
---|
| 192 | // final Activity act = ((Activity) context); |
---|
| 193 | // act.runOnUiThread(new Runnable() { |
---|
| 194 | // public void run() { |
---|
| 195 | // Toast.makeText(act, message, Toast.LENGTH_SHORT).show(); |
---|
| 196 | // } |
---|
| 197 | // }); |
---|
| 198 | // } |
---|
| 199 | // throw new DocumentWritingException(); |
---|
| 200 | // |
---|
| 201 | // }catch (JSONException e){} |
---|
| 202 | // |
---|
| 203 | // //---- |
---|
| 204 | // |
---|
| 205 | // |
---|
| 206 | // |
---|
| 207 | // byte[] hash = base64Decode(json.getString("hash")); |
---|
| 208 | // Signature signer = Signature.getInstance("SHA1withRSA"); |
---|
| 209 | // signer.initSign(key); |
---|
| 210 | // signer.update(hash); |
---|
| 211 | // byte[] signature = signer.sign(); |
---|
| 212 | // String signature64 = base64Encode(signature); |
---|
| 213 | // |
---|
| 214 | // return res.queryParam("s", signature64).accept("application/pdf").get(InputStream.class); |
---|
| 215 | // } |
---|
| 216 | |
---|
| 217 | private static String base64Encode(byte[] data) |
---|
| 218 | throws IOException { |
---|
| 219 | |
---|
| 220 | Base64Encoder encoder = new Base64Encoder(); |
---|
| 221 | ByteArrayOutputStream stream = new ByteArrayOutputStream(); |
---|
| 222 | encoder.encode(data, 0, data.length, stream); |
---|
| 223 | return stream.toString(); |
---|
| 224 | } |
---|
| 225 | |
---|
| 226 | private static byte[] base64Decode(String string) |
---|
| 227 | throws IOException { |
---|
| 228 | |
---|
| 229 | Base64Encoder encoder = new Base64Encoder(); |
---|
| 230 | ByteArrayOutputStream buf = new ByteArrayOutputStream(); |
---|
| 231 | encoder.decode(string, buf); |
---|
| 232 | return buf.toByteArray(); |
---|
| 233 | } |
---|
| 234 | } |
---|