View Javadoc

1   package es.caib.signatura.impl;
2   
3   import java.io.*;
4   import java.lang.reflect.Constructor;
5   import java.security.InvalidKeyException;
6   import java.security.NoSuchAlgorithmException;
7   import java.security.NoSuchProviderException;
8   import java.security.SignatureException;
9   import java.security.cert.CertificateException;
10  import java.security.cert.CertificateExpiredException;
11  import java.security.cert.CertificateNotYetValidException;
12  import java.security.cert.X509Certificate;
13  import java.util.Collection;
14  import java.util.Iterator;
15  import java.util.List;
16  
17  import es.caib.signatura.api.CertificateVerifyException;
18  import es.caib.signatura.api.ParsedCertificate;
19  import es.caib.signatura.api.SignatureProviderException;
20  import es.caib.signatura.api.SignatureVerifyException;
21  import es.caib.signatura.api.Certificate;
22  
23  /**
24   * 
25   */
26  public class CertificateImpl implements Certificate {
27  	private X509Certificate[] certificateChain = null;
28  	
29  
30  	/**
31  	 * Constructor.
32  	 * 
33  	 * @param certificateChain
34  	 */
35  	public CertificateImpl(X509Certificate[] certificateChain){
36  		this.certificateChain = certificateChain;
37  	}
38  	
39  	/**
40  	 * {@inheritDoc}
41  	 */
42  	  public String getCertCaName(){
43  		if(certificateChain == null || certificateChain.length == 0){
44  			throw new Error("The certificate chain cannot be found.");
45  		}
46  		return certificateChain[certificateChain.length-1].getSubjectX500Principal().getName();
47  	  }
48  
49  	/**
50  	 * {@inheritDoc}
51  	 */
52  	  public String getCertSubjectCommonName(){
53  		  ParsedCertificate Parsed = this.getParsedCertificate();
54  		  return(Parsed.getName());
55  	  }
56  
57  	/**
58  	 * {@inheritDoc}
59  	 */
60  	  public String getCertSubjectAlternativeNames(){
61  		  StringBuffer altNameSB = new StringBuffer("");
62  			String altNameString = null;
63  			try {
64  				Collection generalNames = certificateChain[0].getSubjectAlternativeNames();
65  				Iterator itr = generalNames.iterator();
66  				while (itr.hasNext()) {
67  					List list = (List) itr.next();
68  
69  					int tagNo = ((Integer) list.get(0)).intValue();
70  					switch (tagNo) {
71  					case 0:
72  						altNameSB.append("," + "otherName=");
73  						break;
74  
75  					case 1:
76  						altNameSB.append("," + "rfc822Name=");
77  						break;
78  
79  					case 2:
80  						altNameSB.append("," + "dNSName=");
81  						break;
82  
83  					case 3:
84  						altNameSB.append("," + "x400Address=");
85  						break;
86  
87  					case 4:
88  						altNameSB.append("," + "directoryName=");
89  						break;
90  
91  					case 5:
92  						altNameSB.append("," + "ediPartyName=");
93  						break;
94  
95  					case 6:
96  						altNameSB.append("," + "uniformResourceIdentifier=");
97  						break;
98  
99  					case 7:
100 						altNameSB.append("," + "iPAddress=");
101 						break;
102 
103 					case 8:
104 						altNameSB.append("," + "registeredID=");
105 						break;
106 
107 					}
108 					altNameSB.append(list.get(1).toString());
109 
110 					// Quitamos la coma del principio
111 					if (altNameSB.length() > 0) {
112 						altNameString = altNameSB.substring(1, altNameSB.length());
113 					}
114 
115 				}
116 			}
117 
118 			catch (Exception ex) {
119 				return null;
120 			}
121 
122 			return altNameString;
123 	  }
124 
125 
126 	/**
127 	 * {@inheritDoc}
128 	 */
129 	public X509Certificate getCert(){
130 		return certificateChain[0];
131 	}
132 	  
133 	/**
134 	 * {@inheritDoc}
135 	 */
136 	  public ParsedCertificate getParsedCertificate(){
137 		try {
138 			ClassLoader cl = ClassLoaderFactory.getFactory().getMasterClassLoader();
139 			Class clazz = cl .loadClass( "es.caib.signatura.provider.impl.common.ParsedCertificatImpl" );
140 			Constructor constructor = clazz.getConstructor(new Class[] {certificateChain.getClass(), Boolean.TYPE});
141 			ParsedCertificate parsed = (ParsedCertificate) constructor.newInstance(new Object [] {certificateChain, new Boolean(false)});
142 			return new ParsedCertificateProxy (parsed);
143 		} catch (Exception e) {
144 			throw new RuntimeException(e);
145 		}
146 	  }
147 	  
148 		/**
149 		 * {@inheritDoc}
150 		 */
151 	  	public boolean verify()
152 	            throws IOException, CertificateVerifyException{
153 	  		boolean isValid = true;
154 	  		isValid = isValid && verifyCertificateChain();
155 	  		if(!isValid){
156 	  			/*
157 	  			 * Podría darse el caso que la cadena de certificación estuviera invertida
158 	  			 */
159 	  			invertCertificateChain();
160 	  			isValid = isValid && verifyCertificateChain();
161 	  			if(!isValid){
162 	  				/*
163 	  				 * Si no es válida la cadena de certificación una vez invertida se asume
164 	  				 * que la cadena de certificación original es la válida
165 	  				 */
166 	  				invertCertificateChain();
167 	  			}
168 	  		}
169 	  		return isValid;
170 	  	}
171 	  	
172 	  	/**
173 	  	 * Method to invert the certificate chain.
174 	  	 */
175 		private void invertCertificateChain(){
176 			for(int i = 0;i < certificateChain.length / 2;i++){
177 				X509Certificate temporalCertificate = certificateChain[certificateChain.length - 1 - i];
178 				certificateChain[certificateChain.length - 1 - i] = certificateChain[i];
179 				certificateChain[i] = temporalCertificate;
180 			}
181 		}
182 		
183 	  /**
184 	   * Verifies the certificate and its certificate chain.
185 	   */
186 	  	private boolean verifyCertificateChain()
187 	            throws IOException, CertificateVerifyException{
188 	  		boolean isValid = true;
189 	  		/*
190 	  		 * date validity verification
191 	  		 */
192 	  		for(int i = 0;i < certificateChain.length && isValid;i++){
193 	  			try {
194 	  				certificateChain[i].checkValidity();
195 	  			
196 	  			} catch (CertificateExpiredException cee) {
197 	  				System.out.println("CMSSignature Certificat rebutjat, el certificat ha caducat.");
198 		  				isValid = false;
199 	  			} catch (CertificateNotYetValidException cve) {
200 	  				System.out.println("CMSSignature Certificat rebutjat, el certificat encara no és vàlid.");
201 	  				isValid = false;
202 	  			}
203 	  		}	  		
204 	  		/*
205 	  		 * signature validity verification
206 	  		 */
207 	  		for(int i = 0;(i < certificateChain.length - 1) && isValid;i++){	  			
208 	  				try {
209 						certificateChain[i].verify(certificateChain[i + 1].getPublicKey());
210 					} catch (InvalidKeyException e) {
211 						isValid = false;
212 					} catch (CertificateException e) {
213 						isValid = false;
214 					} catch (NoSuchAlgorithmException e) {
215 						throw new CertificateVerifyException(e);
216 					} catch (NoSuchProviderException e) {
217 						throw new CertificateVerifyException(e);
218 					} catch (SignatureException e) {
219 						isValid = false;
220 					}	  			
221 	  		}
222 	  		/*
223 	  		 * Root certificate verification through Web Services.
224 	  		 */
225 	  		try{
226 	  			isValid = isValid && verifyCertificateWebServices(certificateChain);
227 	  		}catch(Exception e){
228 	  			throw new CertificateVerifyException(e);
229 	  		}
230 	  		return isValid;
231 	  	}
232 	  	
233 	  	/*
234 	  	 * Validation through web services of the certificate chain.
235 	  	 */
236 	  	private boolean verifyCertificateWebServices(X509Certificate[] certificateChain)throws CertificateVerifyException{
237 	  		/* TODO: commons-logging*/
238 	  		return true;
239 	  		/*
240 	  		String result = verifyWebServices(certificateChain);
241   			return WSResponseIsAVerifiedMessage(result);
242   			*/
243 	  	}
244 	  	
245 		/*
246 		 * Validación mediante Web Services de la cadena de certificación
247 		 */
248 	  	/*
249 		private String verifyWebServices(X509Certificate[] certificateChain) throws CertificateVerifyException{
250 			String toReturn = new String();
251 			try{
252 				URLClassLoader urlClassLoader = (URLClassLoader)ClassLoaderFactory.getFactory().getMasterClassLoader();
253 				Class c;			
254 				c = urlClassLoader.loadClass("es.caib.signatura.cliente.ValidadorCertificadosEmbedded");						
255 				Constructor constructor = c.getConstructor(new Class [] {});
256 				IValidadorCertificados iValidadorCertificados = (IValidadorCertificados)constructor.newInstance(new Object [] {});
257 				//ValidadorCertificadosEmbedded validadorCertificados = new ValidadorCertificadosEmbedded();
258 				toReturn = iValidadorCertificados.validarCertificadoParaFirma(certificateChain);
259 			} catch (Exception e) {
260 				throw new CertificateVerifyException(e);
261 			}
262 			return toReturn;
263 		}
264 	  	
265 		private boolean WSResponseIsAVerifiedMessage(String result) throws CertificateVerifyException {
266 			String content = new String();
267 			try {
268 				DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
269 				DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
270 				Document document;	    	  
271 				StringBufferInputStream inputStream = new StringBufferInputStream(result);
272 				document = documentBuilder.parse((InputStream)inputStream);	    	  
273 				//Element element = document.getDocumentElement();
274 				try{
275 					NodeList nodeList = document.getElementsByTagName("validado");
276 					Node node = nodeList.item(0);
277 					Element element = (Element) node;
278 					String tagName = element.getTagName();
279 					Node textData = null;
280 					boolean stop = false;
281 					NodeList nodeDataList = element.getChildNodes();				
282 					for(int i = 0;i < nodeDataList.getLength() && !stop;i++){
283 						textData = nodeDataList.item(i);
284 						stop = textData.getNodeType() == org.w3c.dom.Node.TEXT_NODE;						
285 					}
286 					content = ((org.w3c.dom.Text)textData).getData();
287 				}catch(Exception e){
288 					// Para no llevar a malos entendidos
289 					// se da la firma como falsa
290 					// 
291 					return false;
292 				}
293 				if(content == null){
294 					throw new Exception("No content in 'validado' TAG. Response message: " + result);
295 				}
296 			}catch(Exception e){
297 				throw new CertificateVerifyException(e);
298 			}
299 			return content.compareToIgnoreCase("true") == 0;
300 		}
301 	  	*/
302 
303 }