Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does somebody have a Java implementation of the method how "mosquitto_passwd" generates hashes for the "passwd" file...? #2613

Closed
jayjupdhig opened this issue Aug 12, 2022 · 10 comments
Labels

Comments

@jayjupdhig
Copy link

jayjupdhig commented Aug 12, 2022

What that guy writes seems to be a lil bit weird...

https://mikini.dk/2017/01/generating-passwords-for-mosquitto-mqtt-broker-using-php

1.) Salt value "spicychilinstuff" will go into the hash code as clear text
image

2.) Then will try to base64-decode a CLEAR (non-base64 encoded) text

image

And his example output begins with "$6$ ... " - not with "$7$ ... "

@jayjupdhig
Copy link
Author

jayjupdhig commented Aug 12, 2022

And that here is also "special"... score of -1...

https://stackoverflow.com/questions/63265141/mosquitto-password-generation-in-python

The problem is that i'n neither a c/c++ nor a python programmer.

I understand PHP, but the example from my first post seems to be unusable. And i also (as already writter) understand Java. And also "speak" C# and J# .NET...

Maybe somebody can help me?

Thank you very very much for your feedback(s). :-)

With best regards from Switzerland.

@jayjupdhig
Copy link
Author

And somewhere i read it's the same method as /etc/shadow does... but when i look into that file, there is no "$7$ ... " on beginning of the entries, and no "="-charachter at the end...

I'm confused, really... :-(

@ralight
Copy link
Contributor

ralight commented Aug 12, 2022

  1. Generate some random bytes as a salt - this is 12 bytes for 2.0.x, or up to 64 bytes for 2.1.
  2. Pass the password, the salt and a number of iterations to a pbkdf2 hashing function using the sha512 digest
  3. Create the base64 encoding of the result and the salt
  4. Write out to the password file in the format <username>:$7$<integer number of iterations>$<base64 encoded salt>$<base64 encoded password hash> - everything within the <> is to be replaced, everything else is the literal characters.

@jayjupdhig
Copy link
Author

Thank you very very much for your fast feedback!! :-)

@jayjupdhig
Copy link
Author

Another question: How is it for version 1.x, concrete version 1.4.15? We also have a server with that version, besides one with v2.0.11...

Does v1.x use the same password hash generation method as v2.0.x?

Thank you very much for your feedback :-)

@jayjupdhig jayjupdhig reopened this Aug 16, 2022
@ralight
Copy link
Contributor

ralight commented Aug 16, 2022

  1. Generate 12 random bytes as a salt
  2. Pass the password, the salt to the sha512 digest function
  3. Create the base64 encoding of the result and the salt
  4. Write out to the password file in the format <username>:$6$<base64 encoded salt>$<base64 encoded password hash> - everything within the <> is to be replaced, everything else is the literal characters.

@jayjupdhig
Copy link
Author

jayjupdhig commented Aug 16, 2022

What i have to to with the return value from 2.) - "Pass the password, the salt and a number of iterations to ... " ? How to concatenate it?

On 4.), i only see username + $x$ + integer number of iterations+ $ + base64 encoded salt + $ + base64 encoded password hash

...BUT what is with the return value of the pbkdf2 hashing function using the sha512 digest that has 3 input paramters? (salt, password, number of iterations)

Test code here:

`
package com.xaxada.tools.mosquitto.testing;

import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.util.Base64;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

public class MosquittoUsrAcctGenTest {

private MosquittoUsrAcctGenTest(final String[] caArgs) {
	super();
	this.init();
	this.start();
}

private void init() {

}

public static String encode(String aString) {
	return Base64.getEncoder().encodeToString(aString.getBytes());
}

public static String decode(String aString) {
	return new String(Base64.getDecoder().decode(aString));
}

private void start() {
	String username = "myuser";
	String password = "mypass";

	// Generate some random bytes as a salt - this is 12 bytes for 2.0.x, or up to 64 bytes for 2.1.
	byte[] randomSalt = generateRandomSalt(12);

	// Pass the password, the salt and a number of iterations to a pbkdf2 hashing function using the sha512 digest
	int numberOfIterations = 101; // Same value as i saw in "passwd" file
	String passwordHash = pbkdf2Encode(password, randomSalt, numberOfIterations);
	
	// Create the base64 encoding of the result and the salt
	String test = encode(passwordHash + new String(randomSalt));

	String test2 = encode(new String(randomSalt));

	String pwd = username + ":$7$" + numberOfIterations + "$" + test2 + "$" + test;
	System.out.println(pwd);
}

public static void main(String[] caArgs) throws Exception {
	if (caArgs == null) {
		caArgs = new String[0];
	}

	new MosquittoUsrAcctGenTest(caArgs);
}

public static byte[] generateRandomSalt(final int caNumberOfBytes) {
	byte[] lNonce = new byte[caNumberOfBytes];
	new SecureRandom().nextBytes(lNonce);

	final StringBuilder clResult = new StringBuilder();

	for (byte temp : lNonce) {
		clResult.append(String.format("%02x", temp));
	}

	Exception lException = null;

	byte[] lReturn = null;

	try {

		lReturn = clResult.toString().getBytes("UTF-8");

	} catch (final Exception clException) {
		lException = clException;
	} finally {
		if (lException != null) {
			throw new RuntimeException(lException);
		}
	}

	return lReturn;
}

public static String pbkdf2Encode(String rawPassword, byte[] salt, int numberOfIterations) {
	try {
		PBEKeySpec spec = new PBEKeySpec(rawPassword.toCharArray(), salt, numberOfIterations, 512);
		SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
		return Base64.getEncoder().encodeToString(skf.generateSecret(spec).getEncoded());
	} catch (GeneralSecurityException ex) {
		throw new IllegalStateException("Could not create hash", ex);
	}
}

}`

@jayjupdhig
Copy link
Author

OUTPUT:

user1:$7$101$MGI4ZGM2MmNmYmQ2NGE0MjlhMmI4YmIx$UDRsUDlHZ0QxVmlWMkRYQk1YZ25FbHhHMFRWNk1xTlVXZ2tLYjNNeW5DWUxiKzFaWkNhZFNuR3VlY0pQeHBXUW53MUNEMHdxNXBzQkZSVGMwTUE4VXc9PTBiOGRjNjJjZmJkNjRhNDI5YTJiOGJiMQ==

@jayjupdhig
Copy link
Author

solved

@jayjupdhig
Copy link
Author

Got it! ;-)

-> https://www.java-forum.org/thema/jre-jdk-unabhaengige-pbkdf2withhmacsha512-implementierung.198804/

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 20, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants