View Javadoc

1   /***
2    * 
3    */
4   package de.cohesion.bssh.impl;
5   
6   import java.io.File;
7   import java.io.FileInputStream;
8   import java.io.FileOutputStream;
9   import java.io.IOException;
10  import java.io.ObjectInputStream;
11  import java.io.ObjectOutputStream;
12  import java.security.Provider;
13  import java.security.Security;
14  import java.util.Iterator;
15  
16  import javax.crypto.Cipher;
17  import javax.crypto.SealedObject;
18  import javax.crypto.SecretKey;
19  import javax.crypto.SecretKeyFactory;
20  import javax.crypto.spec.PBEKeySpec;
21  import javax.crypto.spec.PBEParameterSpec;
22  
23  import de.cohesion.bssh.Member;
24  import de.cohesion.bssh.PasswordStore;
25  
26  /***
27   * @author schulzs
28   */
29  public class PBEPasswordStore implements PasswordStore {
30  
31  	private enum Ciphers {
32  		ENCRYPT(Cipher.ENCRYPT_MODE), DECRYPT(Cipher.DECRYPT_MODE);
33  
34  		private static final String CIPHER_ALGORITHM_NAME = "PBEWithMD5AndDES";
35  
36  		private static final byte[] SALT = { (byte) 0xc7, (byte) 0x73,
37  				(byte) 0x21, (byte) 0x8c, (byte) 0x7e, (byte) 0xc8,
38  				(byte) 0xee, (byte) 0x99 };
39  
40  		private static final int ITERATIONS = 20;
41  
42  		private static final PBEParameterSpec PARAM_SPEC = new PBEParameterSpec(
43  				SALT, ITERATIONS);
44  
45  		private int opMode;
46  
47  		Ciphers(int opMode) {
48  			this.opMode = opMode;
49  		}
50  
51  		public Cipher get(final char[] passphrase) throws Exception {
52  			Cipher c = Cipher.getInstance(CIPHER_ALGORITHM_NAME, "SunJCE");
53  			c.init(opMode, this.getKey(passphrase), PARAM_SPEC);
54  			return c;
55  		}
56  
57  		private SecretKey getKey(final char[] passphrase) throws Exception {
58  			SecretKeyFactory factory = SecretKeyFactory
59  					.getInstance(CIPHER_ALGORITHM_NAME);
60  			return factory.generateSecret(new PBEKeySpec(passphrase));
61  		}
62  
63  	}
64  
65  	private static void dumpProviders() {
66  		try {
67  			Provider[] providers = Security.getProviders();
68  			for (Provider p : providers) {
69  				System.out.println("Provider: " + p.getName() + ", "
70  						+ p.getInfo());
71  				for (Iterator itr = p.keySet().iterator(); itr.hasNext();) {
72  					String key = (String) itr.next();
73  					String value = (String) p.get(key);
74  					System.out.println("\t" + key + " = " + value);
75  				}
76  			}
77  		} catch (Exception e) {
78  			e.printStackTrace();
79  		}
80  	}
81  
82  	private final File root;
83  
84  	private final char[] passphrase;
85  
86  	public PBEPasswordStore(final File root, final char[] passphrase)
87  			throws IOException {
88  		this.root = root;
89  		this.passphrase = passphrase;
90  	}
91  
92  	private File getPasswordFile(final Member member) throws IOException {
93  		File f = new File(root.getAbsolutePath() + File.separator
94  				+ member.getUserName() + File.separator
95  				+ member.getHost().toString().replace('/', '-') + "-"
96  				+ member.getPort());
97  		if (!f.exists()) {
98  			boolean success = f.mkdirs();
99  			if (!success) {
100 				throw new IOException("could not create directory structure");
101 			}
102 		}
103 		return f;
104 	}
105 
106 	public char[] getPassword(final Member member) throws IOException {
107 		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(this
108 				.getPasswordFile(member)));
109 		String result = null;
110 		try {
111 			SealedObject so = (SealedObject) ois.readObject();
112 			result = (String) so.getObject(Ciphers.DECRYPT.get(passphrase));
113 		} catch (Exception e) {
114 			IOException ioe = new IOException(
115 					"opening sealed password file failed");
116 			ioe.initCause(e);
117 			throw ioe;
118 		} finally {
119 			ois.close();
120 		}
121 
122 		return result.toCharArray();
123 	}
124 
125 	public void store(final Member member, char[] password) throws IOException {
126 		File f = this.getPasswordFile(member);
127 		if (f.exists()) {
128 			boolean success = f.delete();
129 			if (!success) {
130 				throw new IOException(
131 						"file already exists and could not be deleted");
132 			}
133 		}
134 		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
135 		try {
136 			SealedObject so = new SealedObject(new String(password),
137 					Ciphers.ENCRYPT.get(passphrase));
138 			oos.writeObject(so);
139 		} catch (Exception e) {
140 			IOException ioe = new IOException(
141 					"storing sealed password file failed");
142 			ioe.initCause(e);
143 			throw ioe;
144 		} finally {
145 			oos.close();
146 		}
147 	}
148 
149 }