View Javadoc

1   package org.eparapher.core.crypto.keystore;
2   
3   import java.security.KeyStore;
4   import java.security.KeyStoreException;
5   import java.security.NoSuchAlgorithmException;
6   import java.security.PrivateKey;
7   import java.security.PublicKey;
8   import java.security.UnrecoverableKeyException;
9   import java.security.cert.Certificate;
10  import java.security.cert.TrustAnchor;
11  import java.security.cert.X509Certificate;
12  import java.util.ArrayList;
13  import java.util.Collections;
14  import java.util.Enumeration;
15  import java.util.Iterator;
16  import java.util.List;
17  import java.util.Set;
18  
19  import org.apache.log4j.Logger;
20  import org.eparapher.core.EParapherManager;
21  import org.eparapher.core.crypto.EPKeystoreManager;
22  import org.eparapher.core.crypto.KeystoreEntry;
23  import org.eparapher.core.crypto.cert.X509Util;
24  
25  
26  public abstract class GenericKeystore implements IUserKeystore {
27  
28  	private static Logger log = Logger.getLogger(GenericKeystore.class);
29  	
30  	protected PrivateKey currentPrivateKey;
31  	protected PublicKey  currentPublicKey;
32  	
33  	protected X509Certificate   currentX509Certificate;
34  	protected X509Certificate[] currentX509CertificateChain;
35  
36  	protected String  currentalias;
37  	protected boolean currentaliasselected;
38  	
39  	protected KeyStore ks;
40  	protected boolean loadedKeystore;
41  	
42  	public boolean isKeystoreLoaded() {
43  		if (ks!=null)
44  			if (loadedKeystore)
45  				return true;
46  		return false;
47  	}
48  
49  	protected GenericKeystore(){
50  		this.loadedKeystore=false;
51  		this.currentaliasselected = false;
52  	}
53  	
54  	public KeystoreEntry[] getKeystoreEntries() {
55  		
56  		ArrayList<KeystoreEntry> certificatelist = new ArrayList<KeystoreEntry>();
57  		if (isKeystoreLoaded()) {
58  			try {
59  				List<String> list = Collections.list(ks.aliases());
60  				for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
61  					//TODO : IBM PKCS11 Implementation is really strange here
62  					String alias = (String) iterator.next();
63  					X509Certificate[] currentCertChain = null;
64  					if (ks.getCertificateChain(alias)!=null)
65  						currentCertChain = X509Util.convertCertChaintoX509( ks.getCertificateChain(alias) );
66  					else if (ks.getCertificate(alias)!=null)
67  						currentCertChain = X509Util.convertCertChaintoX509( new Certificate[] {ks.getCertificate(alias)} );
68  					if ( isX509validatedByFilter(currentCertChain) )
69  						certificatelist.add( new KeystoreEntry( alias, currentCertChain, this ) );
70  				}
71  				
72  				return certificatelist.toArray(new KeystoreEntry[]{});
73  			} catch (KeyStoreException kse) {
74  				log.error("Error on reading keystore alias cert chain : " + kse.getMessage());
75  				return null;
76  			} catch (Exception e) {
77  				log.error("Error on getting alias cert chain : " + e.getMessage());
78  				return null;
79  			}
80  		}
81  		else {
82  			if (EPKeystoreManager.isPKCS11Used())
83  				log.info("Token not present!!!");
84  			else
85  				log.info("Keystore not loaded!");
86  		}
87  		return null;
88  	}
89  
90  	public KeystoreEntry[] getTrustedCertificates() {
91  		
92  		KeystoreEntry[] certificatelist = null;
93  		if (isKeystoreLoaded()) {
94  			try {
95  				int size = 0;
96  				Enumeration<String> en = ks.aliases();
97  				while (en.hasMoreElements())
98  					// Must have a private key
99  					if ( ks.isCertificateEntry((String) en.nextElement()) )
100 						size++;
101 
102 				certificatelist = new KeystoreEntry[size];
103 				int index=0;
104 				List<String> list = Collections.list(ks.aliases());
105 				Collections.sort(list);
106 				for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
107 					String alias = (String) iterator.next();
108 					if ( ks.isCertificateEntry(alias) ) {
109 						X509Certificate currentCert = (X509Certificate) ks.getCertificate(alias);
110 						certificatelist[index++] = new KeystoreEntry( alias, currentCert, this );
111 					} else if (ks.isKeyEntry(alias))
112 						log.debug("Found a key entry in the truststore!");
113 				}
114 				
115 				return certificatelist;
116 			} catch (KeyStoreException kse) {
117 				log.error("Exception on reading aliases in truststore.",kse);
118 				return null;
119 			} catch (Exception e) {
120 				log.error("Exception on reading aliases in truststore.",e);
121 				return null;
122 			}
123 		}
124 		else {
125 			if (EPKeystoreManager.isPKCS11Used())
126 				log.info("Token not present!!!");
127 			else
128 				log.info("Keystore not loaded!");
129 		}
130 		return null;
131 	}
132 	
133 	private boolean isX509validatedByFilter(X509Certificate[] currentCertChain) {
134 		// TODO Implement a certificate filter
135 		return true;
136 	}
137 
138 	/** Load Public key and certificate on the selected/default alias
139 	 * 
140 	 * @return true if public key and X509 certificate(s) loaded
141 	 */
142 	public boolean loadPublicInformation() {
143 
144 		//Select an alias or cancel
145 		if (!selectAlias())
146 			return false;
147 		
148 		// Load Public Information : Certificates
149 		try {
150 			currentX509Certificate      = (X509Certificate) ks.getCertificate(currentalias);
151 			currentX509CertificateChain = X509Util.convertCertChaintoX509(ks.getCertificateChain(currentalias));
152 			if (currentX509CertificateChain == null) 
153 				currentX509CertificateChain = new X509Certificate[] {currentX509Certificate};
154 			//TODO : rebuild certificate path from trust store
155 			return true;
156 		} catch (KeyStoreException e) {
157 			log.error("Certificate not accessible : "  + e.getLocalizedMessage(),e);
158 		}
159 		return false;
160 	}
161 	/**
162 	 * 
163 	 * @param ALIAS
164 	 * @param PINorPWD
165 	 * @return
166 	 */
167 	public boolean loadPrivateKey(String secret) {
168 		if ( isKeystoreLoaded() ) {
169 			
170 			if (loadPublicInformation()) {
171 
172 				//Load private information
173 				try {
174 					if ( secret != null )
175 						currentPrivateKey = (PrivateKey) ks.getKey( currentalias, secret.toCharArray() );
176 					else
177 						currentPrivateKey = (PrivateKey) ks.getKey( currentalias, null );
178 					log.info("Using certificate " + currentX509Certificate.getSubjectDN() + " for signing");
179 					if (currentPrivateKey != null)
180 						return true;
181 				} catch (KeyStoreException e) {
182 					log.error("Private key not accessible : "  + e.getLocalizedMessage());
183 				} catch (NoSuchAlgorithmException e) {
184 					log.error("Private key not accessible : "  + e.getLocalizedMessage());
185 				} catch (UnrecoverableKeyException e) {
186 					log.error("Private key not accessible : "  + e.getLocalizedMessage());
187 				}
188 			}
189 		}
190 		return false;
191 	}
192 	
193 	protected boolean selectAlias() {
194 		boolean aliasExists = false;
195 		if (currentaliasselected)
196 			return true;
197 		if ( isKeystoreLoaded() ) {
198 			//Get alias from config
199 			currentalias = EParapherManager.getInstance().getSettings().getPersonalStoreDefaultAlias();
200 			
201 			//Search if the alias exists in keystore
202 			try {
203 				aliasExists = ks.containsAlias(currentalias);
204 			} catch (KeyStoreException e) {
205 				log.error("error on verifying alias in keystore",e);
206 			}
207 
208 			if ( currentalias.equals("")  ) {
209 				log.info("Alias not set in conf : search for the first 'usable' certificate");
210 				return autoSelectAlias();
211 			} else if (!aliasExists) {
212 				log.info("Alias not found in keystore : search for the first 'usable' certificate");
213 				return autoSelectAlias();
214 			} else {
215 				currentaliasselected = true;
216 				log.info("Using stored alias : '"+currentalias+"'");
217 			}
218 		}
219 		else log.warn("Private Key not loaded : cannot find a usable alias!");
220 		
221 		return aliasExists;
222 	}
223 	
224 	protected boolean autoSelectAlias() {
225 		Enumeration<String> en;
226 		boolean found = false;
227 		try {
228 			//FIXME : Prompt user to select a certificate
229 			en = ks.aliases();
230 			while (en.hasMoreElements()) {
231 				String alias = (String) en.nextElement();
232 				if ( ks.isKeyEntry(alias) ) {
233 					// TODO : verify certificate through certificatefilter
234 					currentalias = alias;
235 					found = true;
236 				}
237 			}
238 			if (found)
239 				log.info("     -> Using alias '" + currentalias +"'");
240 		} catch (KeyStoreException e) {
241 			String msg = "Error while parsing Keystore..." + e.getLocalizedMessage();
242 			EParapherManager.getInstance().getUI().errorMessage(msg,e);
243 			log.error(msg, e);
244 		}
245 		if (!found) {
246 			String message = "Couldn't find a usable alias in your keystore\r\n";
247 			message += "Do you want to create a self signed certificate?";
248 			if (EParapherManager.getInstance().getUI().askUserYesNo(message)) {
249 				found = newcertificate();
250 			}
251 		}
252 		currentaliasselected = found;
253 		return found;
254 	}
255 
256 	public boolean setDefaultAlias(String alias) {
257 		if (currentalias != alias) {
258 			currentalias = alias;
259 			EParapherManager.getInstance().getSettings().setPersonalStoreDefaultAlias(alias);
260 			loadPublicInformation();
261 			currentaliasselected = true;
262 			currentPrivateKey = null;
263 		}
264 		return true;
265 	}
266 
267 	public String getDefaultAlias() {
268 		return currentalias;
269 	}
270 
271 	/** Return true if alias already define in the keystore
272 	 */
273 	public boolean containsAlias(String alias){
274         //Verify if the alias already exists
275 		if (ks!=null) {
276 			try {
277 				if (ks.containsAlias(alias))
278 					return true;
279 			} catch (KeyStoreException e) {
280 				String msg = "No such algorithm with your provider " ;
281 				log.error(msg, e);
282 			}
283 		}
284 		return false;
285 	}
286 	public PrivateKey getPrivateKey() {
287 		return currentPrivateKey;
288 	}
289 	public PublicKey getPublicKey() {
290 		if (!loadedKeystore)
291 			loadKeyStore();
292 		if (currentaliasselected && currentPublicKey == null)
293 			loadPublicInformation();
294 		return currentPublicKey;
295 	}
296 	public X509Certificate getX509Certificate() {
297 		if (!loadedKeystore)
298 			loadKeyStore();
299 		if (currentaliasselected && currentX509Certificate == null)
300 			loadPublicInformation();
301 		return currentX509Certificate;
302 	}
303 	public X509Certificate[] getX509CertificateChain() {
304 		if (!loadedKeystore)
305 			loadKeyStore();
306 		if (currentaliasselected && currentX509Certificate == null)
307 			loadPublicInformation();
308 		return currentX509CertificateChain;
309 	}	
310 	public String getProviderName() {
311 		return ks.getProvider().getName();
312 	}	
313 	public KeyStore getKeystore() {
314 		//if (!this.loadedKeystore)
315 		//	this.loadKeyStore();
316 		return ks;
317 	}
318 	
319 	public boolean newcertificate() {
320 		return EParapherManager.getInstance().getUI().askUserNewCertificate();
321 	}
322 	
323 	public Set<TrustAnchor> getTrustAnchors() {
324 		//TODO : Implement getTrustAnchors
325 		log.warn("Need to implement getTrustAnchors");
326 		return null;
327 	}
328 
329 }