1package signtool; 2 3import java.io.*; 4import java.util.Properties; 5import java.util.ArrayList; 6 7import javax.mail.internet.*; 8import javax.mail.MessagingException; 9import javax.mail.Session; 10import javax.activation.MailcapCommandMap; 11import javax.activation.CommandMap; 12 13import java.security.PrivateKey; 14import java.security.Security; 15import java.security.KeyFactory; 16import java.security.KeyStore; 17import java.security.NoSuchAlgorithmException; 18import java.security.spec.PKCS8EncodedKeySpec; 19import java.security.spec.InvalidKeySpecException; 20import java.security.cert.X509Certificate; 21import java.security.cert.CertificateFactory; 22import java.security.cert.Certificate; 23import java.security.cert.CertificateException; 24import java.security.cert.CertificateEncodingException; 25 26import org.bouncycastle.jce.provider.BouncyCastleProvider; 27import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; 28import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; 29import org.bouncycastle.operator.ContentSigner; 30import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; 31import org.bouncycastle.cms.CMSProcessableByteArray; 32import org.bouncycastle.cms.CMSSignedGenerator; 33import org.bouncycastle.cms.CMSSignedDataGenerator; 34import org.bouncycastle.cms.CMSSignedGenerator; 35import org.bouncycastle.cms.CMSProcessable; 36import org.bouncycastle.cms.CMSSignedData; 37import org.bouncycastle.cms.CMSTypedData; 38import org.bouncycastle.cert.jcajce.JcaCertStore; 39import org.bouncycastle.util.Store; 40import org.bouncycastle.asn1.ASN1InputStream; 41import org.bouncycastle.asn1.DEROutputStream; 42import org.bouncycastle.asn1.ASN1Object; 43 44 45public 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