how to search encrypted data in grails - java

I have domain with 3 field cardNo, cardName and account
class card {
String cardNo
String cardName
Account account
static constraints = {
cardNo(blank:false, unique:true)
cardName(blank:false)
account(blank:false)
}
The cardNo must be encrypted when saved, I used encryptionUtil Java to encrypt it.
On my list screen, I want to make search fiture, which can be search by cardNo and cardName.
Is it possibe if I search data encrypted with create cretiria in grails??
If can't use create criteria, what is the best way to search encrypted data??
Need your help. thanks before :)

I can give you an advice: avoid store card numbers in your database. Use payment services for it.

Related

Memory Based Data Storage

I need to load instances of an Account class
class Account {
private String firstName;
private String lastName;
private String email;
...
}
to memory for a quick access. I can use a Java collection class to store the data. I also need to search the data. Since the email address needs to be unique, I am thinking of using map with an email address as the key. That approach won't help if searching the first name and last name are required. I can use filters for searching on first name and last name.
Any better approach?
You can maintain several different Java collections or use in-memory databases with better searching capabilities or Java object databases.
However, see also Coollection. It's interesting.
If you want to search for stuff, you want to use an indexed collection like Data Store:
https://github.com/jparams/data-store
Example:
Store<Account> store = new MemoryStore<>() ;
store.add(new Account("Ed", "Smith", "ed.smith#gmail.com"));
store.add(new Account("Fred", "Smith", "fred.johnson#hotmail.com"));
store.add(new Account("Freda", "Pinto", null));
store.index("firstName", Account::getFirstName);
store.index("lastName", Account::getLastName);
Account ed = store.getFirst("firstName", "Ed");
Account smiths = store.get("lastName", "Smith");
With data store you can create case-insensitive indexes and all sorts. If you are doing a lot of lookups, you definitely want to use a library like this.

Login Function Improvement and Solve Looping Issue

