2016-12-21 51 views
0

我试图创建我自己的小程序以获得乐趣,该程序允许用户创建用AES加密的用户名/密码,然后存储用户名,加密的密码以及MySQL数据库中的密钥。我未来的计划是允许用户通过从数据库中检索这些信息并将其解密以检查数据库的登录信息来“登录”。试图在MySQL中通过JDBC存储SecretKey,加密密码

目前,我已经掌握了Java中的所有加密/解密功能。我已经使用各种输入来测试它,并且我知道这些方法都可以正常工作。我遇到的问题涉及将这些信息存储在MySQL数据库中。我能够连接到数据库并执行SELECT查询,但是当我使用INSERT语句来存储信息时,出现错误。

这里是我的MySQL数据库的设置:

mysql> SHOW COLUMNS FROM Accounts; 
+----------+-------------+------+-----+---------+----------------+ 
| Field | Type  | Null | Key | Default | Extra   | 
+----------+-------------+------+-----+---------+----------------+ 
| id  | int(11)  | NO | PRI | NULL | auto_increment | 
| username | varchar(45) | NO | UNI | NULL |    | 
| password | blob  | NO |  | NULL |    | 
| key  | blob  | NO |  | NULL |    | 
+----------+-------------+------+-----+---------+----------------+ 
4 rows in set (0.00 sec) 

这里是有问题的代码:

public static void main(String[] args) throws Exception { 

    String plainText = "test"; 
    SecretKey secKey = getSecretEncryptionKey(); // working correctly 
    byte[] cipherText = encryptText(plainText, secKey); // working correctly 
    String decryptedText = decryptText(cipherText, secKey); // working correctly 
    byte[] secKey2 = secKey.getEncoded(); // necessary?? 

    try{ 
     Class.forName("com.mysql.jdbc.Driver"); 
     Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/Test?useSSL=false","****","****"); // user/pass commented out 
     Statement stmt = con.createStatement(); 
     ResultSet rs = stmt.executeQuery("use Test;"); 
     stmt = con.createStatement(); 
     stmt.executeUpdate("INSERT INTO Accounts (username, password, key) VALUES ('test1', '"+cipherText+"', '"+secKey2+"');"); 
     con.close(); 
    } catch(Exception e){ 
     System.out.println(e); 
    } 

} 

的错误,我得到:

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key) VALUES ('test1', '[[email protected]', '[[email protected]')' at line 1 

我使用的架构在我的数据库中被称为“测试”。 “使用测试”查询似乎工作。

在上面的例子中,“test1”是用户名,cipherText是散列密码,secKey2是编码成字节数组的密钥。

我已经试过这样做,无论是否将密钥转换为字节数组,因为我读过最好将密钥转换为字节数组并存储为blob。我也尝试过使用'password'和'key'字段作为VARCHAR。我没有包括加密/解密的方法,因为我知道它们正常工作,问题是将信息存储在数据库中。

任何帮助将不胜感激!

+0

您好,欢迎计算器!您能否向我们提供关于您遇到的错误的更多具体信息? – Maurice

+0

我得到的错误是正确的Java代码的下面包括在内。我使用Eclipse,这是我看到的唯一错误输出。 – JAM1295

+0

你应该散列密码,而不是加密它们。 – EJP

回答

1

@Jose_Ferrer的回答完全正确地指出了代码的一些问题(例如:你正在存储字节数组的地址而不是计算出来的散列)。

但是,您所遇到的语法错误消息不直接相关的:你最终会与数据库中存储的无用的字符串,但是这不是数据库可抱怨的。

语法错误似乎是由于“钥匙”保留字的用法作为表的字段。 SQL解析器抱怨找到一个关键字(关键字),它期望一个字段名称。

+0

没有看到那个。接得好! –

+0

啊,我相信固定它,谢谢!我确实知道你和何塞在说什么,而我其实本来就是要按照你的建议去做。我已经改变了我的代码,它运行良好。谢谢您的帮助! – JAM1295

1

在根目录中,您试图将两个字节数组存储在适当的列中。您看到的问题是由您用来创建插入语句的字符串连接引起的。当你说 "INSERT INTO Accounts (username, password, key) VALUES ('test1', '"+cipherText+"', '"+secKey2+"');" 你真正想说的是 "INSERT INTO Accounts (username, password, key) VALUES ('test1', '"+cipherText.toString()+"', '"+secKey2.toString()+"');" 那些[B @ 735b478和[B @ 2c9f9fb0值(有效)指针地址,这些阵列,因为这是默认的Object.toString()实现。

您不应该通过字符串连接创建SQL语句。在打开SQL Injection之前,您最终会看到难以阅读和维护的代码。使用PreparedStatement而不是声明,这将允许您使用setBlob()方法。但不知道如何从byte[]中获得Blob。你也可以将Base64编码为byte[]并将它们存储为变种,但这是另一个话题。

至于是否应该在数据库中以任何形式的可逆形式存储密码,请参阅here

+0

我要澄清,在“密码”我说的是哈希和盐渍的密码,而不是明文密码。纯文本一旦被散列就会被抛弃。 – JAM1295