我正在尝试使用一种登录方法来确保客户端密码在我的服务器中安全并加密。
我在 Angular 使用的库是 https://github.com/middleout/angular-cryptography
我们的想法是,遵循以下步骤:
我在 module.config 中设置了盐:
app.config(['$cryptoProvider', function($cryptoProvider){ $cryptoProvider.setCryptographyKey('thisismysalt'); }]);
我用自身加密密码:
user.pw = $crypto.encrypt(user.pw, user.pw);
如果我要注册用户,我会使用自身重新加密密码(重复步骤 2)并将其保存在数据库中。如果我正在记录,我只需将最后一步的结果发送到服务器。
当您用单次加密的字符串解密双重加密的字符串时,您将再次获得单次加密的字符串。因此,如果您的密码正确,您只需将结果与单一加密的字符串进行比较,即可验证用户。
好的,这个方法应该可行(我之前已经在 Node 中做过了),与 SSL 配合使用,即使在您的服务器中也可以保护用户的密码!
但是我在 Java 中找不到任何可以做到这一点的库或代码片段。我尝试了很多方法,但它们很难理解,当我将它们适应我的程序时,它们就行不通。我尝试了以下方法:
static String IV = "AAAAAAAAAAAAAAAA";
static String plaintext = "test text 123\0\0\0"; /*Note null padding*/
static String encryptionKey = "0123456789abcdef";
public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
return new String(cipher.doFinal(cipherText),"UTF-8");
}
我将其作为第一个参数(来自数据库的双重加密密码)传递,作为第二个参数传递(来自前端的单次加密密码):
java.security.InvalidKeyException: Invalid AES key length: 44 bytes
我做错了什么吗?我应该使用不同的算法吗?
最佳答案
middleout/Angular-cryptography 使用 CryptoJS 3.1.2 under the hood with the least effort possible .
所以
return $crypto.encrypt(plaintext, password);
与
相同$cryptoProvider.setCryptographyKey(password);
return $crypto.encrypt(plaintext, password);
与
相同return CryptoJS.AES.encrypt(plaintext, password).toString();
我在回答中描述here如何在 Java 中做同样的事情。
<小时/>如果您使用 SSL/TLS,额外进行此加密并没有多大好处。密码已通过互联网以加密方式发送。更糟糕的是,由于密码必须在服务器端可用,因此必须以明文形式存储密码。 事实并非如此。
您需要使用哈希来代替一些强大的哈希,例如 PBKDF2、bcrypt、scrypt 和 Argon2。由于哈希函数是单向函数,因此您将无法“解密”哈希值。为了验证您的用户身份,您可以再次通过哈希函数运行密码,以便与存储在数据库中的哈希进行比较。由于您已经在使用 SSL/TLS,因此密码在传输过程中已经受到保护。查看更多:How to securely hash passwords?
关于从 Angular-Cryptography 解密 AES 字符串的 Java 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39610952/