how to get/set the salt for a JdbcRealm - java

I am attempting to use the Shiro JdbcRealm and SHA256 hashedcredentialsMatcher. I need to update a legacy database and assign the appropriate salt for each user (via a batch routine).
how do I get/set the salt for a given account using the Shiro framework?

With Shiro 1.2.3 all you need to do is:
Extend JdbcRealm and set salt style.
public class JdbcSaltRealm extends JdbcRealm {
public JdbcSaltRealm() {
setSaltStyle(SaltStyle.COLUMN);
}
}
Update shiro.ini to use extended realm and to get salt column from DB
credentialsMatcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher
credentialsMatcher.hashAlgorithmName = SHA-256
jdbcRealm = com.mypackage.JdbcSaltRealm
jdbcRealm.authenticationQuery = SELECT password, salt FROM user WHERE username = ?
jdbcRealm.credentialsMatcher = $credentialsMatcher
Hash & salt current / new user passwords. This should be done for all existing users as well as on new user registrations.
private void saltHashPassword(String password) {
String salt = new BigInteger(250, new SecureRandom()).toString(32);
//TODO: save salt value to "salt" column in user table
Sha256Hash hash = new Sha256Hash(password,
(new SimpleByteSource(salt)).getBytes());
String saltedHashedPassword = hash.toHex();
//TODO: save saltedHashedPassword value to "password" column in user table
}
I hope my answer is clear and understandable.

Maybe a bit late:
Have a look at this tutorial.
Meri, the guy who owns the blog, describes exactly how to create an own salted JDBC Realm.
This is also an acknowledged improvement in the community for version 1.3.0 .
Hope this helpes, have Fun!

Related

In what form to store salt and how to retrieve it later for password validate

I use MD5 algorithm to hash passwords with salt. After registering a user, I store both hashed password and salt in my SQL database. Unfortunately, when I retrieve them, later, so as to compare them with the user's input I address a problem with the encoding of salt. I store salt as VARCHAR(16) and when I try to retrieve it from my DataBase, it converts in a different form. This is my code :
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
String DB_salt1 = rs.getString("Salt");
byte [] DB_salt = DB_salt1.getBytes();
I used some System.out.println(); functions in order to locate the problem and I found out that byte [] DB_salt = DB_salt1.getBytes(); outputs the wrong salt, while String DB_salt1 = rs.getString("Salt"); outputs the proper one. My guess is that it happens byte loss.
EDIT: To clarify, the proper salt and the one stored in my DataBase, let's say is [B#4e25154. String DB_salt1 = rs.getString("Salt"); stores this salt; the proper one. But when byte [] DB_salt = DB_salt1.getBytes(); is executed, it outputs a different salt, which ruins the whole process.
The best way to store the passwords in the Database is using Bcrypt. With this you don't need to store the salt.
Below is the sample code that uses Bcrypt.
1) String pw_hash = BCrypt.hashpw("PLAIN PASSWORD", BCrypt.gensalt());
2) Store the pw_hash in DB
3) if(BCrypt.checkpw("PLAIN PASSWORD", pw_hash)){ System.out.println("Success Login"); }else{ System.out.println("Failure Login"); }
Steps 1 and 2 will be followed while user registering the password for the first time. While Step 3 is used if the given password is matching with the encrypted password.

Using MySql PASSWORD() function from hibernate

