java.lang.ClassCastException: [B cannot be cast to java.lang.String
Asked Answered
T

1

8

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.

Threadfin answered 24/12, 2012 at 14:31 Comment(3)
Why use the database to do that when Java has libraries to do that for you?Delegation
Do not encrypt passwords. Passwords should be securely hashed; it should never be possible to retrieve a password.Enos
Why use Java libraries when the database provides this out of the box, so that the password doesn't even have to leave the db?Dimercaprol
D
10

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.

Dimercaprol answered 24/12, 2012 at 14:50 Comment(1)
Is encrypting the passwords and saving them using the DB functions not a good desing??Threadfin

© 2022 - 2024 — McMap. All rights reserved.