【问题标题】:Trying to Store SecretKey, Encrypted Password in MySQL through JDBC尝试通过 JDBC 在 MySQL 中存储 SecretKey、加密密码
【发布时间】:2016-12-21 21:23:36
【问题描述】:

我正在尝试创建自己的有趣小程序,它允许用户创建一个用户名/密码,然后使用 AES 对其进行加密,然后将用户名、加密密码和密钥存储在 MySQL 数据库中。我未来的计划是允许用户“登录”,方法是从数据库中检索此信息并对其进行解密,以对照数据库检查登录信息。

目前,我已经在 J​​ava 中使用了所有的加密/解密功能。我已经使用各种输入对其进行了测试,并且我知道这些方法都可以正常工作。我遇到的问题涉及将此信息存储在 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', '[B@735b478', '[B@2c9f9fb0')' at line 1

我在数据库中使用的架构称为“测试”。 “使用测试”查询似乎确实有效。

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

我尝试过将密钥转换为字节数组和不转换为字节数组,因为我读到最好将密钥转换为字节数组并存储为 blob。我也尝试过将“密码”和“密钥”字段作为 VARCHAR。我没有包含加密/解密的方法,因为我知道它们可以正常工作,问题是将信息存储在数据库中。

任何帮助将不胜感激!

【问题讨论】:

  • 您好,欢迎来到 stackoverflow!您能否向我们提供有关您遇到的错误的更具体信息?
  • 我得到的错误包含在 Java 代码的正下方。我正在使用 Eclipse,这是我看到的唯一错误输出。
  • 你应该散列密码,而不是加密它们。

标签: java mysql database encryption jdbc


【解决方案1】:

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

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

语法错误似乎是由于使用“key”保留字作为表的字段。 SQL 解析器抱怨在需要字段名称的地方找到关键字(键)。

【讨论】:

  • 没看到那个。好收获!
  • 啊,我相信修好了,谢谢!我确实知道你和何塞在说什么,我原本打算按照你的建议去做。我现在已经更改了我的代码,并且运行良好。感谢您的帮助!
【解决方案2】:

在根目录中,您尝试将两个字节数组存储到适当的列中。您看到的问题是由您用于创建插入语句的字符串连接引起的。当你说 "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 而不是Statement,这样您就可以使用setBlob() 方法。不知道如何从byte[] 中获得Blob。您还可以对 byte[] 进行 Base64 编码并将它们存储为 varchars,但这是另一个话题。

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

【讨论】:

  • 我应该澄清一下,“密码”是指散列和加盐密码,而不是纯文本密码。纯文本在散列后被丢弃。
猜你喜欢
  • 2016-07-19
  • 2014-06-23
  • 2014-09-16
  • 1970-01-01
  • 2011-12-04
  • 2011-06-17
  • 2014-12-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多