How to map the byte [] property to Hibernate?

I am using Hibernate / Java to store an object in a database. The object has a password field, which is a String . When registering a user in my application, I use a password using SHA-1 (I admit that this is a little weak). This creates byte [] , which is then converted to String using new String(byte[] arr); Whenever I want to log in, I simply retrieve the hashed password from the database (like String ) and compare it with the password of the login password at login using hashedPasswordFromDatabase.equals(SHA1_HASH(inputPassword));

This worked fine on my development system (Windows 7, JDK 1.6.0_23 / JDK 1.7, MySQL 5.5, Tomcat 6.0.26), but after deploying it to our server (running JDK 1.6 on Linux), the equals method never evaluates to TRUE even for equal passwords. I quickly set up a new development system (Ubuntu 12.04, MySQL 5.5, JDK 1.7.0_03, Tomcat 7.0.22), and it also does not work.

I know the possible encoding problems mentioned in the Java API documentation for the String class, as well as in several places here in SO. I tried a couple of the encodings suggested in this forum (e.g. Base64, Latin-1), and I ended up with a UnsupportedEncodingException . I think I better avoid string conversion. So, how do I create my database so that the entity class generated by Hibernate includes byte [] for the password field instead of String ?

+7
source share
3 answers

Yes, the problem is most likely to convert byte[] to String . You should know that SHA creates a raw byte array, and there is no guarantee that an arbitrary byte[] will produce a valid String , regardless of encoding. Thus, your code only worked by accident.

Avoid the problem in general:

  • storing raw byte[] in a BLOB is the safest and most efficient way to store data. In Hibernate, just use the byte[] property on your POJO.

  • encode byte[] with (check Decode Base64 data in Java ) and save it as a string.

BTW remember salt !

+5
source

In my case, a poor database design forces me to use Blob in the case of Clob. The solution was to Map in the hibernate property with Lob annotation and put another property in the String type.

At another level of code, when I call get or set, I use the String property and this one, get or set the value of the byte array.

 @Entity @Table(name = "CMUN_TAGS") @SequenceGenerator(name = "idSeqTag", sequenceName = "SEQ_CMUN_TAGS") public class CmunTagsDO implements java.io.Serializable { private BigDecimal lngIdTag; private byte[] blobValTag; private String strValTag; @Id @Column(name = "LNG_ID_TAG", unique = true, nullable = false, precision = 20, scale = 0) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "idSeqTag") public BigDecimal getLngIdTag() { return this.lngIdTag; } public void setLngIdTag(BigDecimal lngIdTag) { this.lngIdTag = lngIdTag; } @Column(name = "BLOB_VAL_TAG", nullable = false) @Lob public byte[] getBlobValTag() { return this.blobValTag; } public void setBlobValTag(byte[] blobValTag) { this.blobValorTag = blobValorTag; } @Transient public String getStrValTag() { strValTag = new String(getBlobValTag()); return strValTag; } public void setStrValTag(String strValTag) { setBlobValTag(strValTag.getBytes()); this.strValTag = strValTag; } } 
+1
source

You can convert your byte to hexadecimal representation as follows:

 public String encryptPassword(String passwordInClear) { // Salt all you want here. MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); byte[] digest = sha256.digest(passwordInClear.getBytes()); return digestToString(digest); } private String digestToString(byte[] digest) { StringBuilder hashString = new StringBuilder(); for (int i = 0; i < digest.length; i++) { String hex = Integer.toHexString(digest[i]); if (hex.length() == 1) { hashString.append('0'); hashString.append(hex.charAt(hex.length() - 1)); } else { hashString.append(hex.substring(hex.length() - 2)); } } return hashString.toString(); } 
0
source

All Articles