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(); } }