Get decrypted LDAP pwdhistory values using Java - java

String[] userAttrList = {"cn", "sn","pwdHistory};
SearchResult searchResult = lc.search(baseDN, SearchScope.SUB, searchFilter, userAttrList);
List<SearchResultEntry> result = searchResult.getSearchEntries();
for (SearchResultEntry sre : result) {
value = sre.getAttributeValue("pwdHistory");
System.out.println(sre.getAttributeValue("pwdHistory"));
return value; }
I'm using unboundidsdk to get the user's details from LDAP.
Attribute(name=cn, values={'Test User'}),
Attribute(name=sn, values={'User'}),
Attribute(name=pwdHistory, values={'20150902093503Z#2.5.4.35#32#{AES256}33243DD8jnwa8a8asbaaa==', '20150903091818Z#2.5.4.35#32#{AES256}PJiYUi+ssasassasaasa==', '20150902090417Z#2.5.4.35#32#{AES256}asasasAAA222221211221=='})}, controls={})]
I get the password history in the LDAP default encrypted form.
Is there an API available to get it in a decrypted format?

get decrypted pwdHistory values
You can't, because they aren't encrypted is the first place. They are hashed.
Any system that allows you to retreive passwords in plaintext is ill-designed. OpenLDAP isn't one of them.

Related

Oauth Client id and Secret without Basic Authorization

I have a situation where I can find out the Client_id and Client_secret from the Principle/ Basic Auth coming inside the request with the below snippet.
if(authorization!=null && !authorization.isEmpty()) {
String base64Credentials = authorization.substring("Basic".length()).trim();
byte[] credDecoded = Base64.getDecoder().decode(base64Credentials);
String credentials = new String(credDecoded, StandardCharsets.UTF_8);
String[] values = credentials.split(":", 2);
client_id=values[0];client_secret=values[1];
}
Can I provide the client_id and client_secret other than the basic auth format?
I saw we have password encoder to set as plain password encoder or bcrypt encoder to verify if the provided one and the one stored in DB are a match. But i don't see a method/ attribute so that I can control the input from a request.

Connect to Wildfly Elytron's Credential Store with Masked Password

I have a credential store that I created with Elytron's tool giving a clear text password: "mypassword". In my Java program I can connect to the store with the following code;
Password storePassword = ClearPassword.createRaw(ClearPassword.ALGORITHM_CLEAR,"mypassword");
CredentialStore.ProtectionParameter protectionParameter = new CredentialStore.CredentialSourceProtectionParameter(
IdentityCredentials.NONE.withCredential(new PasswordCredential(storePassword)));
Provider provider = new WildFlyElytronPasswordProvider();
Security.addProvider(provider);
CredentialStore credentialStore = CredentialStore.getInstance(KeyStoreCredentialStore.KEY_STORE_CREDENTIAL_STORE);
// Configure and Initialise the CredentialStore
String configPath = System.getProperty("jboss.server.data.dir");
Map<String, String> configuration = new HashMap<>();
String path = configPath + File.separator + "credentials" + File.separator + "csstore.jceks";
configuration.put("keyStoreType", "JCEKS");
configuration.put("location", path);
configuration.put("modifiable", "false");
//Initialize credentialStore
credentialStore.initialize(configuration, protectionParameter);
However, I now want to connect to the credential store with an encrypted password instead of a clear text. For this purpose, I again used Elytron's tool to create a Masked Passowrd of "mypassword" with the following command;
elytron-tool.sh mask --salt 12345678 --iteration 123 --secret mypassword;
Here the values for salt and iteration are just random, could be anything. The above command gives me the masked password which is;
MASK-38PaKyS.9hHaRq7pAaE5tB;12345678;123
I now need a way to connect to credential store with this masked password within my Java program. I found that there is also a class called "MaskedPassword" which I might use but I couldn't find out how.
Any suggestions?
When you use elytron tool to generate masked password then you get string with prefix MASK- and suffix with salt and iteration
in your case - MASK-38PaKyS.9hHaRq7pAaE5tB;12345678;123
you can use below piece of code to decrypt the masked password,
private char[] getUnmaskedPass(String maskedPassword) throws GeneralSecurityException {
int maskLength = enter code here"MASK-".length();
if (maskedPassword == null || maskedPassword.length() <= maskLength) {
throw new GeneralSecurityException();
}
String[] parsed = maskedPassword.substring(maskLength).split(";");
if (parsed.length != 3) {
throw new GeneralSecurityException();
}
String encoded = parsed[0];
String salt = parsed[1];
int iteration = Integer.parseInt(parsed[2]);
PasswordBasedEncryptionUtil encryptUtil = new PasswordBasedEncryptionUtil.Builder().picketBoxCompatibility().salt(salt).iteration(iteration)
.decryptMode().build();
return encryptUtil.decodeAndDecrypt(encoded);
}
Now you can use this in your piece of code as a clearPassword. I hope that helped.
Source - https://github.com/wildfly-security/wildfly-elytron-tool/blob/master/src/main/java/org/wildfly/security/tool/MaskCommand.java static char[] decryptMasked(String maskedPassword)
We can create it using the below code...
Password storePassword = MaskedPassword.createRaw(MaskedPassword.ALGORITHM_MASKED_MD5_DES, <CREDENTIAL_STORE_ENTRY_PREFIX>.toCharArray(), 120,"12345678".getBytes(StandardCharsets.UTF_8),"MASK-38PaKyS.9hHaRq7pAaE5tB".getBytes(StandardCharsets.UTF_8));
....
....

