I have written an entitity class with Field LoginId and Password.
Iam encrypting the passwrd and stoiring it in the db using the AES_ENCRYPT.
I want to retrive only the password which is decrypted. so, im using AES_DECRYPT using NAtiveQueryis in OPen JPA 2.0.
Query i have written is :
Query q = em.createNativeQuery("select AES_DECRYPT(l.password,?2) from loginDetails l where l.loginID = ?1");
q.setParameter(1, loginId);
q.setParameter(2, getKey());
String s = q.getSingleResult();
But im getting the following exception:
java.lang.ClassCastException: [B cannot be cast to java.lang.String
at com.rcs.chef.validation.UserValidation.decryptedPasswordForID(UserValidation.java:99)
at com.rcs.chef.validation.UserValidation.validateUser(UserValidation.java:81)
at com.rcs.chef.validation.UserValidation.activate(UserValidation.java:72)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.aries.blueprint.utils.ReflectionUtils.invoke(ReflectionUtils.java:226)
at org.apache.aries.blueprint.container.BeanRecipe.invoke(BeanRecipe.java:824)
at org.apache.aries.blueprint.container.BeanRecipe.runBeanProcInit(BeanRecipe.java:636)
at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:724)
at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:64)
at org.apache.aries.blueprint.container.BlueprintRepository.createInstances(BlueprintRepository.java:219)
at org.apache.aries.blueprint.container.BlueprintRepository.createAll(BlueprintRepository.java:147)
at org.apache.aries.blueprint.container.BlueprintContainerImpl.instantiateEagerComponents(BlueprintContainerImpl.java:640)
at org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintContainerImpl.java:331)
at org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintContainerImpl.java:227)
I have even tried this:
Query q = em.createNativeQuery("select AES_DECRYPT(l.password,?2) from loginDetails l where l.loginID = ?1");
q.setParameter(1, loginId);
q.setParameter(2, getKey());
List<Object> s = q.getResultList();
String s1 = null;
for(Object o : s){
s1= (String) o;
}
Even here also im gettng the same Exception as :
java.lang.ClassCastException: [B cannot be cast to java.lang.Object
Can you tell me what is the Mistake with the query adn handling the req.
Similar question: What kind of Java type is "[B"?
MySQL's AES_DECRYPT
does not return a String
but rather an array of bytes, denoted by "[B". Cast the result to byte[]
and build your string from that.
It looks like you don't even need to decrypt the password; you just want to validateUser
, right? - In that case, as others have noted, secure hashes should be used.
You can easily do this with MySQL, as it already provides the necessary functions: MD5 (considered insecure), SHA1 (pretty much standard), and SHA2 (even more secure than SHA1).
So your scheme basically may look like:
insert into loginDetails (..., passwordHashSalt, passwordHash) values ( ..., ?1, SHA1(CONCAT( ?1, ?2 )) )
, where ?1
is set to the unique 'salt', which may be for example the user name itself, and ?2
is the actual password. Note that the salt must be stored in the DB too and 'must' be unique for every user/password; thus, the user name is a natural choice for that.
Then, to verify a given password you can do:
select 'OK' from loginDetails where ... and passwordHash = SHA1(CONCAT( passwordHashSalt, ?1 ))
, where ?1
is the password which is to be verified.
For more information search the internet for 'password hashing', see for example here or here.
Those hashing operations may also be done in your database client code instead, if desired.