这是我在stackoverflow上的第一篇文章,如果不是那么好对不起。我是一个相对优秀的Java程序员,我目前正在制作一个新的密码存储程序。要做到这一点,我使用的是MySQL和Java。我将它存储在便携式(SQLite)数据库中。但是我的问题是,当我的安全性更加安全时,它就失败了。在我将密码放入数据库之前,我将其加密以保证安全性,然后在加密的末尾(现在)添加一个更安全的字符串。我知道我可能不应该告诉你这个但我会在得到一些帮助之后改变它。我的问题是,当我将两个字符串加在一起时,它可以工作。然后我尝试删除第二个字符串(用于解密),除了字节不等于16,所以我无法解密我的密码。我知道将字符串转换为字节有几个问题,除了这个是不同的。我的代码如下。
public static String upload(String password, String username, String website) throws Exception, GeneralSecurityException{
//Generates the encryption
String key = "dcW2znalixOYi7jt";
byte[] encrypted = Encryption.encrypt(key, password);
String encryption = "syfs8yy48y3483434tg4";
String encryptionfinal = encrypted + encryption;
if(encryptionfinal.contains(encryption)){
System.out.println("LOL FAILURE");
System.out.println(encrypted);
String test = encryptionfinal.replace(encryption, "");
System.out.println(encryptionfinal);
System.out.println(test);
byte[] atest = test.getBytes();
System.out.println("Length Of Byte From Test:");
System.out.println(atest.length);
System.out.println("Length Of Byte From Key:");
System.out.println(key.length());
System.out.println("Length Of String Test:");
System.out.println(test.length());
System.out.println("Length Of Encryption:");
System.out.println(encrypted.length);
System.out.println("Length Of EncryptionFinal:");
System.out.println(encryptionfinal.length());
System.out.println("Length of encryption addon:");
System.out.println(encryption.length());
System.out.println("Length of encryption final - encryption addon:");
System.out.println(encryptionfinal.length() - encryption.length());
String decrypted = Encryption.decrypt(key, atest);
System.out.println(decrypted);
}
String sDriverName = "org.sqlite.JDBC";
Class.forName(sDriverName);
String sTempDb = "passwords.db";
String sJdbc = "jdbc:sqlite";
String sDbUrl = sJdbc + ":" + sTempDb;
Connection conn = DriverManager.getConnection(sDbUrl);
String sql = "INSERT INTO information " + "VALUES ("+null+",'"+encryptionfinal+"', '"+username+"', '"+website+"');";
String insert = "CREATE TABLE IF NOT EXISTS 'information' ('id' INTEGER DEFAULT '0' PRIMARY KEY AUTOINCREMENT,'password' TEXT NOT NULL,'username' TEXT NOT NULL,'website' TEXT NOT NULL);";
try {
Statement stmt = conn.createStatement();
stmt.executeUpdate(insert);
stmt.executeUpdate(sql);
stmt.close();
}
finally{
}
return null;
}
问题在于,当我运行它时,它说
> LOL FAILURE
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
[B@2b8898c5
[B@2b8898c5syfs8yy48y3483434tg4
[B@2b8898c5
Length Of Byte From Test:
11
Length Of Byte From Key:
16
Length Of String Test:
11
Length Of Encryption:
16
Length Of EncryptionFinal:
31
Length of encryption addon:
20
Length of encryption final - encryption addon:
11
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:913)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
at javax.crypto.Cipher.doFinal(Cipher.java:2121)
at me.thomasjcf21.SecurePassword.Encryption.decrypt(Encryption.java:38)
at me.thomasjcf21.SecurePassword.MySQL.upload(MySQL.java:37)
at me.thomasjcf21.SecurePassword.Program$3.actionPerformed(Program.java:90)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$400(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
请忽略“LOL失败”,这是一个测试,看看它是否在之前工作。
谢谢,
托马斯
答案 0 :(得分:1)
当您持久保存真实用户密码(我假设您正在做的事情)进行身份验证时,您只需要存储密码哈希,并且您应该在加密之前添加之前的,而不是之后。 Bellow是MD5的一个例子,但是还有其他用于Java的哈希生成算法。
String saltedPassword = password + salt;
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(saltedPassword .getBytes());
byte byteData[] = md.digest();
一般的良好做法是为每个用户创建单独的盐。您永远不会解密哈希,只有在用户输入验证密码时才会再次比较它。
现在,如果您正在加密并存储 需要检索 的密码,比如数据库密码,或者甚至是真正的用户,为什么不加密,您不需要盐。对称或非对称算法就足够了。我个人总是在需要时使用AES 256,Java也支持它。
要正确存储和检索它,您需要对算法/ Java API返回的生成字节进行编码,并且我个人总是使用 Base64 。
{8}来自Java 8,但它也可以在更早版本中使用。如果需要,也可以使用Apache实现。
Base64.getEncoder().encodeToString(encryptedPasswordArray);
我认为这可以帮助您解决问题,但如果您有任何其他问题,请告诉我们。