我需要帮助找出运行Linux Mint 17.2 Rafaela的机器上Java加密失败的原因。我的应用程序无法使用RC4算法解密以前加密的值。
我正在使用Java 8 u112进行测试,我安装了JCE,但这没有帮助。
以下是我创建的最小样本,适用于我的Windows机器:
import javax.xml.bind.DatatypeConverter;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
public class CryptoTest
{
private static final String ADMIN_PASSWORD = "admin";
private static final String ADMIN_ENCRYPTED_PASSWORD = "532C05C5B5"; // RC4 encrypted password using KEY
private static final String ADMIN_AUTH_KEY = "1391a8a860b7d6e2e86df513700e490c16dae47cdae227ca"; // PBKDF2(username,password,salt)
private static final String CRYPTO_ALGORITHM = "RC4";
protected static String encryptPassword(String passwordDataToEncrypt, String userskey) throws Exception
{
SecureRandom sr = new SecureRandom(userskey.getBytes());
KeyGenerator kg = KeyGenerator.getInstance(CRYPTO_ALGORITHM);
kg.init(sr);
SecretKey sk = kg.generateKey();
Cipher cipher = Cipher.getInstance(CRYPTO_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, sk);
return bytesToHex(cipher.doFinal(passwordDataToEncrypt.getBytes()));
}
private static String bytesToHex(byte[] in)
{
return DatatypeConverter.printHexBinary(in);
}
private static byte[] hexStringToByteArray(String s)
{
return DatatypeConverter.parseHexBinary(s);
}
protected static String decryptPassword(byte[] toDecryptPassword, String key) throws Exception
{
SecureRandom sr = new SecureRandom(key.getBytes());
KeyGenerator kg = KeyGenerator.getInstance(CRYPTO_ALGORITHM);
kg.init(sr);
SecretKey sk = kg.generateKey();
Cipher cipher = Cipher.getInstance(CRYPTO_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, sk);
return new String(cipher.doFinal(toDecryptPassword));
}
public static void assertEquals(String arg1, String arg2)
{
if (! arg1.equals(arg2))
{
System.out.println(String.format("%s does not equal %s", arg1, arg2));
}
}
public static void testGetDecryptedPassword() throws Exception
{
String decryptedPassword = decryptPassword(hexStringToByteArray(ADMIN_ENCRYPTED_PASSWORD), ADMIN_AUTH_KEY);
assertEquals(ADMIN_PASSWORD, decryptedPassword);
}
public static void testGetEncryptedPassword() throws Exception
{
String encryptedPassword = encryptPassword(ADMIN_PASSWORD, ADMIN_AUTH_KEY);
assertEquals(ADMIN_ENCRYPTED_PASSWORD, encryptedPassword);
}
public static void testEncryptAndDecryptPasswords() throws Exception
{
String originalPassword = "password";
String encryptedPassword = encryptPassword(originalPassword, ADMIN_AUTH_KEY);
String decryptedPassword = decryptPassword(hexStringToByteArray(encryptedPassword), ADMIN_AUTH_KEY);
assertEquals(originalPassword, decryptedPassword);
originalPassword = "This is a STRONG password 4 me!!!@#$^";
encryptedPassword = encryptPassword(originalPassword, ADMIN_AUTH_KEY);
decryptedPassword = decryptPassword(hexStringToByteArray(encryptedPassword), ADMIN_AUTH_KEY);
assertEquals(originalPassword, decryptedPassword);
}
public static void main(final String[] args)
{
try
{
int strength = Cipher.getMaxAllowedKeyLength("AES");
if ( strength > 128 ){
System.out.printf("isUnlimitedSupported=TRUE,strength: %d%n",strength);
} else {
System.out.printf("isUnlimitedSupported=FALSE,strength: %d%n",strength);
}
testGetDecryptedPassword();
testGetEncryptedPassword();
testEncryptAndDecryptPasswords();
}
catch (Exception e)
{
System.out.printf("Caught exception: %s\n", e.getMessage());
e.printStackTrace(System.out);
}
}
}
我的linux框上的输出是:
isUnlimitedSupported=TRUE,strength: 2147483647
admin does not equal <junk>
532C05C5B5 does not equal 5D16D89D2F
password does not equal <junk>
This is a STRONG password 4 me!!!@#$^ does not equal <junk>
<junk>
是一堆不可打印的字符。
答案 0 :(得分:2)
您的代码假定您每次使用以下代码中的相同密码初始化SecretKey
时都会获得相同的SecureRandom()
:
SecureRandom sr = new SecureRandom(userskey.getBytes());
KeyGenerator kg = KeyGenerator.getInstance(CRYPTO_ALGORITHM);
kg.init(sr);
SecretKey sk = kg.generateKey();
你真的不能做出这样的假设,你不应该使用这种方法。 SecureRandom
是 JCA 体系结构的一部分,实例化新SecureRandom(..)
时获得的实际实现取决于系统上可用的安全提供程序,以及每个安全提供程序的优先级提供者有。
如果您需要使用密码创建加密密钥,则应使用为PBKDF2创建的密钥派生函数。