I'm rewriting old java desktop swing app to JSF application using PrimeFaces.
The old app didn't use hibernate but I have decided to use it in new app. Everything works fine but the problem is when I want to save passwords with hibernate using MySql’s function password().
Is there a way to do this because it would be nice if I could import data from old database to new database without changing passwords.
I managed to bring login to work using this code snippet:
public User login(String username, String password) {
User result = null;
Session session = HibernateUtil.getSessionFactory().openSession();
try {
String sql = "select s from User where username=:username and password=password(:password)";
Query query = session.createQuery(sql);
query.setString("username", username);
query.setString("password", password);
result = (User) query.uniqueResult();
if (result != null) {
Hibernate.initialize(result.getUserData());
}
}
finally {
session.close();
}
return result;
}
But here is problem with registration of new users since I don't know how store passwords. The code I’m using to save users to database looks like:
public User addUser(User obj) {
Session session = HibernateUtil.getSessionFactory().openSession();
try {
session.save(obj);
session.flush();
}
finally {
session.close();
}
return obj;
}
I know I could write the whole insert statement the old fashioned way but what’s the point of using hibernate then and the code would look ugly. Also I’m not happy with login snippet as well.
I’ve also tried to update password with trigger after insert but I kept getting error:
Updating of NEW row is not allowed in after trigger
So I abandoned this approach since its ugly and it doesn’t work.
Should I just use jasypt or any other library to encrypt password in applications and be done with it? Or is there an elegant solution to my problem.
The MySql function password() should not be used at all for hashing passwords! From the documentation:
The PASSWORD() function is used by the authentication system in MySQL
Server; you should not use it in your own applications.
The calculation is fast and unsalted, which makes it very unsecure. Instead leave the hashing to the server side language and use a library which uses a slow hash function with a cost factor like BCrypt, PBKDF2 or SCrypt. A wellknown library for Java is jBCrypt.
Using Jasypt EncryptedStringType is much more convenient, since you delegate the password hashing to the UserType.
This way your application logic doesn't have to deal with password related responsibilities (like it's the case of your SELECT using the non-portable PASSWORD SQL function).
The UserType will also take care of hashing the actual password for an INSERT/UPDATE too.
So, Jasypt is a much better alternative.

How to store hashed pws into a db with Apache Shiro?

I have been looking all over the place with no luck to what I am trying to do.
I am looking to hash and salt my user passwords and store them into the DB. The issue is, how do I store them?
I have looked at this http://shiro.apache.org/realm.html#Realm-authentication which I have found similar answers, but it doesn't make sense.
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
...
//We'll use a Random Number Generator to generate salts. This
//is much more secure than using a username as a salt or not
//having a salt at all. Shiro makes this easy.
//
//Note that a normal app would reference an attribute rather
//than create a new RNG every time:
RandomNumberGenerator rng = new SecureRandomNumberGenerator();
Object salt = rng.nextBytes();
//Now hash the plain-text password with the random salt and multiple
//iterations and then Base64-encode the value (requires less space than Hex):
String hashedPasswordBase64 = new Sha256Hash(plainTextPassword, salt, 1024).toBase64();
User user = new User(username, hashedPasswordBase64);
//save the salt with the new account. The HashedCredentialsMatcher
//will need it later when handling login attempts:
user.setPasswordSalt(salt);
userDAO.create(user);
User nor "UserDAO" exists currently from what I'm seeing, and all of these examples seem to use older Shiro examples.
When I look at the "PasswordService" javadoc I read
Account Creation or Password Reset
Whenever you create a new user account or reset that account's password,
we must translate the end-user submitted raw/plaintext password value to a
string format that is much safer to store. You do that by calling the
encryptPassword(Object) method to create the safer value. For example:
String submittedPlaintextPassword = ...
String encryptedValue = passwordService.encryptPassword(submittedPlaintextPassword);
...
userAccount.setPassword(encryptedValue);
userAccount.save(); //create or update to your data store
Be sure to save this encrypted password in your data store
and never the original/raw submitted password.
but what is "userAccount?"
A lot of times the documentation is very vague.
However I did notice there is a "SubjectDAO" Class, but no UserDAO class...
So yeah I'm confused on what to do next, so if anyone could help me I would appreciate it greatly!
Thanks a lot!
Seems like the Documentation is refering User and UserDAO as your own User Model Entity (Table) and User Data Access Layer Entity (Class to Save, Update, Delete and Retrieve). These necessarily not required to be a part of Apache Shiro (Reason some Data Access Layer may be in RDBMS, Some in In-memory dbs, some could even be in properties file, why not?)
You must implement User and UserDAO to save to your own persistence store.
UserAccount also is the Model object you use when you want to register user accounts. Like the Gmail signup.
You must know that Apache Shiro is just a layer for Security (Authentication, Authorization, etc). Persistence must be implemented by you.
Strongly advice you to check out Spring Data JPA and Spring Security.
When you are hashing the password :
DefaultPasswordService passwordService = new DefaultPasswordService();
String encytptedPwd= passwordService.encryptPassword("your password");
Above api will generate password including salt.
Update this password using JDBC native api...
When you are implementing the JDBCRealm
PasswordMatcher credentialsMatcher = new PasswordMatcher();
this.setCredentialsMatcher(credentialsMatcher);
above will set the credential matcher and use SimpleAuthenticationInfo to validate your login.
The PasswordMatcher can be configured to use an ini file too.

