newbie question : Apache Shiro recover password - java

I have little experience with encryption / decryption..
for my web app I want to use Apache Shiro to login user, with salted password ..
this is the article I read : http://shiro.apache.org/realm.html#Realm-HashingCredentials and the code to generate the salted password :
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);
This give me a encrypted password.. but how can I recover the plain text password? It's possible?

Thanks to Benjamin Marwell :
This is possible only in theory and/or with a lot of money.
You can use hacking tools which run on your GPU, but even then it
might take years to find it.
And that is exactly the point: Password-based key derivation functions
are designed to create an in-revertable hash.
Shiro 2.0 will use even better KDFs like Argon2 or bcrypt/script,
which require a vast amount of memory and cpu to make attacks not
feasible.
If you have access to the database where you stored the password, I
would just set a new password and forget about the old one, if
possible.

Related

How can I decrypt a string if I encrypt it with a random key

I am trying to develop an android app in java which needs encryption. Also I want to use AES-256 for encryption. But when I look a tutorial of it, It always generates a random key. My question is: How can I decrypt a string if I encrypt it with a random key? Also I tried almost every code in web, but none of them worked, so can you provide a AES-256 encryption code with no salt and IV. If I know something wrong, please correct me and teach me the truth.
EDIT: I am trying to make a password manager app. App has two passwords, first one is the master password that we use for encryption string data. Second one is the passwords that we want to manage. Master password is stored in users mind. And other password will be stored in the app with encrypted version.
When user wants to see his passwords he will input his master key to decrypt the encrypted passwords. So how can I do it? And user's master password will be 32 or 64 digit and I don't think we need to generate a random key. Can you show me some way? I am not native english speaker, sorry for my bad english. Thanks for help.
As you have already discovered, a random key doesn't make sense for your app. Instead, you want to derive a key from the master password. To that end, you use a key derivation function or KDF.
In order to prevent dictionary attacks, you must also use a salt. A salt is a random value that you generate once and then store in your app (without any encryption).
Create salt
void initSalt()
{
byte[] salt = new byte[32];
new SecureRandom().nextBytes(salt);
... save salt ...
}
Get key for encryption
SecretKey getSecretKey(String masterPassword)
{
byte[] salt = ... retrieve saved salt ...
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
char[] chars = password.toCharArray();
int hashIterations = 1024;
int keySizeBytes = 32;
return keyFactory.generateSecret(
new PBEKeySpec(chars, salt, hashIterations, keySizeBytes * 8));
}
The getSecretKey() function is call both when the password manager is first setup as well as on any later use. The function will always return the same secret key if the salt doesn't change.
Some Android versions might not support PBKDF2WithHmacSHA256. If so, you have to revert to PBKDF2withHmacSHA1.
With the secret key generated from the master password, you can then go ahead an encrypt the data that the password manager wants to store.

How to hide password within JAR file

I am trying to make a Java program that requires a password. The problem is that a Java class or JAR file can be converted back to source code, so people can see the password by converting the program back to source code. How can I fix this?
You can't.
Even if you encrypt the password, the code to decrypt the password will be available in, and so will not prevent someone decompiling your application.
You have some options:
Put your password in an environment variable (accessible with System.getProperty("variable.name"))
Store the password in a file (still not great, but better than sources)
Access the password from a server, however, you are still required to make the user enter their creds for the server, and now you're left with the same problem.
Make the user enter a password every time they run the application
Probably the best way is to protect the password is to use a one-way hash. I would recommend investigating the Secure Hash Algorithms (SHA). These are one-way hashes (aka cryptographic checksums) that generate, for all practical purposes, a unique hash for some given text or message. Store the hash in the JAR file and the use the same algorithm to hash the entered password. Compare that hash to the stored one for verification.
The down side to this is that it is not easy (or in some cases possible) to change the password.
The odds of generating identical hashes for different inputs is infinitesimal.
Here is one way it could be done using standard Java libraries.
MessageDigest md = MessageDigest.getInstance("SHA-256");
String password = "Password"; // password to be "stored"
byte[] bytes = password.getBytes();
md.update(bytes);
byte[] digest = md.digest();
// store the following string in the jar file
String storedDigest = toHex(digest);
// validation process
String enteredPassword = "Password";
md.update(enteredPassword.getBytes());
System.out.println(toHex(md.digest()).equals(storedDigest) ? "Passed"
: "Failed");
//Convert array of bytes to a long hex string
public static String toHex(byte[] digest) {
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(Integer.toHexString((b >> 4) & 0xF));
sb.append(Integer.toHexString(b & 0xF));
}
return sb.toString();
}

Java cryptography object in file password

i try to find the good way for the best technology/method for hidden password in a file, but without use external jar or library.
Actually i use one object that represent a list of user name and password. Convert my list in a xml (only in memory) and after that, i store in a file with AES.
Use only java 7, no external library.
Is a good/secure method?
If this operation is no good, is possible to create dynamically xml encrypted?
thanks
You can use a FileOutputStream wrapped in a CipherOutputStream.
It's not really secure to save passwords encrypted with AES because:
1) Where do you store the key? If you store it in the server, if an attacker violates the server and finds the key, he will have complete acces to the users information.
2) Do you really need to know the users' passwords? In many application, for security reasons, it's better to keep only the hash of the password. The username can be stored in plaintext and you can also add a salt to the password to enforce it. You can do that with some algorithms offered by Java7 platform. In this way, even if someone enters your server, he can't use users login informations without breaking the hash function.
Here's an example that worked for me:
public byte[] getHash(String password, byte[] salt, String algorithm) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest digest = MessageDigest.getInstance(algorithm);//The String rapresents the alg you want to use: for example "SHA-1" or "SHA-256"
digest.reset();
digest.update(salt);
return digest.digest(password.getBytes("UTF-8"));
}
You can also look at this link for a more complete example: https://www.owasp.org/index.php/Hashing_Java

