目前我们正在加密用户在登录页面输入的密码并将其存储在数据库中。这里正在开发一个用于内部目的的新登录页面,并重复使用相同的用户名和加密密码。如果用户获得授权,则将允许他访问报告。我的问题是,我怎样才能获得他们用来加密的 key 。想要使用相同的 key 来解密密码,我可以继续我的逻辑。
这是我们用来加密密码的加密方法的代码。
user = userRemote.loginUser(userName, new String(EncryptDecrypt.storePassword(password),"Cp1252"));
Here password is Password entered in the login page.
这是加密密码的方法。
final static byte[] salt = {
(byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
(byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
};
final static int count = 1;
public static byte[] storePassword(char[] password) throws InternalException {
PBEKeySpec pbeKeySpec;
PBEParameterSpec pbeParamSpec;
SecretKeyFactory keyFac;
byte[] ciphertext = null;
try {
// Install SunJCE provider
Provider sunJce = new com.sun.crypto.provider.SunJCE();
Security.addProvider(sunJce);
// Create PBE parameter set
pbeParamSpec = new PBEParameterSpec(salt, count);
pbeKeySpec = new PBEKeySpec(password);
keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
// Create PBE Cipher
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
// Initialize PBE Cipher with key and parameters
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
// Our cleartext
byte[] cleartext = (new String(password)).getBytes("Cp1252");
// Encrypt the cleartext
ciphertext = pbeCipher.doFinal(cleartext);
} catch (BadPaddingException ex) {
log.error("EncryptDecrypt: " + ex.getMessage());
throw new InternalException(ex.getMessage());
} catch (Exception ex) {
log.error("EncryptDecrypt: " + ex.getMessage());
throw new InternalException(ex.getMessage());
}
return ciphertext;
}
这是用于解密密码的类。这里我只使用加密的密码作为解密密码的输入。例如•?0 BÒó,所以我使用相同的方法来生成 key 并解密它。但是,低于异常(exception)。 java.security.spec.InvalidKeySpecException:密码不是 ASCII
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class DecryptPassword {
public static void main(String[] args) {
String decryptedStr = checkPassword("•Ä0BÒ¦O");
System.out.println("decryptedStr : "+decryptedStr);
}
final static byte[] salt = {
(byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
(byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
};
final static int count = 1;
static String decryptedPassword = "";
public static String checkPassword(String encryptedPassword) {
PBEKeySpec pbeKeySpec;
PBEParameterSpec pbeParamSpec;
SecretKeyFactory keyFac;
try {
// Install SunJCE provider
Provider sunJce = new com.sun.crypto.provider.SunJCE();
Security.addProvider(sunJce);
// Create PBE parameter set
pbeParamSpec = new PBEParameterSpec(salt, count);
pbeKeySpec = new PBEKeySpec(encryptedPassword.toCharArray());
keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
// Create PBE Cipher
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
// Initialize PBE Cipher with key and parameters
pbeCipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec);
byte[] decrypted = pbeCipher.doFinal(encryptedPassword.getBytes());
decryptedPassword = decrypted.toString();
} catch (BadPaddingException ex) {
System.out.println("EncryptDecrypt: " + ex.getMessage());
} catch (Exception ex) {
System.out.println("EncryptDecrypt: " + ex.getMessage());
}
return decryptedPassword;
}
}
在这里我应该能够成功解密密码,但没有。任何人都可以帮助我这里缺少什么吗?提前致谢。
最佳答案
这不是加密,而是哈希!(边缘射击)
该storePassword
例程有效地使用密码来加密自身;更准确地说,PBEwithMD5andDES
使用通过原始 PKCS5v1 派生函数从密码派生的 key (为了清晰起见,现在将其重新命名为 PBKDF1),使用 MD5、固定盐和 1 (!) 次迭代进行实例化,以使用原始 DES 进行加密CBC 密码。这是以前流行的创建加密哈希方法的变体。
在 20 世纪 60 年代和 1970 年代,也许还有 1980 年代,在密码学家将注意力转向设计特定的加密哈希函数之前,密码是唯一的加密原语,这是将密码(带 key 的排列)转换为加密哈希(无 key 的排列)的常见方法。 function) 是使用数据作为 key 来加密常量;它的一个细微变化是作为一个库函数实现的,错误地命名为crypt
并用作the password hashing function in early Unix大约 1970 年,至今仍被人们所铭记(有时甚至被使用),但现在经常被重新命名为 DES-crypt
或 descrypt
,以区别于此后开发的替代方案和替代方案。
与设计用于解密的密码不同,这是一个哈希值并且设计为不可逆。我不知道有什么方法可以比暴力破解(即分析“破解”)更容易地逆转此方法,但是原始 DES,现在通常称为单 DES(或 1DES),以区别于其直接后继三重 DES(或3DES 或正式的 TDEA)已经足够弱了,如果你真的愿意的话,现在可以进行暴力破解。例如JTR reports对于单盐解密,大约每秒 10M-30M 次尝试,这相当于简单 DES 的大约 0.5G/秒,因此尝试所有 DES key 对于一台计算机来说需要几年的时间,对于一千台计算机需要几天的时间,或者是几台计算机分钟与一百万台计算机。 hashcat 上的数据很难找到,但看起来大致可比。如果您知道如何选择密码,则仅尝试可能的密码而不是所有可能的 key 可能会更快。
但不要。 验证密码散列的正确方法是用户提供所声明的密码,使用相同的参数重复散列过程(这里很简单,因为它没有使用应有的可变盐),并查看新的哈希结果是否与存储的结果匹配。
关于java - 如何从加密密码中解密密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55788823/