blob: 338d427fa7045980bf784643e0fc22d35303edb3 [file] [log] [blame]
Szymon Starzycki781f9fc2013-10-02 17:21:41 -07001package 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}