View Javadoc

1   package es.caib.signatura.impl;
2   
3   import java.io.ByteArrayOutputStream;
4   import java.io.FileNotFoundException;
5   import java.io.IOException;
6   import java.io.InputStream;
7   import java.io.Serializable;
8   import java.lang.reflect.Method;
9   import java.security.cert.X509Certificate;
10  import java.util.Date;
11  
12  import es.caib.signatura.api.ParsedCertificate;
13  import es.caib.signatura.api.Signature;
14  import es.caib.signatura.api.SignatureDataException;
15  import es.caib.signatura.api.SignatureProviderException;
16  import es.caib.signatura.api.SignatureTimestampException;
17  import es.caib.signatura.api.SignatureVerifyException;
18  import es.caib.signatura.api.Signer;
19  import es.caib.signatura.impl.ClassLoaderFactory;
20  import es.caib.signatura.impl.SignatureProviderInterface;
21  
22  /**
23   * Implementation of the interface <code>Signature</code> for a web signature.
24   * 
25   * @author Jesús Reyes (3dígits)
26   * @version 0.98
27   * @see Signer
28   * @see Signature
29   */
30  public class WebSignature implements Signature, Serializable {
31  
32  	protected byte[] signatureBytes = null; // array de bytes con la firma
33  
34  	private String contentType = null;
35  
36  	private static final long serialVersionUID = 1;
37  
38  	private transient SignatureProviderInterface impl = null;
39  
40  	private static final int INTERNET_EXPLORER = 1;
41  	private static final int MOZILLA_FIREFOX = 2;
42  	private int origin;
43  
44  	/**
45  	 * Creates a signature object from a web signature. The signature has the
46  	 * following format: &lt;Software identifier&gt;:&lt;MIME type&gt;:&lt;Base 64 codified signature&gt;.
47  	 * The software identifier can be FF (Firefox) or IE (Internet Explorer).
48  	 * 
49  	 * @param firma Web signature.
50  	 * @throws IOException
51  	 * 
52  	 */
53  	public WebSignature(String firma) throws SignatureDataException {
54  		if (firma.startsWith("FF:"))
55  			origin = MOZILLA_FIREFOX;
56  		else if (firma.startsWith("IE:"))
57  			origin = INTERNET_EXPLORER;
58  		else
59  			throw new SignatureDataException();
60  
61  		int len = firma.indexOf(":", 3);
62  
63  		try {
64  			Class base64Class = ClassLoaderFactory.getFactory()
65  					.getMasterClassLoader().loadClass(
66  							"org.bouncycastle.util.encoders.Base64");
67  			Method m = base64Class.getMethod("decode",
68  					new Class[] { String.class });
69  			signatureBytes = (byte[]) m.invoke(null, new Object[] { firma
70  					.substring(len + 1) });
71  			contentType = firma.substring(3, len);
72  			init();
73  		} catch (Exception e) {
74  			throw new SignatureDataException(e);
75  		}
76  	}
77  
78  	public void setContentType(String contentType) {
79  		this.contentType = contentType;
80  	}
81  
82  	public void setPkcs7(byte pkcs7[]) {
83  		signatureBytes = pkcs7;
84  	}
85  
86  	private void init() throws IOException {
87  		if (impl == null) {
88  			try {
89  				ClassLoader cl = ClassLoaderFactory.getFactory()
90  						.getMasterClassLoader();
91  				Class clazz = cl.loadClass(getInternalClassName());
92  				impl = (SignatureProviderInterface) clazz.newInstance();
93  			} catch (InstantiationException e) {
94  				throw new RuntimeException(e);
95  			} catch (IllegalAccessException e) {
96  				throw new RuntimeException(e);
97  			} catch (ClassNotFoundException e) {
98  				throw new RuntimeException(e);
99  			}
100 		}
101 		try {
102 			impl.setContentType(contentType);
103 			impl.setSignedData(signatureBytes);
104 		} catch (Exception e) {
105 			throw new IOException("Unable to parse signature");
106 		}
107 	}
108 
109 	/**
110 	 * Gets the implementing class name.
111 	 * 
112 	 * @returns The implementing class name.
113 	 */
114 	protected String getInternalClassName() {
115 		if (origin == INTERNET_EXPLORER)
116 			return "es.caib.signatura.provider.impl.common.CapicomSignatureImpl";
117 		else if (origin == MOZILLA_FIREFOX)
118 			return "es.caib.signatura.provider.impl.common.CMSSignatureImplv2";
119 		else
120 			throw new RuntimeException("Signature type unknown " + origin);
121 	}
122 
123 	/**
124 	 * {@inheritDoc}
125 	 */
126 	public String getCertCaName() {
127 		return impl.getCertCaName();
128 	}
129 
130 	/**
131 	 * {@inheritDoc}
132 	 */
133 	public String getCertSubjectCommonName() {
134 		return impl.getCertSubjectCommonName();
135 	}
136 
137 	/**
138 	 * {@inheritDoc}
139 	 */
140 	public String getCertSubjectAlternativeNames() {
141 		return impl.getCertSubjectAlternativeNames();
142 	}
143 
144 	/**
145 	 * {@inheritDoc}
146 	 */
147 	public byte[] getPkcs7() {
148 		return this.signatureBytes;
149 	}
150 
151 	// Sobreescribimos el método readObject que deserializa el objeto para
152 	// llamar posteriormente al método privado de inicialización del objetco
153 	// cuyo cometido es extraer el certificado de usuario de la firma
154 	private void readObject(java.io.ObjectInputStream in) throws IOException,
155 			ClassNotFoundException {
156 		in.defaultReadObject();
157 		init();
158 	}
159 
160 	/**
161 	 * {@inheritDoc}
162 	 */
163 	public Date getDate() throws SignatureTimestampException {
164 		return impl.getDate();
165 	}
166 
167 	/**
168 	 * {@inheritDoc}
169 	 */
170 	public boolean verify() throws SignatureVerifyException {
171 		return impl.verify();
172 	}
173 
174 	/**
175 	 * {@inheritDoc}
176 	 */
177 	public String getContentType() {
178 		return contentType;
179 	}
180 
181 	/**
182 	 * {@inheritDoc}
183 	 */
184 	public X509Certificate getCert() {
185 		return impl.getCert();
186 	}
187 
188 	/**
189 	 * {@inheritDoc}
190 	 */
191 	public X509Certificate[] getCertificateChain() throws Exception {
192 		return impl.getCertificateChain();
193 	}
194 
195 	/**
196 	 * {@inheritDoc}
197 	 */
198 	public ParsedCertificate getParsedCertificate() {
199 		return impl.getParsedCertificate();
200 	}
201 
202 	/**
203 	 * {@inheritDoc}
204 	 */
205 	public boolean verify(InputStream contentStream)
206 			throws SignatureProviderException, IOException,
207 			SignatureVerifyException {
208 		boolean isVerified = true;
209 		try {
210 			// verificación interna de la firma
211 			isVerified = isVerified && impl.verify(contentStream);
212 			// isVerified = isVerified && verifyWS();
213 		} catch (SignatureVerifyException e) {
214 			throw e;
215 		} catch (Exception e) {
216 			throw new SignatureVerifyException(e);
217 		}
218 		return isVerified;
219 	}
220 
221 	/**
222 	 * {@inheritDoc}
223 	 */
224 	public boolean verifyAPosterioriTimestamp(InputStream contentStream)
225 			throws SignatureProviderException, IOException,
226 			SignatureVerifyException {
227 		boolean isVerified = true;
228 		try {
229 			// verificación interna de la firma
230 			isVerified = isVerified
231 					&& impl.verifyAPosterioriTimestamp(contentStream);
232 			// *
233 			// * Se actualiza la firma por si el validador ha añadido
234 			// * un sello de tiempo
235 
236 			if (isVerified) {
237 				this.setPkcs7(impl.getPkcs7());
238 			}
239 
240 		} catch (SignatureVerifyException e) {
241 			throw e;
242 		} catch (Exception e) {
243 			throw new SignatureVerifyException(e);
244 		}
245 		return isVerified;
246 	}
247 	/*
248 	 * private boolean WSResponseIsAVerifiedMessage(String result) throws
249 	 * SignatureVerifyException { String content = new String(); try {
250 	 * DocumentBuilderFactory documentBuilderFactory =
251 	 * DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder =
252 	 * documentBuilderFactory.newDocumentBuilder(); Document document;
253 	 * StringBufferInputStream inputStream = new
254 	 * StringBufferInputStream(result); document =
255 	 * documentBuilder.parse((InputStream)inputStream); //Element element =
256 	 * document.getDocumentElement(); try{ NodeList nodeList =
257 	 * document.getElementsByTagName("valido"); Node node = nodeList.item(0);
258 	 * Element element = (Element) node; String tagName = element.getTagName();
259 	 * Node textData = null; boolean stop = false; NodeList nodeDataList =
260 	 * element.getChildNodes(); for(int i = 0;i < nodeDataList.getLength() &&
261 	 * !stop;i++){ textData = nodeDataList.item(i); stop =
262 	 * textData.getNodeType() == org.w3c.dom.Node.TEXT_NODE; } content =
263 	 * ((org.w3c.dom.Text)textData).getData(); }catch(Exception e){ //* Para no
264 	 * llevar a malos entendidos // * se da la firma como falsa // * return
265 	 * false; } if(content == null){ throw new Exception("No content in 'valido'
266 	 * TAG. Response message: " + result); } }catch(Exception e){ throw new
267 	 * SignatureVerifyException(e); } return content.compareToIgnoreCase("true") ==
268 	 * 0; }
269 	 */
270 }