Java encryption alternitive to hardcoded key

I am new to encryption.
I have looked at the javax.crypto documentation and got encryption of a file to work using this code ...
File saveFile = new File("Settings.set");
saveFile.delete();
FileOutputStream fout = new FileOutputStream(saveFile);
//Encrypt the settings
//Generate a key
byte key[] = "My Encryption Key98".getBytes();
DESKeySpec desKeySpec = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey skey = keyFactory.generateSecret(desKeySpec);
//Prepare the encrypter
Cipher ecipher = Cipher.getInstance("DES");
ecipher.init(Cipher.ENCRYPT_MODE, skey);
// Seal (encrypt) the object
SealedObject so = new SealedObject(this, ecipher);
ObjectOutputStream o = new ObjectOutputStream(fout);
o.writeObject(so);
o.close();
However if you were a clever hacker ( or maybe even amateur since I figured this out), all you would have to do is open the class file that contains this code, and the encryption key (My Encryption Key98) is plainly visible.
How do you encrypt the encryption key? ...LOL... Can you?
Thanks for your help!
If the attacker has access to both the software and the file, it could decrypt it. There are some ways to solve this:
Use asymetric keys. Encrypt the file with the public key, and it can only be decrypted with a private key. This assumes that the software does not need to decrypt the file.
Use Diffie-Hellman exchange. If you want to send an encrypted piece of data over the network, both parties can establish a key without an attacker knowing about it.
If the program needs to both encrypt and decrypt the data, there is nothing you can do. The attacker can simply run the program and look at the decrypted information.
An attacker can always do everything the program can do and usually quite a bit more. The only way to get things secure is the use information not under control of the program. Request the user to enter a password or put information in a store under control of the operating system. The later will not help if an attacker has physical access or maybe even a lot of rights unless special hardware like a Trusted Platform Module (TPM) is involved.
Well if the program can decrypt the data without additional input from the user, you can't really avoid someone else from accessing the file if he has access to the program.
If you are targeting Windows only, you might want to take a look at the Data Protection API (DPAPI). It essentially does the same thing, but the passphrase used for encryption is protected by the operating system on a user (or machine) scope. Simply put: you need the user login (or a program that runs on the given user account) to access the key (or for machine scope the login for any user on the machine).
I don't know how to access the API from Java, but Google brings up some wrapper libraries.
Don't hardcode the key. Assuming you don't have a user on hand to enter the passphrase, configure your code to pull the encryption key from a plain file, then rely on operating system security to keep the file safe. Provide a way to migrate to a new key when the system administrator deems it necessary.
I do not believe that this is possible without having the user entering the key on encryption and decryption.
You could employ some technique to make it harder to view the key without the full source code, but it would not be secure.
If your program can encrypt / decrypt a file on its own, then everything you need to perform the decryption is already built into the program, so a determined troublemaker could decrypt files you encrypted.
If possible, ask the user for a 'password,' and use what they give you as the encryption / decryption key.
Is it important that the user not be able to see his own encryption key? Or merely important that by discovering his won key, the user should not thereby know everyone else's key?
You could prompt the user for a personal key and either store it externally or prompt the user each time you need it. That way each user's key would be his own, and would not be usable to decrypt documents stored by other users on other machines.
the most secure method is not use any encryption, just put your user.properties to your home directory, with following code:
String userhome = System.getProperty("user.home");
String username = system.getProperty("user.name");
String hostname = java.net.InetAddress.getLocalHost().getHostName();
if (hostname.equals("webserver") && username.equals("root")){
ResourceBundle user = ResourceBundle.getBundle(userhome/ "user.properties");
}

How to programatically encrypt/decrypt plain text credentials in JSP?

As as part of my daily routine, I have the misfortune of administering an ancient, once "just internal" JSP web application that relies on the following authentication schema:
...
// Validate the user name and password.
if ((user != null) && (password != null) && (
(user.equals("brianmay") && password.equals("queen")) ||
(user.equals("rogertaylor") && password.equals("queen")) ||
(user.equals("freddiemercury") && password.equals("queen")) ||
(user.equals("johndeacon") && password.equals("queen"))
)) {
// Store the user name as a session variable.
session.putValue("user", user);
...
As much as I would like to, the Queen members have never been users of the system but anyway it does make a great example, does it not?
Despite that by policy this client enforces security by domain authentication among other things, therefore this issue isn't seen as a security risk, still, my idea is to at least obfuscate that plain text credentials using perhaps a simple MD5 or SHA1 method, so such sensitive data is not visible to the naked eye.
I'm a total newbie when it comes to JSP so I would really appreciate any piece of advice you'd be willing to share with me.
Thanks much in advance!
It is hard to understand the exact scheme you are thinking about but I assume the password is coming in from a request and you want to calculate the MD5 hash in a JSP that the request is being sent to. After that you can compare it to the pre-computed MD5 version. You could even be more secure if it isn't being done with https and use a javascript MD5 library to hash the password before submitting it.
You can MD5 a string in java like this:
try
{
String digestInput = "queen";
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(digestInput.getBytes());
BASE64Encoder base64Encoder = new BASE64Encoder();
String digestString = base64Encoder.encode(messageDigest.digest());
// digestString now contains the md5 hashed password
}
catch (Exception e)
{
// do some type of logging here
}
First of all you should move that logic from jsp to a separate class.
Second, you shouldn't keep plain text password anywhere in the code. Use some kind of one way hash function (md5, sha1, ...) and keep only password hashes.
When checking for user password, first hash it and then compare hashes.

Categories