/* * Copyright 2012 Nodeable Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.streamreduce.util; import java.security.Key; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; import org.apache.shiro.codec.Base64; import org.apache.shiro.crypto.AesCipherService; import org.apache.shiro.crypto.RandomNumberGenerator; import org.apache.shiro.crypto.SecureRandomNumberGenerator; import org.apache.shiro.crypto.hash.Sha256Hash; import org.apache.shiro.util.ByteSource; import org.apache.shiro.util.SimpleByteSource; import org.springframework.util.StringUtils; public final class SecurityUtil { public static String passwordEncrypt(String password) { return new Sha256Hash(password).toBase64(); } public static boolean isValidPassword(String password) { return !(password.isEmpty() || password.length() < 6 || password.length() >= 20); } public static String createNodeableFUID(String str, Long created) { str = StringUtils.trimAllWhitespace(str); str = str.toLowerCase(); // remove all non alphanumeric str = str.replaceAll("[^a-zA-Z0-9]", ""); str = str + "_" + created; return str; } /* * This method generates a random n digit string, which contains at least one number, lower case alphabet, upper * case alphabet and as special character. */ public static String generateRandomString(int n) { Random rd = new Random(); char lowerChars[] = "abcdefghijklmnopqrstuvwxyz".toCharArray(); char upperChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); char numbers[] = "0123456789".toCharArray(); //char specialChars[] = "~!@#$%^&*()-_=+[{]}|;:<>/?".toCharArray(); char specialChars[] = "!$-_+".toCharArray(); // limited subset List<Character> pwdLst = new ArrayList<>(); for (int g = 0; g <= n; g++) { for (int z = 0; z < 1; z++) { if (g == 0) { pwdLst.add(numbers[rd.nextInt(10)]); // must match char array length(s) above } else if (g == 1) { pwdLst.add(lowerChars[rd.nextInt(26)]); } else if (g == 2) { pwdLst.add(upperChars[rd.nextInt(26)]); } else if (g == 3) { pwdLst.add(specialChars[rd.nextInt(5)]); } } if (pwdLst.size() == n) { break; } if (g + 1 == 4) { g = (int) (Math.random() * 5); } } StringBuilder password = new StringBuilder(); Collections.shuffle(pwdLst); for (Character aPwdLst : pwdLst) { password.append(aPwdLst); } return password.toString(); } /** * Generate a random string, default is 10 characters in length * * @return */ public static String generateRandomString() { return generateRandomString(10); } /** * Returns encrypted password using given key * * @param password password to encrypt in plain text * @param key the encryption key * @return encrypted password in base64 encoding */ public static String encryptPassword(String password, byte[] key) { AesCipherService cipherService = new AesCipherService(); ByteSource encrypted = cipherService.encrypt(password.getBytes(), key); return encrypted.toBase64(); } /** * Returns decrypted password using given key * * @param password the password to decrypt in base64 encoding * @param key the key used to encrypt the password * @return decrypted password in plain text */ public static String decryptPassword(String password, byte[] key) { AesCipherService cipherService = new AesCipherService(); ByteSource decrypted = cipherService.decrypt(Base64.decode(password), key); return new String(decrypted.getBytes()); } /** * Returns a new encryption key * * @return encryption key in base64 encoding */ public static String generateNewKey() { AesCipherService cipherService = new AesCipherService(); Key newKey = cipherService.generateNewKey(); return new SimpleByteSource(newKey.getEncoded()).toBase64(); } public static String issueRandomAPIToken() { // we need to see our tokens with a random value so the same one isn't generated // for the same user each time. RandomNumberGenerator rng = new SecureRandomNumberGenerator(); Object randomNumber = rng.nextBytes(); // we also use a user agent as a validation factor // so when we later validate the token, we also validate the user agent String secret = generateRandomString(); String salt = secret.concat(randomNumber.toString()); return new Sha256Hash(secret, salt, 1024).toBase64(); } }