I am new. Trying to do a database retrieve demo to login a system, here is my function code:
I will call goLogin function and pass in the input id and password for validation and I will also get all the id from Database for checking purpose. After ID is correct, only go check the password.
public void goLogin(String id, String pass){
String[99] allID = getAllIDFromDB();
for(int i=0;i<allID.length;i++){
if(allID[i]==id){
String passwordDB = getPasswordFromDB(id);
if(pass==password){
System.out.println("Correct Password");
}else{
System.out.println("Wrong Password");
}
}
}
My peers say I was using too much if else and I can shorten the code and make the program better, and I faced some issue on looping for example when ID and Password are correct, the program will still continue the loop.
Is there any suggestion to make this function better?
First of all, Why retrieve all the user IDs from the database instead make sql query to retrieve the row of this user based on this id.
something like this:
Select * from `users` where id = {id};
And if you want to stop looping a wrong password was found, add break in the else scope.
In my opinion, the main issue of your program is your logic to implement the Login Function.
Login Function implementation can be implemented with various pattern, Based on your program code I will assume you just want a Most Basic Login Function that allow the program to do validation on user input ID and Password.
Actually, this Basic validation can be done in your Database Query. You can just take the user input ID and Password and let Database Query to do filtering and determine if the user input ID and Password is valid or invalid.
First use this Query:
Select DATABASEID From Database Where DATABASEID=inputID and DATABASEPASSWORD=inputPassword;
Java Code:
public void goLogin(String id, String pass){
// Since i changed the Query, you need to pass in the ID and Password to let the Query to filtering
String DatabaseID = getIDFromDB(id, pass);
// Simple Logic, If DatabaseID have value which mean the ID and Password is correct
// Because the Database Query will return null if the ID and Password is Wrong
if(DatabaseID!=null){
System.out.println("ID and Password is Correct.");
}else{
System.out.println("ID or Password is Incorrect.");
}
}
This Logic is very simple, but also come with some drawback, the only Advantage Compare to your code are:
Still able to do basic validation on User Input ID and Password.
Remove for loop and other unnecessary if else.
Only access database for once.
Hope this would help.
Yes, you could even do:
Select * from `users` where id = {id} and password = {password}
Also, to compare Strings in Java, you should use string1.equals(string2), not the == operator.

Sha1 hashed string correctly encoded in mysql but displayed differently as a Java string

I am currently developping a java program coupled with a mysql database using the Dao pattern. I have some user info to be stored in a table and I am storing a Sha1 hashed version of the original password string. I am using apache.commons.codec.digest.DigestUtils to do that. The string displayed in php-mysql is perfect, but when I am trying to display the same string in a java test program I have a completely different result.
Here is my constructor for the user object :
public User(int id, String name, String firstName, String email, String login, String password)
{
super(id, name, firstName);
this.email = email;
this.login = login;
//Convert the password to SHA1 before storing it in the object
//using Apache commons-codec-1.9 lib
this.hashedPassword = DigestUtils.sha1Hex(password);
}
So for example when creating a User with "aff" as the password,
by
User user1 = new User(1, "Durand", "Jack", "jack.durand#mymail.com", "jack", "aff");
I get
"0c05aa56405c447e6678b7f3127febde5c3a9238" in mysql which looks correct, and the same as the output of online sha1 hashers.
But when reading the data back into an object and displaying it by a Sysout(User.getPassword()) in java I get
"c14b77e8930a8bfd884c8917f2b7335501a39dde" which obviously isn't the same.
Any idea of what's causing this? I have read some previous posts about a Byte[] issue, but the DigestUtils.sha1Hex(password) method is said to return a plain String. So what am I missing?
Everything you did is correct.
"0c05aa56405c447e6678b7f3127febde5c3a9238" is the correct output.
I would suspect MySQL is being updated between reads.
My suggestion would be, check if the value "0c05aa56405c447e6678b7f3127febde5c3a9238" is actually being saved to MySQL. Break the workbench open and access the row to check its value.
If the value in MySQL is correct then it is in the transformation from RDBMS -> Java. If you defined the attribute password as a String then Hibernate (or whatever you are using) should leave the field as is.

How can I make AccountManager handle multiple accounts per username?

I would like to use Android's built-in AccountManager to handle accounts for our native Android app. However, we have a peculiar need.
It appears that Android's concept of an Account is a combination of name (i.e. MazerRackham#example.com) and type (i.e. com.example). Name is the username you login with. Type is associated with your application or company.
However, our REST backend allows a single user to have multiple accounts and each account must be accessed by its own unique hash tied to the combination of one username and one account number (in addition to type).
I already have the AccountAuthenticator, AuthenticationService, and AccountAuthenticatorActivity working for a single user with a single account number and single stored hash. Is there any way in which I could implement my AccountAuthenticator to handle users with multiple accounts under the same username, each requiring a hash? Would it be possible to attach a delimiter to the username and split it into username and account number every time I use it?
If I cannot figure out a way to handle this, how should I gracefully fall back during AbstractAccountAuthenticator.getAuthToken? Would it make sense to set the hash to a special flag value and use legacy login methods for that user? Or is that too much of a hack?
Thanks for your help!
If you don't mind the hash being public, you can certainly make the account name username|hash (or whatever separator you want) - the system does not care what you use for an account name except that it uniquely defines a user.
I ended up serializing the data into the username using an at sign (#) as a delimiter. I chose the at sign because it's the only restricted character in an e-mail address that should only be used exactly one time.
Here is the code from getAuthToken in my AccountAuthenticator which gets called only if I need to obtain a fresh token for that user and account id:
/*
*
* The login params need to handle users with multiple accounts under the same username.
*
* Since Android's AccountManager does not allow multiple accounts per username, I had
* to create a hack which joins and splits the username on a delimiter to serialize the
* data and retrieve the account number for users with multiple accounts. I chose the #
* sign as a delimiter because e-mail addresses have VERY few invalid characters in
* the account name part of the address.
*
* If the user has multiple accounts, we need to create each one in AccountManager.
*
* */
String[] accountParts = account.name.split("#");
numParts = accountParts.length;
if (numParts<2) {
Log.wtf(Config.TAG, "Username split produced too few parts. WTF.");
return null;
}
String email = accountParts[0] + "#" + accountParts[1];
if (numParts==3) {
String account_id = accountParts[2];
} else if (numParts>3) {
Log.wtf(Config.TAG, "Username split produced too many parts. WTF.");
return null;
}

matching user's password from record in db

In my web app which uses servlets and hibernate. I need to authenticate a Customer who enters a password.
If he is already in database, I need to check if his password matches that of the record in db.For a new Customer, I want to take a password and create a record for him.
I tried to do it this way for the scenarios.
Existing Customer enters an emailAddress and password
String email = req.getParameter("emailAddress");
String password = req.getParameter("password");
Customer cust = dao.findByEmailAddress(email);
Now, how do I check if this cust object is associated with a password and that matches what the user entered? Manning's hibernate book example stores password as a String in Customer class. Is this a good idea? How will this be stored in database?
When using hibernate, how can this be handled? I have heard people mentioning about storing passwords as hash. But I am not very sure how I can do this in my app.
Can someone tell me how I can tackle this?
Storing plain text passwords is never a good idea. In fact it is listed as #8 threat in the Top 25 Most Dangerous Software Errors.
You need to encrypt the passwords before writing them in the database. When searching for a user use the encrypted password
String email = req.getParameter("emailAddress");
String password = req.getParameter("password");
String encryptedPassword = MD5Helper.hashPassword(password)
Customer cust = dao.findByEmailAddressAndPassword(email, encryptedPassword);
You can use something like this to encrypt the passwords using the MD5 algorithm.
public class MD5Helper {
private static final int MD5_PASSWORD_LENGTH = 16;
public static String hashPassword(String password) {
String hashword = null;
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(password.getBytes());
BigInteger hash = new BigInteger(1, md5.digest());
hashword = hash.toString(MD5_PASSWORD_LENGTH);
} catch (NoSuchAlgorithmException nsae) {
// handle exception
}
return hashword;
}
}
You have to decide how to store passwords. If you store them as a String in a Hibernate entity, they will be stored in a varchar in database, in clear text. Anyone having access to the database will thus be able to see them. Authenticating in this case consists in comparing the sent password with the one in database.
There are two other possibilities
The first one consists in encrypting them with a secret key before storing them in database. But this secret key will have to be stored somewhere in order for your application to decrypt them and compare the decrypted password with the one sent by the user. But it could at least reduce the visibility of the password only to the persons having acces to the application deployment directory. Authenticating in this case consists in decrypting the password stored in database with the secret key, and compare it with the password sent by the user. If they are equal, then the user sent the correct password.
The last possibility would be to use a one-way hash algorithm (like SHA-1, for example), also known as message digest algorithm. This way, there is no need for a secret key, and it would be very hard (read : nearly impossible) for anyone to get access to the password (if the password is salted). The drawback of this solution is that if a user looses his password, you won't be able to send him. The only possibility is to reset him to a new value, send this new password to the user and ask him to choose a new one. Authenticating the user, in this case, consists in hashing the password he sends and comparing with the hash stored in database.
Read http://en.wikipedia.org/wiki/Salt_(cryptography) for more detailed explanations.
Usually password are stored encrypted in a database and you have to encrypt the input password to check if it matches.
String passwordEncrypted = encrypt(password);
where encrypt is your function that crypt the password (you can try with MD5 or SHA-1, for example).
After you've retrieved your object cust, you can check if
if (cust.getPassword().equals(passwordEncrypted)) {
// login successfull code
} else {
// login failed code
}

Categories

Resources