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   * Implementación de la interfaz <code>SignatureData</code> para usar con la
24   * entidad certificadora Tradisea
25   * 
26   * @author Jesús Reyes (3dígits)
27   * @version 0.98
28   * @see Signer
29   * @see Signature
30   * 
31   */
32  public class WebSignature implements Signature, Serializable {
33  
34  	protected byte[] signatureBytes = null; // array de bytes con la firma
35  
36  	private String contentType = null;
37  
38  	private static final long serialVersionUID = 1;
39  
40  	private transient SignatureProviderInterface impl = null;
41  
42  	private static final int INTERNET_EXPLORER = 1;
43  	private static final int MOZILLA_FIREFOX = 2;
44  	private int origin;
45  
46  	/**
47  	 * Crea un objeto firma a partir de una firma web La firma web consta de
48  	 * <Identificador del software>:<Tipo Mime>:<Firma BASE64>
49  	 * 
50  	 * El identificador del software puede ser FF o IE
51  	 * 
52  	 * @param firma
53  	 *            Firma codificada
54  	 * @throws IOException
55  	 * 
56  	 */
57  	public WebSignature(String firma) throws SignatureDataException {
58  		if (firma.startsWith("FF:"))
59  			origin = MOZILLA_FIREFOX;
60  		else if (firma.startsWith("IE:"))
61  			origin = INTERNET_EXPLORER;
62  		else
63  			throw new SignatureDataException();
64  
65  		int len = firma.indexOf(":", 3);
66  
67  		try {
68  			Class base64Class = ClassLoaderFactory.getFactory()
69  					.getMasterClassLoader().loadClass(
70  							"org.bouncycastle.util.encoders.Base64");
71  			Method m = base64Class.getMethod("decode",
72  					new Class[] { String.class });
73  			signatureBytes = (byte[]) m.invoke(null, new Object[] { firma
74  					.substring(len + 1) });
75  			contentType = firma.substring(3, len);
76  			init();
77  		} catch (Exception e) {
78  			throw new SignatureDataException(e);
79  		}
80  	}
81  
82  	public void setContentType(String contentType) {
83  		this.contentType = contentType;
84  	}
85  
86  	public void setPkcs7(byte pkcs7[]) {
87  		signatureBytes = pkcs7;
88  	}
89  
90  	private void init() throws IOException {
91  		if (impl == null) {
92  			try {
93  				ClassLoader cl = ClassLoaderFactory.getFactory()
94  						.getMasterClassLoader();
95  				Class clazz = cl.loadClass(getInternalClassName());
96  				impl = (SignatureProviderInterface) clazz.newInstance();
97  			} catch (InstantiationException e) {
98  				throw new RuntimeException(e);
99  			} catch (IllegalAccessException e) {
100 				throw new RuntimeException(e);
101 			} catch (ClassNotFoundException e) {
102 				throw new RuntimeException(e);
103 			}
104 		}
105 		try {
106 			impl.setContentType(contentType);
107 			impl.setSignedData(signatureBytes);
108 		} catch (Exception e) {
109 			throw new IOException("Unable to parse signature");
110 		}
111 	}
112 
113 	/**
114 	 * @return
115 	 */
116 	protected String getInternalClassName() {
117 		if (origin == INTERNET_EXPLORER)
118 			return "es.caib.signatura.provider.impl.common.CapicomSignatureImpl";
119 		else if (origin == MOZILLA_FIREFOX)
120 			return "es.caib.signatura.provider.impl.common.CMSSignatureImplv2";
121 		else
122 			throw new RuntimeException("Signature type unknown " + origin);
123 	}
124 
125 	/**
126 	 * Obtiene el nombre de la entidad certificadora usada en la firma
127 	 * 
128 	 * @return nombre de la entidad certificadora
129 	 */
130 	public String getCertCaName() {
131 		return impl.getCertCaName();
132 	}
133 
134 	/**
135 	 * Obtiene el nombre del certificado usado en la firma
136 	 * 
137 	 * @return nombre del certificado (CommonName)
138 	 */
139 	public String getCertSubjectCommonName() {
140 		return impl.getCertSubjectCommonName();
141 	}
142 
143 	public String getCertSubjectAlternativeNames() {
144 		return impl.getCertSubjectAlternativeNames();
145 	}
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 	public Date getDate() throws SignatureTimestampException {
161 		return impl.getDate();
162 	}
163 
164 	public boolean verify() throws SignatureVerifyException {
165 		return impl.verify();
166 	}
167 
168 	public String getContentType() {
169 		return contentType;
170 	}
171 
172 	public X509Certificate getCert() {
173 		return impl.getCert();
174 	}
175 
176 	public X509Certificate[] getCertificateChain() throws Exception {
177 		return impl.getCertificateChain();
178 	}
179 
180 	public ParsedCertificate getParsedCertificate() {
181 		return impl.getParsedCertificate();
182 	}
183 
184 	/*
185 	 * (non-Javadoc)
186 	 * 
187 	 * @see es.caib.signatura.api.Signature#verify(java.io.InputStream)
188 	 */
189 
190 	public boolean verify(InputStream contentStream)
191 			throws SignatureProviderException, IOException,
192 			SignatureVerifyException {
193 		boolean isVerified = true;
194 		try {
195 			// verificación interna de la firma
196 			isVerified = isVerified && impl.verify(contentStream);
197 			// isVerified = isVerified && verifyWS();
198 		} catch (SignatureVerifyException e) {
199 			throw e;
200 		} catch (Exception e) {
201 			throw new SignatureVerifyException(e);
202 		}
203 		return isVerified;
204 	}
205 
206 	public boolean verifyAPosterioriTimestamp(InputStream contentStream)
207 			throws SignatureProviderException, IOException,
208 			SignatureVerifyException {
209 		boolean isVerified = true;
210 		try {
211 			// verificación interna de la firma
212 			isVerified = isVerified
213 					&& impl.verifyAPosterioriTimestamp(contentStream);
214 			// *
215 			// * Se actualiza la firma por si el validador ha añadido
216 			// * un sello de tiempo
217 
218 			if (isVerified) {
219 				this.setPkcs7(impl.getPkcs7());
220 			}
221 
222 		} catch (SignatureVerifyException e) {
223 			throw e;
224 		} catch (Exception e) {
225 			throw new SignatureVerifyException(e);
226 		}
227 		return isVerified;
228 	}
229 	/*
230 	 * private boolean WSResponseIsAVerifiedMessage(String result) throws
231 	 * SignatureVerifyException { String content = new String(); try {
232 	 * DocumentBuilderFactory documentBuilderFactory =
233 	 * DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder =
234 	 * documentBuilderFactory.newDocumentBuilder(); Document document;
235 	 * StringBufferInputStream inputStream = new
236 	 * StringBufferInputStream(result); document =
237 	 * documentBuilder.parse((InputStream)inputStream); //Element element =
238 	 * document.getDocumentElement(); try{ NodeList nodeList =
239 	 * document.getElementsByTagName("valido"); Node node = nodeList.item(0);
240 	 * Element element = (Element) node; String tagName = element.getTagName();
241 	 * Node textData = null; boolean stop = false; NodeList nodeDataList =
242 	 * element.getChildNodes(); for(int i = 0;i < nodeDataList.getLength() &&
243 	 * !stop;i++){ textData = nodeDataList.item(i); stop =
244 	 * textData.getNodeType() == org.w3c.dom.Node.TEXT_NODE; } content =
245 	 * ((org.w3c.dom.Text)textData).getData(); }catch(Exception e){ //* Para no
246 	 * llevar a malos entendidos // * se da la firma como falsa // * return
247 	 * false; } if(content == null){ throw new Exception("No content in 'valido'
248 	 * TAG. Response message: " + result); } }catch(Exception e){ throw new
249 	 * SignatureVerifyException(e); } return content.compareToIgnoreCase("true") ==
250 	 * 0; }
251 	 */
252 }