How to match original password with encrypted password entry in database on login

MessageDigest alg = MessageDigest.getInstance("MD5");
alg.reset();
alg.update(password.getBytes());
byte[] digest = alg.digest();
StringBuffer hashedpasswd = new StringBuffer();
String hx;
for (int i=0;i<digest.length;i++){
hx = Integer.toHexString(0xFF & digest[i]);
//0x03 is equal to 0x3, but we need 0x03 for our md5sum
if(hx.length() == 1){hx = "0" + hx;}
hashedpasswd.append(hx);
}
I followed the above code for password encryption. But when login the password checks with database password and login fails as the db entry is encrypted password. How will i check the database's encrypted password with original password on login?
While checking with the database, Hash the password you entered with the same algorithm as the one you used to save it in the Data Base. That's how Hashing works. You don't need to "Decrypt" the password from the database, that's not possible. You would rather want to Hash the password you're entering and check whether both the hash values (i.e. the one in db and the one you just hashed) are equal. That is the entire concept of hashing. You can't "DeHash" something. You can only hash the coming data and compare it with previously hashed value.
encrypt(user_entered_password) == getPasswordFromDatabase()

Hash a password with $2y$ in java

i am having issues with hashing passwords in java so when i try to log in and write my password i want to get that written password hash it using $2y$ as the same format in my database because that it what the FOSBundle is using as encryption methode the BCrypt but instead i get a hashed password which starts with $2a$ instead of $2y$ so i can't compare them is there anyway to change that $2a$ hash into $2y$ hash ?
My function :
public void CheckLogin(String username,String password) throws SQLException{
String requete = "Select * from user WHERE username ='"+username+"';";
ste = con.createStatement();
res = ste.executeQuery(requete);
while(res.next()) {
if (res.getString(2).equals(username)) {
System.out.println("Password FOS ="+res.getString(8));
String hashed2 = BCrypt.hashpw(password, BCrypt.gensalt(12));
hashed2 = "$2y$" + hashed2.substring(4);
System.out.println("HASHED PASSWORD =" + hashed2);
if (BCrypt.checkpw(res.getString(8),hashed2)) {
System.out.println("It matches");
} else {
System.out.println("It does not match");
}
}
}
}
he can't find the user i am looking for because the hashed password i passed to him " hashed2 " is not the same in my database because in my database it stars with $2y$ and this hash methode give a $2a$ hashed password
Based on BCrypt wiki the prefix $2a$, $2y$ and $2b$ are used to store the algorithm version. Although $2y$ fixed a bug in previous implementation this fix seems to be limited to PHP:
In June 2011, a bug was discovered in crypt_blowfish, a PHP implementation of BCrypt.
...
Nobody else, including canonical OpenBSD, adopted the idea of 2x/2y.
This version marker change was limited to crypt_blowfish.
Since it looks like you are using JBCrypt you will always get $2a$ version. Latest version 0.4 definitely uses it.
You can try comparing the hashed password without the version prefix. I never had to compare PHP and Java BCrypt implementation so I've no idea if this will work. In your code you can do following:
// JBCrypt requires version $2a, change the prefix
String hashed2 = "$2a" + res.getString(8).substring(3);
if (BCrypt.checkpw(password, hashed2)) {
System.out.println("It matches");
}

reading two variable values after decrypting

I am working on "Forgot Password". I am trying to create a reset token with email + current_time. email is user login whilst code will check if time >= 5 minutes then this link will not work. Here is my code:
// preparing token email + time
Date now = new Date();
String prepareToken = "?email="+email+"&tokenTime="+now.getTime();
// encrypt prepareToken value
Encryptor enc = new Encryptor();
resetToken = enc.encrypt(resetToken);
The token will be sent as for example as http://domainname.com/ForgotPassword?resetToken=adj23498ljj238809802340823
Problem:
When user click it then I got as request parameter and obviously decrypt this parameter but how can I get email in one String + time as another String
Please advise
If your issue is simply parsing the decoded String to get some sort of Map of your parameters, I'd suggest you to read Parse a URI String into Name-Value Collection .
Hope it helps.
EDIT :
Assuming you have the splitQuery(URL url) method from the previous link and that you successfully decoded the token :
public String getEmailFromToken(String decodedToken) {
// if you decoded your token it will looks like the prepareToken String
String stubUrl = "http://localhost"+decodedToken;
Map<String,String> map = splitQuery(new URL(stubUrl));
return map.get("timeToken");
}
I created a properly formed URL to respect the URL syntax.
With little tweak, you should be able to implement splitQuery for a String. I hope you can manage that.

Categories