I'm using Hibernate/Java to persist an entity to a database. The entity has a password field which is a String. When registring a user in my application, I hash the password using SHA-1 (I acknowledge this is a little weak). This produces a byte[] which I then convert to String using
new String(byte[] arr);
Whenever I want to log a user in, I simply retrieve the hashed password from the database (as String) and compare it with the digest of the input password at login using
hashedPasswordFromDatabase.equals(SHA1_HASH(inputPassword));
This worked perfectly on my development system (Windows 7, JDK 1.6.0_23 / JDK 1.7, MySQL 5.5, Tomcat 6.0.26) but upon deploying it on our server (running JDK 1.6 on Linux), the equals method never evaluates to TRUE even for equal passwords. I quickly setup a new development system (Ubuntu 12.04, MySQL 5.5, JDK 1.7.0_03, Tomcat 7.0.22) and it doesn't work there too.
I'm aware of the possible encoding issues stated in the Java API documentation for the String class and also stated in several places here on SO. I've tried a couple of encodings suggested on this forum (e.g Base64, Latin-1) and I ended up with UnsupportedEncodingException. I think I'll be better off avoiding the String conversion. So how do I design my database such that the Hibernate-generated entity class comes up with byte[] for the password field instead of String?
The @Lob annotation specifies that the database should store the property as Large Object. The columnDefinition in the @Column annotation defines the column type for the property. Since we're going to save byte array, we're using BLOB.
There are two ways to convert byte array to String: By using String class constructor. By using UTF-8 encoding.
We can use the @Basic annotation to mark a basic type property: @Entity public class Course { @Basic @Id private int id; @Basic private String name; ... } In other words, the @Basic annotation on a field or a property signifies that it's a basic type and Hibernate should use the standard mapping for its persistence.
@Entity annotation marks this class as an entity. @Table annotation specifies the table name where data of this entity is to be persisted. If you don't use @Table annotation, hibernate will use the class name as the table name by default. @Id annotation marks the identifier for this entity.
Yes, the problem is most likely in byte[]
to String
conversion. You must know that SHA produces raw byte
array and there is no guarantee that arbitrary byte[]
will produce valid String
, irrespective to encoding. Thus your code was only working by accident.
Avoid the problem altogether by:
storing raw byte[]
in BLOB - the safest and most storage-effective way. In Hibernate just use byte[]
property on your POJO.
encode byte[]
using base64 (check out Decode Base64 data in Java) and store it as a string.
BTW remember about salting!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With