123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- /*
- * Copyright (c) 2006-2007 Chris Smith, Shane Mc Cormack, Gregory Holmes
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
- package uk.org.ownage.dmdirc;
-
- import java.io.IOException;
- import java.io.UnsupportedEncodingException;
- import java.security.MessageDigest;
- import java.security.NoSuchAlgorithmException;
- import java.security.spec.AlgorithmParameterSpec;
- import java.security.spec.KeySpec;
-
- import javax.crypto.Cipher;
- import javax.crypto.IllegalBlockSizeException;
- import javax.crypto.SecretKey;
- import javax.crypto.SecretKeyFactory;
- import javax.crypto.spec.PBEKeySpec;
- import javax.crypto.spec.PBEParameterSpec;
- import javax.swing.JOptionPane;
-
- import uk.org.ownage.dmdirc.logger.ErrorLevel;
- import uk.org.ownage.dmdirc.logger.Logger;
-
- /**
- * Helper class to encrypt and decrypt strings, requests passwords if needed.
- */
- public final class CipherUtils {
- /**
- * Encryption cipher.
- */
- private static Cipher ecipher;
-
- /**
- * Decryption cipher.
- */
- private static Cipher dcipher;
-
- /**
- * Salt.
- */
- private static final byte[] SALT = {
- (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
- (byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03,
- };
-
- /**
- * Iteration count.
- */
- private static final int ITERATIONS = 19;
-
- /**
- * number of auth attemps before failing the attempt.
- */
- private static final int AUTH_TRIES = 4;
-
- /**
- * User password.
- */
- private static String password;
-
- /**
- * Prevents creation of a new instance of Encipher.
- */
- private CipherUtils() {
- }
-
- /**
- * Encrypts a string using the stored settings. Will return null if the
- * automatic user authentication fails - use checkauth and auth.
- * @param str String to encrypt
- * @return Encrypted string
- */
- public static String encrypt(final String str) {
- if (!checkAuthed()) {
- if (auth()) {
- createCiphers();
- } else {
- return null;
- }
- }
- try {
- return new String(ecipher.doFinal(str.getBytes("UTF8")));
- } catch (javax.crypto.BadPaddingException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to decrypt string", e);
- } catch (IllegalBlockSizeException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to decrypt string", e);
- } catch (UnsupportedEncodingException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to decrypt string", e);
- } catch (java.io.IOException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to decrypt string", e);
- }
- return null;
- }
-
- /**
- * Encrypts a string using the stored settings. Will return null if the
- * automatic user authentication fails - use checkauth and auth.
- * @param str String to decrypt
- * @return Decrypted string
- */
- public static String decrypt(final String str) {
- if (!checkAuthed()) {
- if (auth()) {
- createCiphers();
- } else {
- return null;
- }
- }
- try {
- return new String(dcipher.doFinal(str.getBytes()), "UTF8");
- } catch (javax.crypto.BadPaddingException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to decrypt string", e);
- } catch (IllegalBlockSizeException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to decrypt string", e);
- } catch (UnsupportedEncodingException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to decrypt string", e);
- } catch (java.io.IOException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to decrypt string", e);
- }
- return null;
- }
-
- /**
- * Performs a SHA-512 hash.
- * @param data String to hashed
- * @return hashed string
- */
- public static String hash(final String data) {
- try {
- return new String(MessageDigest.getInstance("SHA-512")
- .digest(data.getBytes("UTF8")));
- } catch (NoSuchAlgorithmException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to hash string", e);
- } catch (IOException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to hash string", e);
- }
- return null;
- }
-
- /**
- * Checks if a user is authed.
- *
- * @return true if authed, false otherwise
- */
- public static boolean checkAuthed() {
- if (dcipher != null && ecipher != null) {
- return true;
- }
- return false;
- }
-
- /**
- * creates ciphers.
- */
- private static void createCiphers() {
- try {
- final KeySpec keySpec = new PBEKeySpec(
- password.toCharArray(), SALT, ITERATIONS);
- final SecretKey key = SecretKeyFactory.
- getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
- ecipher = Cipher.getInstance(key.getAlgorithm());
- dcipher = Cipher.getInstance(key.getAlgorithm());
- final AlgorithmParameterSpec paramSpec =
- new PBEParameterSpec(SALT, ITERATIONS);
- ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
- dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
- } catch (java.security.InvalidAlgorithmParameterException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to create ciphers", e);
- ecipher = null;
- dcipher = null;
- } catch (java.security.spec.InvalidKeySpecException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to create ciphers", e);
- ecipher = null;
- dcipher = null;
- } catch (javax.crypto.NoSuchPaddingException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to create ciphers", e);
- ecipher = null;
- dcipher = null;
- } catch (java.security.NoSuchAlgorithmException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to create ciphers", e);
- ecipher = null;
- dcipher = null;
- } catch (java.security.InvalidKeyException e) {
- Logger.error(ErrorLevel.WARNING, "Unable to create ciphers", e);
- ecipher = null;
- dcipher = null;
- }
- }
-
- /**
- * Auths a user and sets the password.
- *
- * @return true if auth was successful, false otherwise.
- */
- public static boolean auth() {
- String passwordHash = null;
- String prompt = "Please enter your password";
- int tries = 1;
- if (Config.hasOption("encryption", "password")) {
- password = Config.getOption("encryption", "password");
- } else {
- if (Config.hasOption("encryption", "passwordHash")) {
- passwordHash = Config.getOption("encryption", "passwordHash");
- }
- passwordHash = "moo";
- while ((password == null || password.length() == 0) && tries < AUTH_TRIES) {
- password = JOptionPane.showInputDialog(prompt);
- if (passwordHash == null) {
- passwordHash = hash(password);
- Config.setOption("encryption", "passwordHash", passwordHash);
- Config.save();
- }
- if (!hash(password).equals(passwordHash)) {
- prompt = "<html>Password mis-match<br>Please re-enter "
- + "your password</html>";
- tries++;
- password = null;
- }
- }
- }
- if (tries == AUTH_TRIES) {
- return false;
- }
- return true;
- }
- }
|