/* Copyright (C) 2016 maik.jablonski@jease.org This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package jfix.util; import java.security.MessageDigest; import java.security.spec.KeySpec; import java.util.ArrayList; import java.util.Base64; import java.util.Collections; import java.util.List; import java.util.Random; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; /** * Common utility methods to encrypt/decrypt numbers and strings. */ public class Crypts { private static final char[] HEX_CHARACTERS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; /** * Creates a strong password with given length which contains lower and * upercase letters, digits and symbols. */ public static String generatePassword(int length) { final String alpha = "abcdefghijklmnopqrstuvwxyz"; final String digits = "0123456789"; final String symbols = "!$%&/()*+#-_.:,;<>"; final Random random = new Random(); List<Character> password = new ArrayList<Character>(); for (int i = 0; i < length; i++) { password.add(alpha.charAt(random.nextInt(alpha.length()))); password.add(alpha.toUpperCase().charAt( random.nextInt(alpha.length()))); password.add(digits.charAt(random.nextInt(digits.length()))); password.add(symbols.charAt(random.nextInt(symbols.length()))); } String result = ""; while (!isStrongPassword(result)) { Collections.shuffle(password); StringBuilder sb = new StringBuilder(); for (Character c : password) { sb.append(c); } result = sb.toString().substring(0, length); } return result; } /** * Returns true if password is at least 8 characters and contains lower and * uppercase letters, digits and symbols. */ public static boolean isStrongPassword(String password) { if (password == null || password.length() < 8) { return false; } if (!password.matches(".*[a-z]+.*")) { return false; } if (!password.matches(".*[A-Z]+.*")) { return false; } if (!password.matches(".*[\\d]+.*")) { return false; } if (!password.matches(".*[^a-zA-Z\\d]+.*")) { return false; } return true; } /** * Encrypts griven string with given pass-phrase with DES. */ public static String cipher(String msg, byte[] passPhrase) { try { KeySpec keySpec = new DESKeySpec(passPhrase); SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret( keySpec); Cipher cipher = Cipher.getInstance(key.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, key); return toHexString(cipher.doFinal(msg.getBytes())); } catch (Exception e) { return null; } } /** * Decrypts griven string with given pass-phrase with DES. */ public static String decipher(String msg, byte[] passPhrase) { try { KeySpec keySpec = new DESKeySpec(passPhrase); SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret( keySpec); Cipher cipher = Cipher.getInstance(key.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, key); return new String(cipher.doFinal(fromHexString(msg))); } catch (Exception e) { return null; } } /** * Creates a md5 encoded in base64 for given input. */ public static String md5(byte[] input) { try { MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.reset(); md5.update(input); return Base64.getEncoder().encodeToString(md5.digest()); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } /** * Creates a random pass-phrase suitable for DES-encryption. */ public static byte[] createRandomPassPhrase() { byte[] passPhrase = String.valueOf(Math.random()).getBytes(); if (passPhrase.length < 8) { return createRandomPassPhrase(); } return passPhrase; } /** * Converts given byte-array into hexadecimal. */ public static String toHexString(byte[] b) { StringBuffer sb = new StringBuffer(b.length * 2); for (int i = 0; i < b.length; i++) { sb.append(HEX_CHARACTERS[(b[i] & 0xf0) >>> 4]); sb.append(HEX_CHARACTERS[b[i] & 0x0f]); } return sb.toString(); } /** * Converts given hexadecimal into byte-array. */ public static byte[] fromHexString(String s) { int stringLength = s.length(); if ((stringLength % 2) != 0) { throw new IllegalArgumentException( "Even number of characters required"); } byte[] b = new byte[stringLength / 2]; for (int i = 0, j = 0; i < stringLength; i += 2, j++) { int high = charToNibble(s.charAt(i)); int low = charToNibble(s.charAt(i + 1)); b[j] = (byte) ((high << 4) | low); } return b; } private static int charToNibble(char c) { if ('0' <= c && c <= '9') { return c - '0'; } else if ('a' <= c && c <= 'f') { return c - 'a' + 0xa; } else if ('A' <= c && c <= 'F') { return c - 'A' + 0xa; } else { throw new IllegalArgumentException("Invalid hex character: " + c); } } }