/* Tibisay Movil Copyright (C) 2013 Antonio Araujo (aaraujo@cenditel.gob.ve), Jose Ruiz (jruiz@cenditel.gob.ve), Fundacion Centro Nacional de Desarrollo e Investigacion en Tecnologias Libres - CENDITEL. La Fundación CENDITEL concede permiso para usar, copiar, distribuir y/o modificar este programa, reconociendo el derecho que la humanidad posee al libre acceso al conocimiento, bajo los términos de la licencia de software GPL versión 2.0 de la Free Software Foundation. Este programa se distribuye con la esperanza de que sea util, pero SIN NINGUNA GARANTIA; tampoco las implicitas garantias de MERCANTILIDAD o ADECUACION A UN PROPOSITO PARTICULAR. Para mayor información sobre los términos de la licencia ver el archivo llamado "gpl-2.0.txt" en ingles. */ package ve.gob.cenditel.tibisaymovil; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.ArrayList; import javax.ws.rs.core.MediaType; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.spongycastle.asn1.ASN1StreamParser; import org.spongycastle.asn1.DERSequenceGenerator; import org.spongycastle.cert.jcajce.JcaCertStore; import org.spongycastle.cms.CMSException; import org.spongycastle.cms.CMSProcessableFile; import org.spongycastle.cms.CMSSignedData; import org.spongycastle.cms.CMSSignedDataGenerator; import org.spongycastle.cms.CMSTypedData; import org.spongycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; import org.spongycastle.jce.provider.BouncyCastleProvider; import org.spongycastle.operator.ContentSigner; import org.spongycastle.operator.OperatorCreationException; import org.spongycastle.operator.jcajce.JcaContentSignerBuilder; import org.spongycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; import org.spongycastle.util.Store; import org.spongycastle.util.encoders.Base64Encoder; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.widget.Toast; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientHandlerException; import com.sun.jersey.api.client.ClientRequest; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.client.filter.ClientFilter; import com.sun.jersey.multipart.FormDataMultiPart; import com.sun.jersey.multipart.file.DefaultMediaTypePredictor; import com.sun.jersey.multipart.file.DefaultMediaTypePredictor.CommonMediaTypes; import com.sun.jersey.spi.service.ServiceFinder; /** * Cryptograhic utilities. * * @author José M. Prieto (jmprieto@emergya.com) */ public class CryptoUtils { /** * Sign a file. Generates a PKCS#7 signature in DER encoding. * * @param file the File where the data to be signed is stored * @param certificate certificate of the signer. The certificate is included in the resulting signature * @param key private key used to sign * @return a PKCS#7 signature with the certificate attached encoded in DER format * * @throws CertificateEncodingException if there is an error related to the certificate * @throws CMSException if there is an error signing the data * @throws IOException if there is an error encoding the signature * @throws OperatorCreationException if there is an error in the cryptographic library */ public static byte[] signPKCS7(File file, X509Certificate certificate, PrivateKey key) throws CertificateEncodingException, CMSException, IOException, OperatorCreationException { // TODO reuse CertificateUtils provider BouncyCastleProvider provider = new BouncyCastleProvider(); ArrayList certList = new ArrayList(); CMSTypedData msg = new CMSProcessableFile(file); certList.add(certificate); Store certs = new JcaCertStore(certList); CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(provider).build(key); gen.addSignerInfoGenerator( new JcaSignerInfoGeneratorBuilder( new JcaDigestCalculatorProviderBuilder().setProvider(provider).build()) .build(sha1Signer, certificate)); gen.addCertificates(certs); //TODO: Error in Android 4.2 CMSSignedData cmsData = gen.generate(msg, false); byte[] result = cmsData.getEncoded(); return result; } // public static InputStream signPDF(File file, X509Certificate[] chain, PrivateKey key, Context context) // throws IOException, CertificateEncodingException, JSONException, SignatureException, InvalidKeyException, NoSuchAlgorithmException, DocumentWritingException { // // ServiceFinder.setIteratorProvider(new AndroidServiceIteratorProvider()); // Client client = Client.create(); // client.setConnectTimeout(5000); // client.setReadTimeout(5000); // client.addFilter(new ClientFilter() { // private ArrayList cookies; // // @Override // public ClientResponse handle(ClientRequest request) throws ClientHandlerException { // if (cookies != null) { // request.getHeaders().put("Cookie", cookies); // } // ClientResponse response = getNext().handle(request); // if (response.getCookies() != null) { // if (cookies == null) { // cookies = new ArrayList(); // } // // simple addAll just for illustration (should probably check for duplicates and expired cookies) // cookies.addAll(response.getCookies()); // } // return response; // } // }); // // //TODO: SERVER URL // //EXTERNAL // //WebResource res = client.resource("http://venezuela-apps.emergya.es:51880/service/pdf"); // //INTERNAL // WebResource res = client.resource("http://venezuela-apps.emergya.es:8080/service/pdf"); // //LOCAL Android // //WebResource res = client.resource("http://10.0.2.2:8080/service/pdf"); // // ByteArrayOutputStream buf = new ByteArrayOutputStream(); // DERSequenceGenerator seq = new DERSequenceGenerator(buf); // for (X509Certificate cert : chain) { // seq.addObject(new ASN1StreamParser(cert.getEncoded()).readObject()); // } // seq.close(); // // FormDataMultiPart form = new FormDataMultiPart(); // FileInputStream inputStream = new FileInputStream(file); // form.field("pdf", inputStream, // DefaultMediaTypePredictor.CommonMediaTypes.getMediaTypeFromFile(file)); // form.field("chain", buf.toByteArray(), MediaType.APPLICATION_OCTET_STREAM_TYPE); // // // // //New code: Obtain configuration parameters. //// SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); //// String position = prefs.getString(ConfigurationActivity.positionKey, "3"); //// form.field("position", position); //// //// //// String imagePath = prefs.getString(ConfigurationActivity.imageKey, ""); //// File imageFile; //// InputStream imageStream; //// MediaType mediaType; //// if (imagePath.equals("")){ //// //// imageStream = context.getAssets().open("icono_app.png"); //// mediaType = DefaultMediaTypePredictor.CommonMediaTypes.PNG.getMediaType(); //// //// }else{ //// imageFile = new File(imagePath); //// imageStream = new FileInputStream(imageFile); //// mediaType = DefaultMediaTypePredictor.CommonMediaTypes.getMediaTypeFromFile(imageFile); //// } //// form.field("image", imageStream, mediaType); //// //---- // // // JSONObject json = res.type(MediaType.MULTIPART_FORM_DATA_TYPE).accept(MediaType.APPLICATION_JSON_TYPE).post(JSONObject.class, form); // inputStream.close(); // // // //TODO: ERROR CHECKS // String ERROR_MESSAGE = "errorMessage"; // String ERROR_CODE = "errorCode"; // // try{ // int code = json.getInt(ERROR_CODE); // final String message = json.getString(ERROR_MESSAGE); // if (message!=null && !message.equals("")){ // final Activity act = ((Activity) context); // act.runOnUiThread(new Runnable() { // public void run() { // Toast.makeText(act, message, Toast.LENGTH_SHORT).show(); // } // }); // } // throw new DocumentWritingException(); // // }catch (JSONException e){} // // //---- // // // // byte[] hash = base64Decode(json.getString("hash")); // Signature signer = Signature.getInstance("SHA1withRSA"); // signer.initSign(key); // signer.update(hash); // byte[] signature = signer.sign(); // String signature64 = base64Encode(signature); // // return res.queryParam("s", signature64).accept("application/pdf").get(InputStream.class); // } private static String base64Encode(byte[] data) throws IOException { Base64Encoder encoder = new Base64Encoder(); ByteArrayOutputStream stream = new ByteArrayOutputStream(); encoder.encode(data, 0, data.length, stream); return stream.toString(); } private static byte[] base64Decode(String string) throws IOException { Base64Encoder encoder = new Base64Encoder(); ByteArrayOutputStream buf = new ByteArrayOutputStream(); encoder.decode(string, buf); return buf.toByteArray(); } }