Last active
December 28, 2015 22:19
-
-
Save rdev5/7570750 to your computer and use it in GitHub Desktop.
Patch for EncryptedMapDecorator.java (cas-server-extension-clearpass). Returns IV (16 bytes) prepended to ciphertext on encrypt(); mandatory for proper decryption. Useful in clustered environments where IVs saved to thread-safe ConcurrentHashMaps are being stored locally in memory, thus rendering other systems in the cluster unable to decrypt a …
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Licensed to Yavapai College under one or more contributor license | |
* agreements. See the NOTICE file distributed with this work | |
* for additional information regarding copyright ownership. | |
* Jasig licenses this file to you 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 the following location: | |
* | |
* 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. | |
*/ | |
import java.io.UnsupportedEncodingException; | |
import java.nio.ByteBuffer; | |
import java.nio.ByteOrder; | |
import java.util.Arrays; | |
import java.util.Random; | |
import java.security.NoSuchAlgorithmException; | |
import java.security.SecureRandom; | |
import java.security.Key; | |
import java.security.spec.KeySpec; | |
import javax.validation.constraints.NotNull; | |
import javax.crypto.Cipher; | |
import javax.crypto.spec.IvParameterSpec; | |
import javax.crypto.NoSuchPaddingException; | |
import javax.crypto.SecretKey; | |
import javax.crypto.SecretKeyFactory; | |
import javax.crypto.spec.SecretKeySpec; | |
import javax.crypto.spec.PBEKeySpec; | |
import org.apache.commons.codec.binary.Base64; | |
/** | |
* Decorator for a map that will hash the key and encrypt the value. | |
* | |
* @author Matt Borja | |
* @version $Revision$ $Date$ | |
* @since 1.0.0 | |
*/ | |
public class CryptDemo { | |
private static final String ENCRYPTION_ALGORITHM = "AES"; | |
private static final String HASH_ALGORITHM = "SHA-512"; | |
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding"; | |
private static final String SECRET_KEY_FACTORY_ALGORITHM = "PBKDF2WithHmacSHA1"; | |
private static final int RAND_MIN = 8; | |
private static final int RAND_MAX = 16; | |
private static final int INTEGER_LEN = 4; | |
private Cipher cipher; | |
@NotNull | |
private Key key; | |
@NotNull | |
private int ivSize; | |
public static void main(String[] args) { | |
try { | |
new CryptDemo().Start(args); | |
} catch(final Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
private Cipher getCipherObject() throws NoSuchAlgorithmException, NoSuchPaddingException { | |
return Cipher.getInstance(CIPHER_ALGORITHM); | |
} | |
private static int getIvSize() throws NoSuchAlgorithmException, NoSuchPaddingException { | |
return Cipher.getInstance(CIPHER_ALGORITHM).getBlockSize(); | |
} | |
private static byte[] generateIV(final int size) { | |
SecureRandom srand = new SecureRandom(); | |
byte[] iv_value = new byte[size]; | |
srand.nextBytes(iv_value); | |
return iv_value; | |
} | |
private static byte[] generateKey() { | |
Random rand = new Random(); | |
return generateKey(rand.nextInt(RAND_MAX) + RAND_MIN); | |
} | |
private static byte[] generateKey(final int size) { | |
SecureRandom srand = new SecureRandom(); | |
byte[] salt = new byte[size]; | |
srand.nextBytes(salt); | |
return salt; | |
} | |
private static byte[] generateSalt() { | |
Random rand = new Random(); | |
return generateSalt(rand.nextInt(RAND_MAX) + RAND_MIN); | |
} | |
private static byte[] generateSalt(final int size) { | |
SecureRandom srand = new SecureRandom(); | |
byte[] salt = new byte[size]; | |
srand.nextBytes(salt); | |
return salt; | |
} | |
private static byte[] encode(final byte[] bytes) { | |
return new Base64().encode(bytes); | |
} | |
private static byte[] decode(final byte[] bytes) { | |
return new Base64().decode(bytes); | |
} | |
// BIG_ENDIAN | |
private static int getInt(final byte[] bytes) { | |
return ByteBuffer.wrap(bytes).getInt(); | |
} | |
public void Start(String[] args) throws Exception { | |
if(args.length < 2) { | |
StackTraceElement[] stack = Thread.currentThread ().getStackTrace (); | |
StackTraceElement main = stack[stack.length - 1]; | |
String mainClass = main.getClassName (); | |
System.out.println("Usage: " + mainClass + " <mode> <plaintext> [key] [salt]"); | |
System.exit(0); | |
} | |
int mode = new String(args[0]).equals("encrypt") ? 1 : (new String(args[0]).equals("decrypt") ? 0 : -1); | |
String input = args[1]; | |
Boolean keySpecified = args.length >= 3; | |
Boolean saltSpecified = args.length >= 4; | |
byte[] key, salt; | |
try { | |
this.ivSize = getIvSize(); | |
} catch (final Exception e) { | |
throw new RuntimeException(e); | |
} | |
switch(mode) { | |
// ENCRYPT_MODE | |
case 1: | |
key = keySpecified ? args[2].getBytes() : generateKey(); | |
if(!keySpecified) System.out.println("[WARNING] New key required for decryption: " + new String(encode(key))); | |
salt = saltSpecified ? args[3].getBytes() : generateSalt(); | |
if(!saltSpecified) System.out.println("[WARNING] New salt required for decryption: " + new String(encode(salt))); | |
cipher = getCipherObject(); | |
this.key = deriveSecretKey(ENCRYPTION_ALGORITHM, new String(key), new String(salt)); | |
System.out.println(encrypt(input)); | |
break; | |
// DECRYPT_MODE | |
case 0: | |
if(!keySpecified || !saltSpecified) { | |
System.out.println("Key and salt required"); | |
System.exit(0); | |
} | |
key = args[2].getBytes(); | |
salt = args[3].getBytes(); | |
cipher = getCipherObject(); | |
this.key = deriveSecretKey(ENCRYPTION_ALGORITHM, new String(key), new String(salt)); | |
System.out.println(decrypt(input)); | |
break; | |
default: | |
System.out.println("Invalid mode specified (" + args[0] + " - " + mode + "). Valid options are: encrypt, decrypt"); | |
System.exit(1); | |
break; | |
} | |
} | |
protected String encrypt(String plaintext) { | |
if (plaintext == null) { | |
return null; | |
} | |
try { | |
byte[] iv_value = generateIV(this.ivSize); | |
IvParameterSpec iv_spec = new IvParameterSpec(iv_value); | |
cipher.init(Cipher.ENCRYPT_MODE, this.key, iv_spec); | |
byte[] ciphertext = cipher.doFinal(plaintext.getBytes()); | |
byte[] iv_ciphertext = new byte[INTEGER_LEN + this.ivSize + ciphertext.length]; | |
System.arraycopy(int2byte(this.ivSize), 0, iv_ciphertext, 0, INTEGER_LEN); | |
System.arraycopy(iv_value, 0, iv_ciphertext, INTEGER_LEN, this.ivSize); | |
System.arraycopy(ciphertext, 0, iv_ciphertext, INTEGER_LEN + this.ivSize, ciphertext.length); | |
return new String(encode(iv_ciphertext)); | |
} catch(final Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
protected String decrypt(String value) { | |
if (value == null) { | |
return null; | |
} | |
try { | |
byte[] iv_ciphertext = decode(value.getBytes()); | |
int ivSize = byte2int(Arrays.copyOfRange(iv_ciphertext, 0, INTEGER_LEN)); | |
byte[] iv_value = Arrays.copyOfRange(iv_ciphertext, INTEGER_LEN, (INTEGER_LEN + ivSize)); | |
byte[] ciphertext = Arrays.copyOfRange(iv_ciphertext, INTEGER_LEN + ivSize, iv_ciphertext.length); | |
IvParameterSpec iv_spec = new IvParameterSpec(iv_value); | |
cipher.init(Cipher.DECRYPT_MODE, this.key, iv_spec); | |
byte[] plaintext = cipher.doFinal(ciphertext); | |
return new String(plaintext); | |
} catch(final Exception e) { | |
System.exit(1); // Invalid key, salt, or ciphertext | |
throw new RuntimeException(e); | |
} | |
} | |
/* | |
* Utility functions | |
*/ | |
protected static byte[] int2byte(final int i) throws UnsupportedEncodingException { | |
return ByteBuffer.allocate(4).putInt(i).array(); | |
} | |
protected static int byte2int(final byte[] bytes) throws UnsupportedEncodingException { | |
return ByteBuffer.wrap(bytes).getInt(); | |
} | |
protected static String byte2char(final byte[] bytes) throws UnsupportedEncodingException { | |
return new String(bytes, "UTF-8"); | |
} | |
protected static byte[] char2byte(final String chars) throws UnsupportedEncodingException { | |
return chars.getBytes("UTF-8"); | |
} | |
private static Key deriveSecretKey(String secretKeyAlgorithm, String secretKey, String salt) throws Exception { | |
SecretKeyFactory factory = SecretKeyFactory.getInstance(SECRET_KEY_FACTORY_ALGORITHM); | |
KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), char2byte(salt), 65536, 128); | |
SecretKey tmp = factory.generateSecret(spec); | |
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), secretKeyAlgorithm); | |
return secret; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Licensed to Jasig under one or more contributor license | |
* agreements. See the NOTICE file distributed with this work | |
* for additional information regarding copyright ownership. | |
* Jasig licenses this file to you 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 the following location: | |
* | |
* 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 org.jasig.cas.extension.clearpass; | |
import java.nio.ByteBuffer; | |
import java.io.UnsupportedEncodingException; | |
import java.security.Key; | |
import java.security.MessageDigest; | |
import java.security.NoSuchAlgorithmException; | |
import java.security.SecureRandom; | |
import java.security.spec.KeySpec; | |
import java.util.Collection; | |
import java.util.Map; | |
import java.util.Set; | |
import java.util.Arrays; | |
import java.util.concurrent.ConcurrentHashMap; | |
import javax.crypto.Cipher; | |
import javax.crypto.NoSuchPaddingException; | |
import javax.crypto.SecretKey; | |
import javax.crypto.SecretKeyFactory; | |
import javax.crypto.spec.IvParameterSpec; | |
import javax.crypto.spec.PBEKeySpec; | |
import javax.crypto.spec.SecretKeySpec; | |
import javax.validation.constraints.NotNull; | |
import org.apache.commons.codec.binary.Base64; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
/** | |
* Decorator for a map that will hash the key and encrypt the value. | |
* | |
* @author Scott Battaglia | |
* @since 1.0.6 | |
*/ | |
public final class EncryptedMapDecorator implements Map<String, String> { | |
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding"; | |
private static final String SECRET_KEY_FACTORY_ALGORITHM = "PBKDF2WithHmacSHA1"; | |
private static final String DEFAULT_HASH_ALGORITHM = "SHA-512"; | |
private static final String DEFAULT_ENCRYPTION_ALGORITHM = "AES"; | |
private static final int INTEGER_LEN = 4; | |
private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', | |
'e', 'f'}; | |
private final Logger logger = LoggerFactory.getLogger(getClass()); | |
@NotNull | |
private final Map<String, String> decoratedMap; | |
@NotNull | |
private final MessageDigest messageDigest; | |
@NotNull | |
private final byte[] salt; | |
@NotNull | |
private final Key key; | |
@NotNull | |
private int ivSize; | |
@NotNull | |
private final String secretKeyAlgorithm; | |
private boolean cloneNotSupported; | |
private ConcurrentHashMap<Object, IvParameterSpec> algorithmParametersHashMap = | |
new ConcurrentHashMap<Object, IvParameterSpec>(); | |
/** | |
* Decorates a map using the default algorithm {@link #DEFAULT_HASH_ALGORITHM} and a | |
* {@link #DEFAULT_ENCRYPTION_ALGORITHM}. | |
* <p>The salt is randomly constructed when the object is created in memory. | |
* This constructor is sufficient to decorate | |
* a cache that only lives in-memory. | |
* | |
* @param decoratedMap the map to decorate. CANNOT be NULL. | |
* @throws Exception if the algorithm cannot be found. Should not happen in this case, or if the key spec is not found | |
* or if the key is invalid. Check the exception type for more details on the nature of the error. | |
*/ | |
public EncryptedMapDecorator(final Map<String, String> decoratedMap) throws Exception { | |
this(decoratedMap, getRandomSalt(8), getRandomSalt(32)); | |
} | |
/** | |
* Decorates a map using the default algorithm {@link #DEFAULT_HASH_ALGORITHM} | |
* and a {@link #DEFAULT_ENCRYPTION_ALGORITHM}. | |
* <p>Takes a salt and secretKey so that it can work with a distributed cache. | |
* | |
* @param decoratedMap the map to decorate. CANNOT be NULL. | |
* @param salt the salt, as a String. Gets converted to bytes. CANNOT be NULL. | |
* @param secretKey the secret to use for the key. Gets converted to bytes. CANNOT be NULL. | |
* @throws Exception if the algorithm cannot be found. Should not happen in this case, or if the key spec is not found | |
* or if the key is invalid. Check the exception type for more details on the nature of the error. | |
*/ | |
public EncryptedMapDecorator(final Map<String, String> decoratedMap, final String salt, | |
final String secretKey) throws Exception { | |
this(decoratedMap, DEFAULT_HASH_ALGORITHM, salt, DEFAULT_ENCRYPTION_ALGORITHM, secretKey); | |
} | |
/** | |
* Decorates a map using the provided algorithms. | |
* <p>Takes a salt and secretKey so that it can work with a distributed cache. | |
* | |
* @param decoratedMap the map to decorate. CANNOT be NULL. | |
* @param hashAlgorithm the algorithm to use for hashing. CANNOT BE NULL. | |
* @param salt the salt, as a String. Gets converted to bytes. CANNOT be NULL. | |
* @param secretKeyAlgorithm the encryption algorithm. CANNOT BE NULL. | |
* @param secretKey the secret to use for the key. Gets converted to bytes. CANNOT be NULL. | |
* @throws Exception if the algorithm cannot be found. Should not happen in this case, or if the key spec is not found | |
* or if the key is invalid. Check the exception type for more details on the nature of the error. | |
*/ | |
public EncryptedMapDecorator(final Map<String, String> decoratedMap, final String hashAlgorithm, final String salt, | |
final String secretKeyAlgorithm, final String secretKey) throws Exception { | |
this(decoratedMap, hashAlgorithm, salt.getBytes(), secretKeyAlgorithm, | |
getSecretKey(secretKeyAlgorithm, secretKey, salt)); | |
} | |
/** | |
* Decorates a map using the provided algorithms. | |
* <p>Takes a salt and secretKey so that it can work with a distributed cache. | |
* | |
* @param decoratedMap the map to decorate. CANNOT be NULL. | |
* @param hashAlgorithm the algorithm to use for hashing. CANNOT BE NULL. | |
* @param salt the salt, as a String. Gets converted to bytes. CANNOT be NULL. | |
* @param secretKeyAlgorithm the encryption algorithm. CANNOT BE NULL. | |
* @param secretKey the secret to use. CANNOT be NULL. | |
* @throws NoSuchAlgorithmException if the algorithm cannot be found. Should not happen in this case. | |
*/ | |
public EncryptedMapDecorator(final Map<String, String> decoratedMap, final String hashAlgorithm, final byte[] salt, | |
final String secretKeyAlgorithm, final Key secretKey) throws NoSuchAlgorithmException { | |
this.decoratedMap = decoratedMap; | |
this.key = secretKey; | |
this.salt = salt; | |
this.secretKeyAlgorithm = secretKeyAlgorithm; | |
this.messageDigest = MessageDigest.getInstance(hashAlgorithm); | |
try { | |
this.ivSize = getIvSize(); | |
} catch (final Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
private static String getRandomSalt(final int size) { | |
final SecureRandom secureRandom = new SecureRandom(); | |
final byte[] bytes = new byte[size]; | |
secureRandom.nextBytes(bytes); | |
return getFormattedText(bytes); | |
} | |
@Override | |
public int size() { | |
return this.decoratedMap.size(); | |
} | |
@Override | |
public boolean isEmpty() { | |
return this.decoratedMap.isEmpty(); | |
} | |
@Override | |
public boolean containsKey(final Object key) { | |
final String hashedKey = constructHashedKey(key.toString()); | |
return this.decoratedMap.containsKey(hashedKey); | |
} | |
@Override | |
public boolean containsValue(final Object value) { | |
if (!(value instanceof String)) { | |
return false; | |
} | |
final String encryptedValue = encrypt((String) value); | |
return this.decoratedMap.containsValue(encryptedValue); | |
} | |
@Override | |
public String get(final Object key) { | |
final String hashedKey = constructHashedKey(key == null ? null : key.toString()); | |
return decrypt(this.decoratedMap.get(hashedKey), hashedKey); | |
} | |
@Override | |
public String put(final String key, final String value) { | |
final String hashedKey = constructHashedKey(key); | |
final String hashedValue = encrypt(value, hashedKey); | |
final String oldValue = this.decoratedMap.put(hashedKey, hashedValue); | |
return decrypt(oldValue, hashedKey); | |
} | |
@Override | |
public String remove(final Object key) { | |
final String hashedKey = constructHashedKey(key.toString()); | |
return decrypt(this.decoratedMap.remove(hashedKey), hashedKey); | |
} | |
@Override | |
public void putAll(final Map<? extends String, ? extends String> m) { | |
for (final Entry<? extends String, ? extends String> entry : m.entrySet()) { | |
this.put(entry.getKey(), entry.getValue()); | |
} | |
} | |
@Override | |
public void clear() { | |
this.decoratedMap.clear(); | |
} | |
@Override | |
public Set<String> keySet() { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public Collection<String> values() { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public Set<Entry<String, String>> entrySet() { | |
throw new UnsupportedOperationException(); | |
} | |
protected String constructHashedKey(final String key) { | |
if (key == null) { | |
return null; | |
} | |
final MessageDigest messageDigest = getMessageDigest(); | |
messageDigest.update(this.salt); | |
messageDigest.update(key.getBytes()); | |
final String hash = getFormattedText(messageDigest.digest()); | |
logger.debug(String.format("Generated hash of value [%s] for key [%s].", hash, key)); | |
return hash; | |
} | |
protected String decrypt(final String value, final String hashedKey) { | |
if (value == null) { | |
return null; | |
} | |
try { | |
final Cipher cipher = getCipherObject(); | |
byte[] ivCiphertext = decode(value.getBytes()); | |
int ivSize = byte2int(Arrays.copyOfRange(ivCiphertext, 0, INTEGER_LEN)); | |
byte[] ivValue = Arrays.copyOfRange(ivCiphertext, INTEGER_LEN, (INTEGER_LEN + ivSize)); | |
byte[] ciphertext = Arrays.copyOfRange(ivCiphertext, INTEGER_LEN + ivSize, ivCiphertext.length); | |
IvParameterSpec ivSpec = new IvParameterSpec(ivValue); | |
cipher.init(Cipher.DECRYPT_MODE, this.key, ivSpec); | |
byte[] plaintext = cipher.doFinal(ciphertext); | |
return new String(plaintext); | |
} catch (final Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
private static int getIvSize() throws NoSuchAlgorithmException, NoSuchPaddingException { | |
return Cipher.getInstance(CIPHER_ALGORITHM).getBlockSize(); | |
} | |
private static byte[] generateIV(final int size) { | |
SecureRandom srand = new SecureRandom(); | |
byte[] ivValue = new byte[size]; | |
srand.nextBytes(ivValue); | |
return ivValue; | |
} | |
private static byte[] encode(final byte[] bytes) { | |
return new Base64().encode(bytes); | |
} | |
private static byte[] decode(final byte[] bytes) { | |
return new Base64().decode(bytes); | |
} | |
protected String encrypt(final String value) { | |
return encrypt(value, null); | |
} | |
protected String encrypt(final String value, final String hashedKey) { | |
if (value == null) { | |
return null; | |
} | |
try { | |
final Cipher cipher = getCipherObject(); | |
byte[] ivValue = generateIV(this.ivSize); | |
IvParameterSpec ivSpec = new IvParameterSpec(ivValue); | |
cipher.init(Cipher.ENCRYPT_MODE, this.key, ivSpec); | |
byte[] ciphertext = cipher.doFinal(value.getBytes()); | |
byte[] ivCiphertext = new byte[INTEGER_LEN + this.ivSize + ciphertext.length]; | |
System.arraycopy(int2byte(this.ivSize), 0, ivCiphertext, 0, INTEGER_LEN); | |
System.arraycopy(ivValue, 0, ivCiphertext, INTEGER_LEN, this.ivSize); | |
System.arraycopy(ciphertext, 0, ivCiphertext, INTEGER_LEN + this.ivSize, ciphertext.length); | |
return new String(encode(ivCiphertext)); | |
} catch(final Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
protected static byte[] int2byte(final int i) throws UnsupportedEncodingException { | |
return ByteBuffer.allocate(4).putInt(i).array(); | |
} | |
protected static int byte2int(final byte[] bytes) throws UnsupportedEncodingException { | |
return ByteBuffer.wrap(bytes).getInt(); | |
} | |
protected static String byte2char(final byte[] bytes) throws UnsupportedEncodingException { | |
return new String(bytes, "UTF-8"); | |
} | |
protected static byte[] char2byte(final String chars) throws UnsupportedEncodingException { | |
return chars.getBytes("UTF-8"); | |
} | |
/** | |
* Tries to clone the {@link MessageDigest} that was created during construction. If the clone fails | |
* that is remembered and from that point on new {@link MessageDigest} instances will be created on | |
* every call. | |
* <p> | |
* Adopted from the Spring EhCache Annotations project. | |
* | |
* @return Generates a {@link MessageDigest} to use | |
*/ | |
protected MessageDigest getMessageDigest() { | |
if (this.cloneNotSupported) { | |
final String algorithm = this.messageDigest.getAlgorithm(); | |
try { | |
return MessageDigest.getInstance(algorithm); | |
} catch (final NoSuchAlgorithmException e) { | |
throw new IllegalStateException("MessageDigest algorithm '" + algorithm + "' was supported when " | |
+ this.getClass().getSimpleName() | |
+ " was created but is not now. This should not be possible.", e); | |
} | |
} | |
try { | |
return (MessageDigest) this.messageDigest.clone(); | |
} catch (final CloneNotSupportedException e) { | |
this.cloneNotSupported = true; | |
final String msg = String.format("Could not clone MessageDigest using algorithm '%s'. " | |
+ "MessageDigest.getInstance will be used from now on which will be much more expensive.", | |
this.messageDigest.getAlgorithm()); | |
logger.warn(msg, e); | |
return this.getMessageDigest(); | |
} | |
} | |
/** | |
* Takes the raw bytes from the digest and formats them correct. | |
* | |
* @param bytes the raw bytes from the digest. | |
* @return the formatted bytes. | |
*/ | |
private static String getFormattedText(final byte[] bytes) { | |
final StringBuilder buf = new StringBuilder(bytes.length * 2); | |
for (byte b : bytes) { | |
buf.append(HEX_DIGITS[b >> 4 & 0x0f]); | |
buf.append(HEX_DIGITS[b & 0x0f]); | |
} | |
return buf.toString(); | |
} | |
private Cipher getCipherObject() throws NoSuchAlgorithmException, NoSuchPaddingException { | |
return Cipher.getInstance(CIPHER_ALGORITHM); | |
} | |
private static Key getSecretKey(final String secretKeyAlgorithm, final String secretKey, | |
final String salt) throws Exception { | |
SecretKeyFactory factory = SecretKeyFactory.getInstance(SECRET_KEY_FACTORY_ALGORITHM); | |
KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), char2byte(salt), 65536, 128); | |
SecretKey tmp = factory.generateSecret(spec); | |
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), secretKeyAlgorithm); | |
return secret; | |
} | |
public String getSecretKeyAlgorithm() { | |
return secretKeyAlgorithm; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment