1 package com.sslexplorer.security; 2 3 import java.io.ByteArrayInputStream ; 4 import java.io.ByteArrayOutputStream ; 5 import java.io.IOException ; 6 import java.io.OutputStream ; 7 import java.util.HashMap ; 8 import java.util.StringTokenizer ; 9 10 import javax.crypto.Cipher; 11 12 import org.apache.commons.logging.Log; 13 import org.apache.commons.logging.LogFactory; 14 15 import sun.awt.image.ByteArrayImageSource; 16 17 import com.maverick.crypto.encoders.Base64; 18 import com.sslexplorer.boot.RepositoryFactory; 19 import com.sslexplorer.boot.RepositoryStore; 20 import com.sslexplorer.boot.Util; 21 import com.sslexplorer.properties.Property; 22 import com.sslexplorer.properties.impl.systemconfig.SystemConfigKey; 23 import com.sslexplorer.security.pki.InvalidKeyException; 24 import com.sslexplorer.security.pki.SshKeyGenerator; 25 import com.sslexplorer.security.pki.SshPrivateKey; 26 import com.sslexplorer.security.pki.SshPrivateKeyFile; 27 import com.sslexplorer.security.pki.SshPublicKey; 28 import com.sslexplorer.security.pki.SshPublicKeyFile; 29 30 35 public class PublicKeyStore { 36 37 private static PublicKeyStore instance; 38 39 static Log log = LogFactory.getLog(PublicKeyStore.class); 40 41 HashMap loadedPrivateKeys = new HashMap (); 42 HashMap loadedPublicKeys = new HashMap (); 43 RepositoryStore store; 44 45 String keyType = "rsa"; 46 int bitLength = 1024; 47 48 public static PublicKeyStore getInstance() { 49 return instance==null ? instance = new PublicKeyStore() : instance; 50 } 51 52 PublicKeyStore() { 53 store = RepositoryFactory.getRepository().getStore("PKI"); 54 55 try { 56 keyType = Property.getProperty(new SystemConfigKey("pki.algorithm")); 57 bitLength = Property.getPropertyInt(new SystemConfigKey("pki.bitLength")); 58 } catch (Exception e) { 59 log.error("Could not get PKI properties! defaults will be used"); 60 keyType = "rsa"; 61 bitLength = 1024; 62 } 63 } 64 65 76 public void verifyPrivateKey(String username, char[] pw) throws PromptForPasswordException, FatalKeyException, UpdatePrivateKeyPassphraseException { 77 78 79 if(!PublicKeyStore.getInstance().hasPrivateKey(username)) { 80 81 if(pw==null) { 82 83 87 throw new PromptForPasswordException(); 88 } 89 90 try { 91 94 getPrivateKey(username, new String (pw)); 95 } catch (Exception e) { 96 log.error("Error creating users private key", e); 97 98 102 throw new FatalKeyException(); 103 } 104 } 105 106 110 if(!PublicKeyStore.getInstance().hasLoadedKey(username)) { 111 112 if(pw==null) { 113 114 125 throw new PromptForPasswordException(); 126 127 } else { 128 129 if(!PublicKeyStore.getInstance().hasPassphraseChanged(username, new String (pw))) 130 throw new UpdatePrivateKeyPassphraseException(); 131 132 try { 133 PublicKeyStore.getInstance().getPrivateKey(username, new String (pw)); 134 } catch (IOException e) { 135 log.error("Error loading users private key", e); 136 throw new FatalKeyException(); 137 138 } catch (InvalidKeyException e) { 139 throw new UpdatePrivateKeyPassphraseException(); 140 } 141 } 142 } 143 } 144 145 152 public void changePrivateKeyPassphrase(String username, String oldPassphrase, String newPassphrase) throws FatalKeyException { 153 154 155 try { 156 changePassphrase(username, oldPassphrase, newPassphrase); 157 } catch (Exception e) { 158 log.error("Error changing users private key passphrase", e); 159 throw new FatalKeyException(); 160 } 161 162 } 163 164 171 public String encryptText(String text, String username) throws FatalKeyException { 172 173 try { 174 175 String cipherText = ""; 176 177 178 byte[] plainText = text.getBytes(); 179 180 for(int i=0;i<plainText.length;i+=117) { 181 SshPublicKey pk = getPublicKey(username); 182 183 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 184 185 cipher.init(Cipher.ENCRYPT_MODE, pk.getPublicKey()); 186 187 byte[] ctext = cipher.doFinal(plainText, i, (plainText.length - i > 117 ? 117 : plainText.length - i)); 188 189 String section = new String (Base64.encode(ctext), "US-ASCII"); 190 cipherText += section + "\n"; 191 192 193 194 } 195 196 197 return cipherText; 198 199 } catch (Exception e) { 200 log.error("Error encrpyting data", e); 201 throw new FatalKeyException(); 202 } 203 } 204 205 213 public String decryptText(String text, String username) throws FatalKeyException, PrivateKeyNotInitializedException { 214 215 if(!hasLoadedKey(username)) 216 throw new PrivateKeyNotInitializedException(); 217 218 try { 219 SshPrivateKey pk = (SshPrivateKey) loadedPrivateKeys.get(username); 220 221 222 StringTokenizer blocks = new StringTokenizer (text, "\n"); 223 224 String plainText = ""; 225 226 227 while(blocks.hasMoreTokens()) { 228 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 229 230 cipher.init(Cipher.DECRYPT_MODE, pk.getPrivateKey()); 231 232 byte[] encrypted = Base64.decode(blocks.nextToken()); 233 byte[] ctext = cipher.doFinal(encrypted); 234 235 plainText += new String (ctext); 236 } 237 238 239 return plainText; 240 241 } catch (Exception e) { 242 log.error("Error decrypting cipher text", e); 243 throw new FatalKeyException(); 244 } 245 } 246 247 248 256 protected SshPrivateKey getPrivateKey(String username, String passphrase) throws IOException , InvalidKeyException { 257 258 if(loadedPrivateKeys.containsKey(username)) 259 return (SshPrivateKey) loadedPrivateKeys.get(username); 260 261 SshPrivateKey pk = getPrivateKeyFromStore(username, passphrase); 262 263 loadedPrivateKeys.put(username, pk); 264 265 return pk; 266 267 } 268 269 275 public void removeCachedKeys(String username) { 276 loadedPrivateKeys.remove(username); 277 loadedPublicKeys.remove(username); 278 } 279 280 285 public void removeKeys(String username) { 286 removeCachedKeys(username); 287 String filename = username + ".prv"; 288 if(store.hasEntry(filename)) { 289 try { 290 store.removeEntry(filename); 291 } catch (IOException e) { 292 log.error("Failed to remove private key for " + username + ".", e); 293 } 294 } 295 filename = username + ".pub"; 296 if(store.hasEntry(filename)) { 297 try { 298 store.removeEntry(filename); 299 } catch (IOException e) { 300 log.error("Failed to remove public key for " + username + ".", e); 301 } 302 } 303 } 304 305 313 protected SshPrivateKey getPrivateKeyFromStore(String username, String passphrase) throws IOException , InvalidKeyException { 314 315 String filename = username + ".prv"; 316 317 if (!store.hasEntry(filename)) { 318 generateKey(username, keyType, bitLength, passphrase); 319 } 320 321 SshPrivateKeyFile f = SshPrivateKeyFile.parse(store.getEntryInputStream(filename)); 322 323 return f.toPrivateKey(passphrase); 324 325 } 326 327 332 public boolean hasPrivateKey(String username) { 333 return store.hasEntry(username + ".prv"); 334 } 335 336 341 public boolean hasLoadedKey(String username) { 342 return loadedPrivateKeys.containsKey(username); 343 } 344 345 351 public boolean hasPassphraseChanged(String username, String passphrase) { 352 353 try { 354 getPrivateKeyFromStore(username, passphrase); 355 return true; 356 357 } catch (IOException e) { 358 return false; 359 } catch (InvalidKeyException e) { 360 return false; 361 } 362 } 363 364 371 protected SshPublicKey getPublicKey(String username) throws IOException , InvalidKeyException { 372 373 if(loadedPublicKeys.containsKey(username)) 374 return (SshPublicKey) loadedPublicKeys.get(username); 375 376 String filename = username + ".pub"; 377 378 if(store.hasEntry(filename)) { 379 SshPublicKeyFile f = SshPublicKeyFile.parse(store.getEntryInputStream(filename)); 380 SshPublicKey pk = f.toPublicKey(); 381 loadedPublicKeys.put(username, pk); 382 return pk; 383 } 384 else 385 throw new IOException ("User does not have a key in the repository!"); 386 } 387 388 protected void changePassphrase(String username, String oldPassphrase, String newPassphrase) throws IOException , InvalidKeyException, PromptForPasswordException, FatalKeyException, UpdatePrivateKeyPassphraseException { 389 String filename = username + ".prv"; 390 if(store.hasEntry(filename)) { 391 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 392 SshKeyGenerator.changePassphrase(store.getEntryInputStream(filename), baos, oldPassphrase, newPassphrase); 393 394 400 OutputStream out = store.getEntryOutputStream(filename); 401 out.write(baos.toByteArray()); 402 out.flush(); 403 Util.closeStream(out); 404 } else 405 throw new IOException ("User does not have a key in the repository!"); 406 } 407 408 protected void generateKey(String username, String type, int bitlength, String passphrase) throws IOException , InvalidKeyException { 409 410 SshKeyGenerator.generateKeyPair(type, bitlength, username, passphrase, store.getEntryOutputStream(username + ".prv"), 411 store.getEntryOutputStream(username + ".pub")); 412 } 413 414 } 415 | Popular Tags |