encrypted and decrypted password in java

i want to store encrypted password in my mysql database.
i have insert the password like ari means have to save the password like B-dd2c1cd0250859d32754fdd85ffc0531.
But i have to insert the data(ari) means the ari is displayed on my database.how can i encrupt the password and save the password like above format.
For eg:
ari is save in database like these format B-dd2c1cd0250859d32754fdd85ffc0531.how can i do.please help me.
i have wrote the code:
public class Insert {
public String insertData(String userName,String userPassword){
try{
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://server:3306/android","XXXX","XXX");
PreparedStatement statement = con.prepareStatement("INSERT INTO xcart_customers(login,password) VALUES ('"+userName+"','"+userPassword+"');");
int result = statement.executeUpdate();
}
catch(Exception exc){
System.out.println(exc.getMessage());
}
return "Insertion successfull!!";
}}
This is my Demo.java class:
public class Demo {
public static void main(String[] args){
Insert obj = new Insert();
System.out.println(obj.insertData("krishna", "ari"));
}
}
Looking at the sql query INSERT INTO xcart_customers(login,password) I guess you are trying to encrypt passwords for X-CART.
X-CART uses Blowfish key-based encryption. You can find your key from config.php -file.
Here's a already answered question about encrypting blowfish with a key in java which might help figuring out how encrypt it
Encryption with BlowFish in Java
You need to look at password hashing and salting. Have a look at this post.
EDIT:
Remember Hashing is One way! so you can't expect to convert the Hashed value back to the clear text (in this case ari). What you can do is when login works you can check user entered value is equal or not to the database value.
Without knowing which scheme was used to encrypt the existing data, there's no way to tell how you can achieve compatibility. If you can start all over again, bcrypt is the way to go.

Using an unencoded key vs a real Key, benefits?

I am reading the docs for Key generation in app engine. I'm not sure what effect using a simple String key has over a real Key. For example, when my users sign up, they must supply a unique username:
class User {
/** Key type = unencoded string. */
#PrimaryKey
private String name;
}
now if I understand the docs correctly, I should still be able to generate named keys and entity groups using this, right?:
// Find an instance of this entity:
User user = pm.findObjectById(User.class, "myusername");
// Create a new obj and put it in same entity group:
Key key = new KeyFactory.Builder(
User.class.getSimpleName(), "myusername")
.addChild(Goat.class.getSimpleName(), "baa").getKey();
Goat goat = new Goat();
goat.setKey(key);
pm.makePersistent(goat);
the Goat instance should now be in the same entity group as that User, right? I mean there's no problem with leaving the User's primary key as just the raw String?
Is there a performance benefit to using a Key though? Should I update to:
class User {
/** Key type = unencoded string. */
#PrimaryKey
private Key key;
}
// Generate like:
Key key = KeyFactory.createKey(
User.class.getSimpleName(),
"myusername");
user.setKey(key);
it's almost the same thing, I'd still just be generating the Key using the unique username anyway,
Thanks
When you specify a string key as you are in your example, you're specifying a key name (see the docs). As such, you shouldn't be using the KeyFactory - simply set the key field as 'myusername'.
There's no performance difference between the two options, though: Internally they are stored identically; the key name is just easier to use if you're not using parent entities for this model.

Categories