Home | History | Annotate | Download | only in src
      1 package signtool;
      2 
      3 import java.io.*;
      4 import java.util.Properties;
      5 import java.util.ArrayList;
      6 
      7 import javax.mail.internet.*;
      8 import javax.mail.MessagingException;
      9 import javax.mail.Session;
     10 import javax.activation.MailcapCommandMap;
     11 import javax.activation.CommandMap;
     12 
     13 import java.security.PrivateKey;
     14 import java.security.Security;
     15 import java.security.KeyFactory;
     16 import java.security.KeyStore;
     17 import java.security.NoSuchAlgorithmException;
     18 import java.security.spec.PKCS8EncodedKeySpec;
     19 import java.security.spec.InvalidKeySpecException;
     20 import java.security.cert.X509Certificate;
     21 import java.security.cert.CertificateFactory;
     22 import java.security.cert.Certificate;
     23 import java.security.cert.CertificateException;
     24 import java.security.cert.CertificateEncodingException;
     25 
     26 import org.bouncycastle.jce.provider.BouncyCastleProvider;
     27 import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
     28 import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
     29 import org.bouncycastle.operator.ContentSigner;
     30 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
     31 import org.bouncycastle.cms.CMSProcessableByteArray;
     32 import org.bouncycastle.cms.CMSSignedGenerator;
     33 import org.bouncycastle.cms.CMSSignedDataGenerator;
     34 import org.bouncycastle.cms.CMSSignedGenerator;
     35 import org.bouncycastle.cms.CMSProcessable;
     36 import org.bouncycastle.cms.CMSSignedData;
     37 import org.bouncycastle.cms.CMSTypedData;
     38 import org.bouncycastle.cert.jcajce.JcaCertStore;
     39 import org.bouncycastle.util.Store;
     40 import org.bouncycastle.asn1.ASN1InputStream;
     41 import org.bouncycastle.asn1.DEROutputStream;
     42 import org.bouncycastle.asn1.ASN1Object;
     43 
     44 
     45 public class SignImg {
     46 
     47     /* It reads private key in pkcs#8 formate
     48      * Conversion:
     49      * openssl pkcs8 -topk8 -nocrypt -outform DER < inkey.pem > outkey.pk8
     50      */
     51     private static PrivateKey getPrivateKey(String path) throws IOException, FileNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException {
     52         File file = new File(path);
     53         FileInputStream fis = new FileInputStream(file);
     54         byte[] data = new byte[(int)file.length()];
     55         fis.read(data);
     56         fis.close();
     57 
     58         PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(data);
     59         KeyFactory kf = KeyFactory.getInstance("RSA");
     60         PrivateKey privateKey = kf.generatePrivate(kspec);
     61 
     62         return privateKey;
     63     }
     64 
     65     private static MimeBodyPart getContent(String path) throws IOException, FileNotFoundException, MessagingException {
     66         MimeBodyPart body = new MimeBodyPart();
     67 
     68         File file = new File(path);
     69         FileInputStream fis = new FileInputStream(file);
     70         byte[] data = new byte[(int)file.length()];
     71         fis.read(data);
     72         fis.close();
     73 
     74         body.setContent(data, "application/octet-stream");
     75 
     76         return body;
     77     }
     78 
     79     private static CMSProcessableByteArray getCMSContent(String path) throws IOException, FileNotFoundException, MessagingException {
     80         File file = new File(path);
     81         FileInputStream fis = new FileInputStream(file);
     82         byte[] data = new byte[(int)file.length()];
     83         fis.read(data);
     84         fis.close();
     85         CMSProcessableByteArray cms = new CMSProcessableByteArray(data);
     86 
     87         return cms;
     88     }
     89 
     90     private static X509Certificate readCert(String path) throws IOException, FileNotFoundException, CertificateException {
     91         File file = new File(path);
     92         FileInputStream is = new FileInputStream(file);
     93 
     94         CertificateFactory cf = CertificateFactory.getInstance("X.509");
     95         Certificate cert = cf.generateCertificate(is);
     96         is.close();
     97 
     98         return (X509Certificate) cert;
     99     }
    100 
    101     private static void save(MimeBodyPart content, String path) throws IOException, FileNotFoundException, MessagingException {
    102         File file = new File(path);
    103         FileOutputStream os = new FileOutputStream(file);
    104 
    105         content.writeTo(os);
    106 
    107         os.close();
    108     }
    109 
    110     private static Store certToStore(X509Certificate certificate) throws CertificateEncodingException {
    111         ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>();
    112         certList.add(certificate);
    113         return new JcaCertStore(certList);
    114     }
    115 
    116     public static void setDefaultMailcap()
    117     {
    118         MailcapCommandMap _mailcap =
    119             (MailcapCommandMap)CommandMap.getDefaultCommandMap();
    120 
    121         _mailcap.addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature");
    122         _mailcap.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime");
    123         _mailcap.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature");
    124         _mailcap.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime");
    125         _mailcap.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed");
    126 
    127         CommandMap.setDefaultCommandMap(_mailcap);
    128     }
    129 
    130     public static void main(String[] args) {
    131         try {
    132             if (args.length < 4) {
    133                 System.out.println("Usage: signimg data private_key certificate output");
    134                 return;
    135             }
    136             System.out.println("Signing the image");
    137             setDefaultMailcap();
    138 
    139             Security.addProvider(new BouncyCastleProvider());
    140 
    141             PrivateKey key = getPrivateKey(args[1]);
    142             System.out.println("File read sucessfully");
    143 
    144             CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
    145 
    146             CMSTypedData body = getCMSContent(args[0]);
    147             System.out.println("Content read sucessfully");
    148 
    149             X509Certificate cert = (X509Certificate) readCert(args[2]);
    150             System.out.println("Certificate read sucessfully");
    151 
    152             ContentSigner sha256Signer = new JcaContentSignerBuilder("SHA256withRSA").setProvider("BC").build(key);
    153 
    154             Store certs = certToStore(cert);
    155 
    156             generator.addCertificates(certs);
    157             generator.addSignerInfoGenerator(
    158                           new JcaSignerInfoGeneratorBuilder(
    159                                 new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
    160                           .build(sha256Signer, cert));
    161 
    162             CMSSignedData signed = generator.generate(body, true);
    163             System.out.println("Signed");
    164 
    165             Properties props = System.getProperties();
    166             Session session = Session.getDefaultInstance(props, null);
    167 
    168             File file = new File(args[3]);
    169             FileOutputStream os = new FileOutputStream(file);
    170 
    171             ASN1InputStream asn1 = new ASN1InputStream(signed.getEncoded());
    172             ByteArrayOutputStream out = new ByteArrayOutputStream();
    173             DEROutputStream dOut = new DEROutputStream(os);
    174             dOut.writeObject(ASN1Object.fromByteArray(signed.getEncoded()));
    175 
    176         }
    177         catch (Exception ex) {
    178             System.out.println("Exception during programm execution: " + ex.getMessage());
    179         }
    180     }
    181 }
    182