下面列出了java.security.KeyStore.SecretKeyEntry#javax.crypto.spec.PBEKeySpec 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public InputStream decrypt(InputStream encryptedStream) {
try {
char[] password = options.getEncryptPassword().toCharArray();
byte[] salt = readSalt(encryptedStream);
byte[] iv = readIv(encryptedStream);
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey secret = new SecretKeySpec(SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(spec).getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
byte[] bytes = toByteArray(encryptedStream);
byte[] decryptedBytes = cipher.doFinal(bytes);
return new ByteArrayInputStream(decryptedBytes);
} catch (Exception e) {
throw new JDriveSyncException(JDriveSyncException.Reason.Encryption, "Failed to decrypt: " + e.getMessage(), e);
}
}
/**
* Returns a specification (key material) of the given key
* in the requested format.
*
* @param key the key
*
* @param keySpec the requested format in which the key material shall be
* returned
*
* @return the underlying key specification (key material) in the
* requested format
*
* @exception InvalidKeySpecException if the requested key
* specification is inappropriate for the given key, or the
* given key cannot be processed (e.g., the given key has an
* unrecognized algorithm or format).
*/
protected KeySpec engineGetKeySpec(SecretKey key, Class<?> keySpecCl)
throws InvalidKeySpecException {
if (key instanceof javax.crypto.interfaces.PBEKey) {
// Check if requested key spec is amongst the valid ones
if ((keySpecCl != null)
&& PBEKeySpec.class.isAssignableFrom(keySpecCl)) {
javax.crypto.interfaces.PBEKey pKey =
(javax.crypto.interfaces.PBEKey) key;
return new PBEKeySpec
(pKey.getPassword(), pKey.getSalt(),
pKey.getIterationCount(), pKey.getEncoded().length*8);
} else {
throw new InvalidKeySpecException("Invalid key spec");
}
} else {
throw new InvalidKeySpecException("Invalid key " +
"format/algorithm");
}
}
/**
* 根据PBE密码生成一把密钥
*
* @param password
* 生成密钥时所使用的密码
* @return Key PBE算法密钥
* */
private static Key getPBEKey(String password) {
// 实例化使用的算法
SecretKeyFactory keyFactory;
SecretKey secretKey = null;
try {
keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
// 设置PBE密钥参数
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
// 生成密钥
secretKey = keyFactory.generateSecret(keySpec);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return secretKey;
}
PKCS8EncodedKeySpec generateKeySpec(char[] password, byte[] key)
throws IOException, NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeySpecException, InvalidKeyException,
InvalidAlgorithmParameterException {
if (password == null) {
return new PKCS8EncodedKeySpec(key);
}
EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(key);
SecretKeyFactory keyFactory =
SecretKeyFactory.getInstance(encryptedPrivateKeyInfo.getAlgName());
PBEKeySpec pbeKeySpec = new PBEKeySpec(password);
SecretKey pbeKey = keyFactory.generateSecret(pbeKeySpec);
Cipher cipher = Cipher.getInstance(encryptedPrivateKeyInfo.getAlgName());
cipher.init(Cipher.DECRYPT_MODE, pbeKey, encryptedPrivateKeyInfo.getAlgParameters());
return encryptedPrivateKeyInfo.getKeySpec(cipher);
}
/**
* The key is generating by SecretKeyFactory and its value just copying in
* the key field of MySecretKey class. So, this is real key derived using
* the given algorithm.
*
* @param passPhrase some string intended to be a password
* @param algo PBKDF2 algorithm
* @param salt slat for PBKDF2
* @param iterationCount iteration count
* @param keySize key size in bits
* @throws InvalidKeySpecException
* @throws NoSuchAlgorithmException
*/
public MyPBKDF2SecretKey(String passPhrase, String algo, byte[] salt,
int iterationCount, int keySize)
throws InvalidKeySpecException, NoSuchAlgorithmException {
this.algorithm = algo;
this.salt = salt;
this.itereationCount = iterationCount;
this.keySize = keySize;
this.pass = passPhrase;
PBEKeySpec spec = new PBEKeySpec(passPhrase.toCharArray(),
this.salt, iterationCount, this.keySize);
SecretKeyFactory keyFactory
= SecretKeyFactory.getInstance(algo);
SecretKey realKey = keyFactory.generateSecret(spec);
this.keyLength = realKey.getEncoded().length;
this.key = new byte[this.keyLength];
System.arraycopy(realKey.getEncoded(), 0, this.key, 0,
this.keyLength);
}
/**
* Returns a specification (key material) of the given key
* in the requested format.
*
* @param key the key
*
* @param keySpec the requested format in which the key material shall be
* returned
*
* @return the underlying key specification (key material) in the
* requested format
*
* @exception InvalidKeySpecException if the requested key
* specification is inappropriate for the given key, or the
* given key cannot be processed (e.g., the given key has an
* unrecognized algorithm or format).
*/
protected KeySpec engineGetKeySpec(SecretKey key, Class<?> keySpecCl)
throws InvalidKeySpecException {
if (key instanceof javax.crypto.interfaces.PBEKey) {
// Check if requested key spec is amongst the valid ones
if ((keySpecCl != null)
&& PBEKeySpec.class.isAssignableFrom(keySpecCl)) {
javax.crypto.interfaces.PBEKey pKey =
(javax.crypto.interfaces.PBEKey) key;
return new PBEKeySpec
(pKey.getPassword(), pKey.getSalt(),
pKey.getIterationCount(), pKey.getEncoded().length*8);
} else {
throw new InvalidKeySpecException("Invalid key spec");
}
} else {
throw new InvalidKeySpecException("Invalid key " +
"format/algorithm");
}
}
protected void loadCipheredStock(){
mStock = new HashMap<String, Integer>();
try {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
String value = preferences.getString("inappservice_stock", "");
if (value.length() == 0) {
return;
}
final byte[] bytes = Base64.decode(value,Base64.DEFAULT);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(getUniquePseudoID().toCharArray()));
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(Settings.Secure.getString(mContext.getContentResolver(), Settings.Secure.ANDROID_ID).getBytes("utf-8"), 20));
String json = new String(pbeCipher.doFinal(bytes),"utf-8");
JSONObject object = new JSONObject(json);
Iterator<?> keys = object.keys();
while( keys.hasNext() ){
String pid = (String)keys.next();
this.mStock.put(pid, object.optInt(pid));
}
} catch( Exception e) {
e.printStackTrace();
}
}
/**
* A function that generates password-based AES and HMAC keys. It prints out exceptions but
* doesn't throw them since none should be encountered. If they are
* encountered, the return value is null.
*
* @param password The password to derive the keys from.
* @return The AES and HMAC keys.
* @throws GeneralSecurityException if AES is not implemented on this system,
* or a suitable RNG is not available
*/
public static SecretKeys generateKeyFromPassword(String password, byte[] salt) throws GeneralSecurityException {
fixPrng();
//Get enough random bytes for both the AES key and the HMAC key:
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt,
PBE_ITERATION_COUNT, AES_KEY_LENGTH_BITS + HMAC_KEY_LENGTH_BITS);
SecretKeyFactory keyFactory = SecretKeyFactory
.getInstance(PBE_ALGORITHM);
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
// Split the random bytes into two parts:
byte[] confidentialityKeyBytes = copyOfRange(keyBytes, 0, AES_KEY_LENGTH_BITS /8);
byte[] integrityKeyBytes = copyOfRange(keyBytes, AES_KEY_LENGTH_BITS /8, AES_KEY_LENGTH_BITS /8 + HMAC_KEY_LENGTH_BITS /8);
//Generate the AES key
SecretKey confidentialityKey = new SecretKeySpec(confidentialityKeyBytes, CIPHER);
//Generate the HMAC key
SecretKey integrityKey = new SecretKeySpec(integrityKeyBytes, HMAC_ALGORITHM);
return new SecretKeys(confidentialityKey, integrityKey);
}
/**
* Initiate the Cipher object for PBKDF2 algorithm using given "mode".
*
* @param mode Cipher mode: encrypt or decrypt
* @return Cipher object for PBKDF2 algorithm
* @throws GeneralSecurityException all security exceptions are thrown.
*/
@Override
protected Cipher initCipher(int mode) throws GeneralSecurityException {
Provider provider = Security.getProvider("SunJCE");
if (provider == null) {
throw new RuntimeException("SunJCE provider does not exist.");
}
// Generate secret key
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(),
salt, DEFAULT_ITERATION, PKDF2_DEFAULT_KEY_LEN);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(baseAlgo);
SecretKey key = keyFactory.generateSecret(pbeKeySpec);
// get Cipher instance
Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION, provider);
cipher.init(mode,
new SecretKeySpec(key.getEncoded(),KEY_ALGORITHM),
new IvParameterSpec(iv));
return cipher;
}
/**
* Returns a specification (key material) of the given key
* in the requested format.
*
* @param key the key
*
* @param keySpecCl the requested format in which the key material shall be
* returned
*
* @return the underlying key specification (key material) in the
* requested format
*
* @exception InvalidKeySpecException if the requested key
* specification is inappropriate for the given key, or the
* given key cannot be processed (e.g., the given key has an
* unrecognized algorithm or format).
*/
protected KeySpec engineGetKeySpec(SecretKey key, Class<?> keySpecCl)
throws InvalidKeySpecException {
if (key instanceof javax.crypto.interfaces.PBEKey) {
// Check if requested key spec is amongst the valid ones
if ((keySpecCl != null)
&& PBEKeySpec.class.isAssignableFrom(keySpecCl)) {
javax.crypto.interfaces.PBEKey pKey =
(javax.crypto.interfaces.PBEKey) key;
return new PBEKeySpec
(pKey.getPassword(), pKey.getSalt(),
pKey.getIterationCount(), pKey.getEncoded().length*8);
} else {
throw new InvalidKeySpecException("Invalid key spec");
}
} else {
throw new InvalidKeySpecException("Invalid key " +
"format/algorithm");
}
}
/**
* A function that generates password-based AES & HMAC keys. It prints out exceptions but
* doesn't throw them since none should be encountered. If they are
* encountered, the return value is null.
*
* @param password The password to derive the keys from.
* @param salt the salt
* @return The AES & HMAC keys.
* @throws GeneralSecurityException if AES is not implemented on this system, or a suitable RNG is not
* available
*/
public static SecretKeys generateKeyFromPassword(String password, byte[] salt)
throws GeneralSecurityException {
fixPrng();
//Get enough random bytes for both the AES key and the HMAC key:
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, PBE_ITERATION_COUNT,
AES_KEY_LENGTH_BITS + HMAC_KEY_LENGTH_BITS);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(PBE_ALGORITHM);
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
// Split the random bytes into two parts:
byte[] confidentialityKeyBytes = copyOfRange(keyBytes, 0, AES_KEY_LENGTH_BITS / 8);
byte[] integrityKeyBytes = copyOfRange(keyBytes, AES_KEY_LENGTH_BITS / 8,
AES_KEY_LENGTH_BITS / 8 + HMAC_KEY_LENGTH_BITS / 8);
//Generate the AES key
SecretKey confidentialityKey = new SecretKeySpec(confidentialityKeyBytes, CIPHER);
//Generate the HMAC key
SecretKey integrityKey = new SecretKeySpec(integrityKeyBytes, HMAC_ALGORITHM);
return new SecretKeys(confidentialityKey, integrityKey);
}
/**
* Creates a PBE key from a given PBE key specification.
*
* @param key the given PBE key specification
*/
PBEKey(PBEKeySpec keySpec, String keytype) throws InvalidKeySpecException {
char[] passwd = keySpec.getPassword();
if (passwd == null) {
// Should allow an empty password.
passwd = new char[0];
}
// Accept "\0" to signify "zero-length password with no terminator".
if (!(passwd.length == 1 && passwd[0] == 0)) {
for (int i=0; i<passwd.length; i++) {
if ((passwd[i] < '\u0020') || (passwd[i] > '\u007E')) {
throw new InvalidKeySpecException("Password is not ASCII");
}
}
}
this.key = new byte[passwd.length];
for (int i=0; i<passwd.length; i++)
this.key[i] = (byte) (passwd[i] & 0x7f);
java.util.Arrays.fill(passwd, ' ');
type = keytype;
}
private Cipher getCipher(int cipherMode) throws Exception {
String encryptionAlgorithm = "AES";
byte[] salt = {
(byte)0x95, (byte)0xaa, (byte)0x21, (byte)0x8c,
(byte)0xa9, (byte)0xc8, (byte)0xfe, (byte)0x99
};
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(encryptionKey.toCharArray(), salt, 1, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance(encryptionAlgorithm);
cipher.init(cipherMode, secret);
return cipher;
}
/**
* @param salt an array of random bytes to use for each (un)obfuscation
* @param applicationId application identifier, e.g. the package name
* @param deviceId device identifier. Use as many sources as possible to
* create this unique identifier.
*/
public AESObfuscator(byte[] salt, String applicationId, String deviceId) {
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance(KEYGEN_ALGORITHM);
KeySpec keySpec =
new PBEKeySpec((applicationId + deviceId).toCharArray(), salt, 1024, 256);
SecretKey tmp = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
mEncryptor = Cipher.getInstance(CIPHER_ALGORITHM);
mEncryptor.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(IV));
mDecryptor = Cipher.getInstance(CIPHER_ALGORITHM);
mDecryptor.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(IV));
} catch (GeneralSecurityException e) {
// This can't happen on a compatible Android device.
throw new RuntimeException("Invalid environment", e);
}
}
/**
* Creates a PBE key from a given PBE key specification.
*
* @param key the given PBE key specification
*/
PBEKey(PBEKeySpec keySpec, String keytype) throws InvalidKeySpecException {
char[] passwd = keySpec.getPassword();
if (passwd == null) {
// Should allow an empty password.
passwd = new char[0];
}
// Accept "\0" to signify "zero-length password with no terminator".
if (!(passwd.length == 1 && passwd[0] == 0)) {
for (int i=0; i<passwd.length; i++) {
if ((passwd[i] < '\u0020') || (passwd[i] > '\u007E')) {
throw new InvalidKeySpecException("Password is not ASCII");
}
}
}
this.key = new byte[passwd.length];
for (int i=0; i<passwd.length; i++)
this.key[i] = (byte) (passwd[i] & 0x7f);
java.util.Arrays.fill(passwd, ' ');
type = keytype;
}
/**
* 根据PBE密码生成一把密钥
*
* @param password
* 生成密钥时所使用的密码
* @return Key PBE算法密钥
* */
private static Key getPBEKey(String password) {
// 实例化使用的算法
SecretKeyFactory keyFactory;
SecretKey secretKey = null;
try {
keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
// 设置PBE密钥参数
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
// 生成密钥
secretKey = keyFactory.generateSecret(keySpec);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return secretKey;
}
/**
* Creates a PBE key from a given PBE key specification.
*
* @param key the given PBE key specification
*/
PBEKey(PBEKeySpec keySpec, String keytype) throws InvalidKeySpecException {
char[] passwd = keySpec.getPassword();
if (passwd == null) {
// Should allow an empty password.
passwd = new char[0];
}
// Accept "\0" to signify "zero-length password with no terminator".
if (!(passwd.length == 1 && passwd[0] == 0)) {
for (int i=0; i<passwd.length; i++) {
if ((passwd[i] < '\u0020') || (passwd[i] > '\u007E')) {
throw new InvalidKeySpecException("Password is not ASCII");
}
}
}
this.key = new byte[passwd.length];
for (int i=0; i<passwd.length; i++)
this.key[i] = (byte) (passwd[i] & 0x7f);
Arrays.fill(passwd, '\0');
type = keytype;
}
private void wrapperPBEKeyTest(Provider p) throws InvalidKeySpecException,
InvalidKeyException, NoSuchPaddingException,
IllegalBlockSizeException, InvalidAlgorithmParameterException,
NoSuchAlgorithmException {
for (String alg : PBE_ALGORITHM_AR) {
String baseAlgo = alg.split("/")[0].toUpperCase();
// only run the tests on longer key lengths if unlimited version
// of JCE jurisdiction policy files are installed
if (Cipher.getMaxAllowedKeyLength(alg) < Integer.MAX_VALUE
&& (baseAlgo.endsWith("TRIPLEDES") || alg
.endsWith("AES_256"))) {
out.println("keyStrength > 128 within " + alg
+ " will not run under global policy");
continue;
}
SecretKeyFactory skf = SecretKeyFactory.getInstance(baseAlgo, p);
SecretKey key = skf.generateSecret(new PBEKeySpec("Secret Lover"
.toCharArray()));
wrapTest(alg, alg, key, key, Cipher.SECRET_KEY, true);
}
}
/**
* Returns a specification (key material) of the given key
* in the requested format.
*
* @param key the key
*
* @param keySpec the requested format in which the key material shall be
* returned
*
* @return the underlying key specification (key material) in the
* requested format
*
* @exception InvalidKeySpecException if the requested key
* specification is inappropriate for the given key, or the
* given key cannot be processed (e.g., the given key has an
* unrecognized algorithm or format).
*/
protected KeySpec engineGetKeySpec(SecretKey key, Class<?> keySpecCl)
throws InvalidKeySpecException {
if (key instanceof javax.crypto.interfaces.PBEKey) {
// Check if requested key spec is amongst the valid ones
if ((keySpecCl != null)
&& PBEKeySpec.class.isAssignableFrom(keySpecCl)) {
javax.crypto.interfaces.PBEKey pKey =
(javax.crypto.interfaces.PBEKey) key;
return new PBEKeySpec
(pKey.getPassword(), pKey.getSalt(),
pKey.getIterationCount(), pKey.getEncoded().length*8);
} else {
throw new InvalidKeySpecException("Invalid key spec");
}
} else {
throw new InvalidKeySpecException("Invalid key " +
"format/algorithm");
}
}
/**
* Creates a PBE key from a given PBE key specification.
*
* @param key the given PBE key specification
*/
PBEKey(PBEKeySpec keySpec, String keytype) throws InvalidKeySpecException {
char[] passwd = keySpec.getPassword();
if (passwd == null) {
// Should allow an empty password.
passwd = new char[0];
}
// Accept "\0" to signify "zero-length password with no terminator".
if (!(passwd.length == 1 && passwd[0] == 0)) {
for (int i=0; i<passwd.length; i++) {
if ((passwd[i] < '\u0020') || (passwd[i] > '\u007E')) {
throw new InvalidKeySpecException("Password is not ASCII");
}
}
}
this.key = new byte[passwd.length];
for (int i=0; i<passwd.length; i++)
this.key[i] = (byte) (passwd[i] & 0x7f);
Arrays.fill(passwd, '\0');
type = keytype;
}
static PBEKeySpec keySpecFromJson(PBEKeyczarKey pbeKey, String password) {
try {
byte[] saltBytes = Base64Coder.decodeWebSafe(pbeKey.salt);
char[] passwordChars = password.toCharArray();
// keyLength is in bits
return new PBEKeySpec(passwordChars, saltBytes, pbeKey.iterationCount, PBE_AES_KEY_BYTES*8);
} catch (Base64DecodingException e) {
throw new RuntimeException(e);
}
}
private static Cipher create(String password, boolean encrypt) throws Exception {
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
KeySpec passwordBasedEncryptionKeySpec = new PBEKeySpec(password.toCharArray(), salt, 10000, 128);
SecretKey secretKeyFromPBKDF2 = secretKeyFactory.generateSecret(passwordBasedEncryptionKeySpec);
SecretKey key = new SecretKeySpec(secretKeyFromPBKDF2.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec spec = new IvParameterSpec(iv);
cipher.init(encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, key, spec);
return cipher;
}
private String pbkdf2( final cfSession _session, final String data, final String salt, final String sha, final Integer iterations, final Integer keylength ) throws cfmRunTimeException, NoSuchAlgorithmException, InvalidKeySpecException {
if( salt.length() == 0 ) {
throwException( _session, "You have to specify a salt when using PBKDF2" );
}
final SecretKeyFactory skf = SecretKeyFactory.getInstance( "PBKDF2WithHmac" + sha );
final char[] charArray = data.toCharArray();
final byte[] saltArray = salt.getBytes();
final PBEKeySpec spec = new PBEKeySpec( charArray, saltArray, iterations, keylength );
final byte[] hash = skf.generateSecret( spec ).getEncoded();
return BinaryEncode.encode(BinaryEncode.HEX, hash);
}
protected SecretKey engineGenerateSecret(
KeySpec keySpec)
throws InvalidKeySpecException
{
if (keySpec instanceof PBEKeySpec)
{
PBEKeySpec pbeSpec = (PBEKeySpec)keySpec;
CipherParameters param;
if (pbeSpec.getSalt() == null)
{
return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, null);
}
if (forCipher)
{
param = PBE.Util.makePBEParameters(pbeSpec, scheme, digest, keySize, ivSize);
}
else
{
param = PBE.Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize);
}
KeyParameter kParam;
if (param instanceof ParametersWithIV)
{
kParam = (KeyParameter)((ParametersWithIV)param).getParameters();
}
else
{
kParam = (KeyParameter)param;
}
DESParameters.setOddParity(kParam.getKey());
return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param);
}
throw new InvalidKeySpecException("Invalid KeySpec");
}
protected SecretKey engineGenerateSecret(
KeySpec keySpec)
throws InvalidKeySpecException
{
if (keySpec instanceof PBEKeySpec)
{
PBEKeySpec pbeSpec = (PBEKeySpec)keySpec;
CipherParameters param;
if (pbeSpec.getSalt() == null)
{
return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, null);
}
if (forCipher)
{
param = PBE.Util.makePBEParameters(pbeSpec, scheme, digest, keySize, ivSize);
}
else
{
param = PBE.Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize);
}
return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param);
}
throw new InvalidKeySpecException("Invalid KeySpec");
}
private SecretKeySpec getKey() throws Exception {
if (this.key == null) {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), this.salt.getBytes("UTF-8"), 5, 256);
SecretKey secretKey = factory.generateSecret(spec);
this.key = new SecretKeySpec(Arrays.copyOf(secretKey.getEncoded(), 16), "AES");
}
return this.key;
}
/**
* Instantiate Cipher for the PBE algorithm.
*
* @param mode Cipher mode: encrypt or decrypt.
* @return Cipher in accordance to the PBE algorithm
* @throws java.security.GeneralSecurityException
*/
@Override
protected Cipher initCipher(int mode) throws GeneralSecurityException {
Provider provider = Security.getProvider("SunJCE");
if (provider == null) {
throw new RuntimeException("SunJCE provider does not exist.");
}
SecretKey key = SecretKeyFactory.getInstance(baseAlgo)
.generateSecret(new PBEKeySpec(password.toCharArray()));
Cipher ci = Cipher.getInstance(transformation, provider);
ci.init(mode, key, new PBEParameterSpec(salt, DEFAULT_ITERATION));
return ci;
}
/**
* Translates a <code>SecretKey</code> object, whose provider may be
* unknown or potentially untrusted, into a corresponding
* <code>SecretKey</code> object of this key factory.
*
* @param key the key whose provider is unknown or untrusted
*
* @return the translated key
*
* @exception InvalidKeyException if the given key cannot be processed by
* this key factory.
*/
protected SecretKey engineTranslateKey(SecretKey key)
throws InvalidKeyException {
if ((key != null) &&
(key.getAlgorithm().equalsIgnoreCase("PBKDF2With" + prfAlgo)) &&
(key.getFormat().equalsIgnoreCase("RAW"))) {
// Check if key originates from this factory
if (key instanceof com.sun.crypto.provider.PBKDF2KeyImpl) {
return key;
}
// Check if key implements the PBEKey
if (key instanceof javax.crypto.interfaces.PBEKey) {
javax.crypto.interfaces.PBEKey pKey =
(javax.crypto.interfaces.PBEKey) key;
try {
PBEKeySpec spec =
new PBEKeySpec(pKey.getPassword(),
pKey.getSalt(),
pKey.getIterationCount(),
pKey.getEncoded().length*8);
return new PBKDF2KeyImpl(spec, prfAlgo);
} catch (InvalidKeySpecException re) {
InvalidKeyException ike = new InvalidKeyException
("Invalid key component(s)");
ike.initCause(re);
throw ike;
}
}
}
throw new InvalidKeyException("Invalid key format/algorithm");
}
private static String generateTokenHash(String password)
throws NoSuchAlgorithmException, InvalidKeySpecException {
int iterations = 1000;
char[] chars = password.toCharArray();
byte[] salt = getSalt();
PBEKeySpec spec = new PBEKeySpec(chars, salt, iterations, 64 * 8);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = skf.generateSecret(spec).getEncoded();
return iterations + ":" + toHex(salt) + ":" + toHex(hash);
}
/**
* Get SecretKey for the given PBKDF2 algorithm.
*
* @param thePBKDF2Algorithm - PBKDF2 algorithm
* @return SecretKey according to thePBKDF2Algorithm
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
protected SecretKey getSecretKey(String thePBKDF2Algorithm)
throws NoSuchAlgorithmException, InvalidKeySpecException {
// Prepare salt
byte[] salt = new byte[64]; // PKCS #5 v2.1 recommendation
new SecureRandom().nextBytes(salt);
// Generate secret key
PBEKeySpec pbeKeySpec = new PBEKeySpec(
"A #pwd# implied to be hidden!".toCharArray(),
salt, 1000, 128);
SecretKeyFactory keyFactory
= SecretKeyFactory.getInstance(thePBKDF2Algorithm);
return keyFactory.generateSecret(pbeKeySpec);
}