I try to Hash this password hoang1#H 3 times with 3 accounts by using SHA256. But when i write this password to file by using FileWriter and BufferedWriter, there are 3 different strings. Why ?
Here are my code for SHA256 hashing:
public byte[] getSHA(String input) throws NoSuchAlgorithmException
{
// Static getInstance method is called with hashing SHA
MessageDigest md = MessageDigest.getInstance("SHA-256");
// digest() method called
// to calculate message digest of an input
// and return array of byte
return md.digest(input.getBytes(StandardCharsets.UTF_8));
}
public String toHexString(byte[] hash)
{
// Convert byte array into signum representation
BigInteger number = new BigInteger(1, hash);
// Convert message digest into hex value
StringBuilder hexString = new StringBuilder(number.toString(16));
// Pad with leading zeros
while (hexString.length() < 32)
{
hexString.insert(0, '0');
}
return hexString.toString();
}
Code
You can test/run this code on ▶▶▶▶▶ https://replit.com/#JomaCorpFX/JavaHashes
HashAlgorithm.java
public enum HashAlgorithm {
SHA512("SHA-512"),
SHA256("SHA-256"),
SHA384("SHA-384"),
SHA1("SHA-1"),
MD5("MD5");
private String Value = "";
HashAlgorithm(String Value) {
this.Value = Value;
}
#Override
public String toString() {
return Value;
}
}
HexEncoder.java
import java.util.Formatter;
public class HexEncoder{
public static String toHex(byte[] data) {
StringBuilder sb = new StringBuilder(data.length * 2);
try (Formatter formatter = new Formatter(sb))
{
for (byte b : data)
{
formatter.format("%02x", b);
}
}
return sb.toString();
}
}
HashManager.java
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;
public class HashManager {
public static byte[] toRawHash(byte[] data, HashAlgorithm algorithm) throws Exception
{
byte[] buffer = data;
MessageDigest messageDigest = MessageDigest.getInstance(algorithm.toString());
messageDigest.reset();
messageDigest.update(buffer);
return messageDigest.digest();
}
public static String toHexHash(byte[] data, HashAlgorithm algorithm) throws Exception
{
return HexEncoder.toHex(toRawHash(data, algorithm));
}
public static String toHexHash(String data, HashAlgorithm algorithm) throws Exception
{
return toHexHash(data.getBytes(StandardCharsets.UTF_8), algorithm);
}
}
Main.java
public class Main {
public static void main(String[] args) throws Exception {
String data = "grape";
System.out.println(HashManager.toHexHash(data, HashAlgorithm.SHA256));
System.out.println(HashManager.toHexHash(data, HashAlgorithm.SHA256));
System.out.println(HashManager.toHexHash(data, HashAlgorithm.SHA256));
System.out.println(HashManager.toHexHash(data, HashAlgorithm.SHA256));
}
}
Output
you should call md.reset() before reuse the MessageDigest instance.Just add it before md.digest(....).
Related
I am trying to create a custom PasswordHashProvider.
I succeeded in creating the component, the algorithm is working, the password saved in the database is correct.
A Salt is stored in a database, but I don't understand how. I thought it was the base 64 salt, but it doesn't match.
database secret_data : {"value":"v8Po+hMGZbS2tWr4IGRXqy3FJyQIavjsrpXHwomWHwRRs+iRVInd+9naF681EENm76lF1omK+BqsPIRrtKH1VQ==","salt":"DEiO17h4/+6gwzxn"}
database credential_data : {"hashIterations":5000,"algorithm":"message-digest"}
I add logs in the console when creating a password and when connecting a user. The salt is generated, stored, but the one retrieved during connection is different on each try.
When I register the user secret :
New salt : [B#7bb894a0
When I try to connect the user :
Existing salt: [B#d433036
// retry connection
Existing salt: [B#355bae9a
Does anyone know how salt is stored?
My class (for tests I force iterations to 5000) :
import org.keycloak.credential.hash.PasswordHashProvider;
import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.credential.PasswordCredentialModel;
import java.util.Base64;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.nio.charset.StandardCharsets;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
public class MessageDigestPasswordHashProvider implements PasswordHashProvider {
private final int defaultIterations;
private final String providerId;
private byte[] salt;
public MessageDigestPasswordHashProvider(String providerId, int defaultIterations) {
this.providerId = providerId;
this.defaultIterations = defaultIterations;
}
#Override
public boolean policyCheck(PasswordPolicy policy, PasswordCredentialModel credential) {
int policyHashIterations = 5000;
return credential.getPasswordCredentialData().getHashIterations() == policyHashIterations
&& providerId.equals(credential.getPasswordCredentialData().getAlgorithm());
}
#Override
public PasswordCredentialModel encodedCredential(String rawPassword, int iterations) {
iterations = 5000;
byte[] salt = generateSalt();
this.salt = salt;
System.out.print("New salt : ");
System.out.println(salt);
String encodedPassword = encode(rawPassword, iterations);
return PasswordCredentialModel.createFromValues(providerId, salt, iterations, encodedPassword);
}
#Override
public String encode(String rawPassword, int iterations) {
iterations = 5000;
byte[] salt = this.salt;
System.out.print("Salt fonction encode :");
System.out.println(salt);
String salted = rawPassword + "{" + salt.toString() + "}";
byte[] digest = getSha512(salted.getBytes());
System.out.println(iterations);
for (int i = 1; i < iterations; i++) {
digest = getSha512(concat(digest, salted.getBytes()));
}
return Base64.getEncoder().encodeToString(digest);
}
#Override
public boolean verify(String rawPassword, PasswordCredentialModel credential) {
this.salt = credential.getSalt();
System.out.print("Existing salt: ");
System.out.println(this.salt);
String encodedPassword = encode(rawPassword, credential.getHashIterations());
return encodedPassword.equals(credential.getValue());
}
private static byte[] generateSalt() {
SecureRandom random = new SecureRandom();
byte salt[] = new byte[12];
random.nextBytes(salt);
return salt;
}
#Override
public void close() {
}
public static byte[] getSha512(byte[] value) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-512");
byte[] messageDigest = md.digest(value);
return messageDigest;
}
catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public static byte[] concat(byte[] a, byte[] b) {
byte[] c = new byte[a.length + b.length];
System.arraycopy(a, 0, c, 0, a.length);
System.arraycopy(b, 0, c, a.length, b.length);
return c;
}
}
A Salt is stored in a database, but I don't understand how. I thought
it was the base 64 salt, but it doesn't match.
It is based 64.
The salt is generated, stored, but the one retrieved during connection
is different on each try.
The problem is this:
System.out.print("New salt : ");
System.out.println(salt);
you are not print the actually content of the salt you are print the object "salt".
Try instead:
System.out.println(Arrays.toString(this.salt));
This question already has an answer here:
What does "Incompatible types: void cannot be converted to ..." mean?
(1 answer)
Closed 3 years ago.
I know there are posts similar to this one, but I cannot seem to figure out my issue. I feel like it is something small, but my method does return a String, so I am no sure why it is telling me type void. I am new to java and would appreciate any help I can get. Here is my code:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.security.MessageDigest;
public class Login{
public static void main(String []args){
Scanner user_input = new Scanner(System.in);
String entered_username = Get_Credentials.get_username(user_input);
String entered_password = Get_Credentials.get_password(user_input);
String encrypted_password = MD5Digest.encrypt(entered_password);
user_input.close();
User[] all_users = File_Scanner.create_users();
}
}
class Get_Credentials{
public static String get_username(Scanner user_input){
System.out.println("Username: ");
return user_input.next();
}
public static String get_password(Scanner user_input){
System.out.println("Password: ");
return user_input.next();
}
}
class File_Scanner{
public static User[] create_users(){
User users[] = new User[6];
int index_counter = 0;
try {
File credentials_file = new File("credentials.txt");
String pattern = "[^\"\\s]+|\"(\\\\.|[^\\\\\"])*\"";
Scanner file_reader = new Scanner(credentials_file);
while (file_reader.hasNextLine()) {
users[index_counter] = new User();
users[index_counter].username = file_reader.findInLine(pattern);
users[index_counter].encrypted_password = file_reader.findInLine(pattern);
users[index_counter].password = file_reader.findInLine(pattern);
users[index_counter].role = file_reader.findInLine(pattern);
file_reader.nextLine();
index_counter++;
}
file_reader.close();
}
catch (Exception e) {
System.out.println(e.getClass());
}
return users;
}
}
class User {
String username;
String password;
String encrypted_password;
String role;
}
class MD5Digest {
public static void encrypt(String original) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(original.getBytes());
byte[] digest = md.digest();
StringBuffer sb = new StringBuffer();
for (byte b : digest) {
sb.append(String.format("%02x", b & 0xff));
}
System.out.println("original:" + original);
System.out.println("digested:" + sb.toString());
}
}
Here is the error I am getting:
Login.java:15: error: incompatible types: void cannot be converted to String
encrypted_password = MD5Digest.encrypt(entered_password);
^
1 error
Your function has no return value void and you try to assign it to a string variable, that is what the error message means.
So change:
public static void encrypt(String original) throws Exception {
to
public static String encrypt(String original) throws Exception {
and
return sb.toString()
So the class looks like:
class MD5Digest {
public static String encrypt(String original) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(original.getBytes());
byte[] digest = md.digest();
StringBuffer sb = new StringBuffer();
for (byte b : digest) {
sb.append(String.format("%02x", b & 0xff));
}
System.out.println("original:" + original);
System.out.println("digested:" + sb.toString());
return sb.toString();
}
}
BTW: Take care of Java's naming convention. Class names should be subjects.
EDIT:
Because your encrypt message throws an exception, you have to throw the exception also in public static void main(String []args) throws Exception{ or you have to handle it in a try-catch-block
In your code you are not returning anything for the method encrypt in MD5Digest class as below :
public static void encrypt(String original) throws Exception
That is the reason why compiler giving error as it is void type but the code is for String
Looks like you wanted to return a String, it should be as below :
class MD5Digest {
public static String encrypt(String original) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(original.getBytes());
byte[] digest = md.digest();
StringBuffer sb = new StringBuffer();
for (byte b : digest) {
sb.append(String.format("%02x", b & 0xff));
}
System.out.println("original:" + original);
System.out.println("digested:" + sb.toString());
return sb.toString();
}
}
i'm trying to generate a 48 character hash string in Java using SHA384, the output should look something like this:
PÊ&¿ a»#óæS0iÛ6në0Ê`o€X·„\KÃò¢ï¼fÖ…)nE#ó^s
My current implementation is as follows:
public static String getHash(byte[] inputBytes, String algorithm) throws Exception{
String hashValue = "";
try {
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
messageDigest.update(inputBytes);
byte[] digestedBytes = messageDigest.digest();
hashValue =
DatatypeConverter.printHexBinary(digestedBytes).toLowerCase();
} catch(Exception e) {
e.printStackTrace();
}
return hashValue;
}
public static void main(String[] args) throws Exception {
System.out.println(getHash("The quick brown fox Jumps over the lazy dog".getBytes(), "SHA-384"));
}
Output:
b94a2179d90daf662f2ae8e41f92c2831eb0eea5a352f81ac7b0a80a07b2c357d88d0e3fc12bf4f0d888335508b09c41
As observed, the output string is a 96 Character string instead of 48, what am I doing wrong?
You can try something like this:
import java.security.MessageDigest;
public class Main {
public static String getHash(byte[] inputBytes, String algorithm) throws Exception{
try {
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
messageDigest.update(inputBytes);
byte[] digestedBytes = messageDigest.digest();
return new String(digestedBytes, "UTF-8");
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) throws Exception {
System.out.println(getHash("The quick brown fox Jumps over the lazy dog".getBytes(), "SHA-384"));
}
}
This converts your 48 byte array into a String using the UTF-8 encoding. However, not all bytes represent printable characters, so you'll end up with a String with slightly fewer characters.
package com.journaldev.examples;
import java.util.UUID;
/**
* Java UUID randomUUID Example
*
*/
public class UUIDExample {
public static void main(String[] args) {
//initialize uuid
UUID uuid = UUID.randomUUID();
System.out.println(uuid);
}
}
Try this for generating random id's
I have a project where our provider has their own DES Encryption logic however I am using django as my backend. I can run the java using subprocess but I'm actually planning to convert that java code to python..
Here is my code:
import java.io.*;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;
public class PHPDESEncrypt {
String key;
public PHPDESEncrypt() {
}
public PHPDESEncrypt(String key) {
this.key = key;
}
public byte[] desEncrypt(byte[] plainText) throws Exception {
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key, sr);
byte data[] = plainText;
byte encryptedData[] = cipher.doFinal(data);
return encryptedData;
}
public String encrypt(String input) throws Exception {
return base64Encode(desEncrypt(input.getBytes())).replaceAll("\\s*", "");
}
public String base64Encode(byte[] s) {
if (s == null) return null;
BASE64Encoder b = new BASE64Encoder();
return b.encode(s);
}
public static void main(String args[]) {
try {
PHPDESEncrypt d = new PHPDESEncrypt(args[0]);
String p=d.encrypt(args[1]);
System.out.println(p);
}
catch (Exception e) {
e.printStackTrace();
}
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
}
Any suggestions on how to convert this? Like a library or an online tool? Or it would be better if there is someone good enough who can easily convert this
I run it in java like:
java PHPDESEncrypt "3r108w5A" "cagent=sample/\\\\/loginname=sample/\\\\/password=password/\\\\/method=ca/\\\\/actype=0/\\\\/cur=USD"
The result should be:
lt5tEqnzRCx67vJ8j3Ap5zIVZYkT01Ho+irM1NPdReJqwyrP9vlypDXvExx9sCOEJPcPCET0aPpKFkW1punRxP/uD8IFM1j4umwLuJpxPQTOdwJsbuuRmhmkFml6l3OV
use pyDes with python3, here is the demo code:
def des_ecb_encode(source, key):
des_obj = des(key, ECB, IV=None, pad=None, padmode=PAD_PKCS5)
des_result = des_obj.encrypt(source)
return base64.encodestring(des_result)
if __name__ == '__main__':
src = b'cagent=81288128/\\\\/method=tc'
key = b'12341234'
encrypted = des_ecb_encode(src, key)
print('encrypted: ', encrypted)
and it will print
encrypted: b'IGcOAYEQN88F1NFLtBOK23PMeg42F7r8jchYOmglMAs=\n'
I already answered it using pycrypto here's the code
from Crypto.Cipher import DES
from base64 import b64encode
def pad(s):
return s + (DES.block_size - len(s) % DES.block_size) * \
chr(DES.block_size - len(s) % DES.block_size)
def get_params(data):
params = ''
if not data:
return params
for key, value in data.iteritems():
if key and value:
params += '{0}={1}/\\\/'.format(key, value)
return params[:-4]
def des_encrypt(plain_text):
key = '3r108w5A'
des = DES.new(key)
return b64encode(des.encrypt(pad(plain_text)))
create_params = {'cagent': 'sample',
'loginname': 'sample',
'password': 'password',
'method': 'ca',
'actype': '0',
'cur': 'USD'}
params = des_encrypt(get_params(create_params))
Thanx to evry one help me ..but still there is 2 problem after editing the code
import java.io.*;
import java.math.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class RCC4 {
public RCC4(){}
public static void main(String[] args)throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException{
String test = "testisperfect";
System.out.println(RCC4.keyGet());
byte b[] = RCC4.keyGet().getBytes();
byte plain[] = test.getBytes();
**byte c[] = RCC4.encrypt(plain,b);**
**byte p[] = RCC4.decrypt(c,b);**
**System.out.println(new String(c)) ;
System.out.println(new String(p));**
}
public static byte[] encrypt(byte[] plaintext,byte[] keyBytes)
{
byte[] e = null;
try
{
Key key = new SecretKeySpec(keyBytes,"RC4");
Cipher enCipher = Cipher.getInstance("RC4");
**enCipher.init(Cipher.ENCRYPT_MODE ,key);**
e = enCipher.doFinal(plaintext);
}
catch(Exception ex)
{
ex.printStackTrace();
}
return e;
}
public static byte[] decrypt(byte[] ciphertext,byte[] keyBytes)
{
byte de[] = null;
try
{
Key key = new SecretKeySpec(keyBytes,"RC4");
Cipher deCipher = Cipher.getInstance("RC4");
**deCipher.init(Cipher.DECRYPT_MODE, key);**
de = deCipher.doFinal(ciphertext);
}
catch(Exception e)
{
e.printStackTrace();
}
return de;
}
public static Key getKey()
{
Key key = null;
try
{
SecureRandom sr = new SecureRandom();
KeyGenerator kg = KeyGenerator.getInstance("RC4");
kg.init(128,sr);
key = kg.generateKey();
}catch(Exception e)
{
e.printStackTrace();
}
return key;
}
public static String keyGet()
{
Key k = RCC4.getKey();
byte[] b = k.getEncoded();
BigInteger big = new BigInteger(b);
String s = big.toString();
return s;
}
}
When I press "Build file" it says process completed but at running file a message says
112670544188765215715791498302542646231
java.security.InvalidKeyException: Illegal key size or default parameters
at RCC4.encrypt(RCC4.java:37)
at RCC4.main(RCC4.java:23)
java.security.InvalidKeyException: Illegal key size or default parameters
at RCC4.decrypt(RCC4.java:53)
at RCC4.main(RCC4.java:24)
Exception in thread "main" java.lang.NullPointerException
at java.lang.String.<init>(String.java:479)
at RCC4.main(RCC4.java:26)
Process completed.
These Lines are indicated as *
Answer to original question:
Key key = new SecretKeySpec(byte[]keyBytes,RC4);
should be
Key key = new SecretKeySpec(keyBytes, "RC4");
Also,
deCipher.init(Cipher.WHATEVER, keyBytes);
should be
deCipher.init(Cipher.WHATEVER, key);
Then it compiles, however there's still some issue with the application logic. That's up to you again :).
Answer to new question:
The problem was the unneeded usage of SecretKeySpec. Somewhere between getKey(), keyGet() all the byte[] games and SecretKeySpec it got wrong somehow. I didn't have the patience to track it, so I just deleted it and made the code somewhat more readable to make sure I didn't miss anything. I think you will still understand it since it still is basically your code and it is much simpler now.
import java.security.*;
import javax.crypto.*;
public class RCC4 {
public static void main(String[] args) throws Exception {
String plain = "testisperfect";
Key key = RCC4.getKey();
String encrypted = RCC4.encrypt(plain, key);
String decrypted = RCC4.decrypt(encrypted, key);
System.out.println(encrypted);
System.out.println(decrypted);
}
private static String rc4(String plaintext, int mode, Key key) throws Exception {
Cipher cipher = Cipher.getInstance("RC4");
cipher.init(mode, key);
return new String(cipher.doFinal(plaintext.getBytes()));
}
public static String encrypt(String plaintext, Key key) throws Exception {
return rc4(plaintext, Cipher.ENCRYPT_MODE, key);
}
public static String decrypt(String ciphertext, Key key) throws Exception {
return rc4(ciphertext, Cipher.DECRYPT_MODE, key);
}
public static Key getKey() throws Exception {
KeyGenerator kg = KeyGenerator.getInstance("RC4");
SecureRandom sr = new SecureRandom();
kg.init(128, sr);
return kg.generateKey();
}
}
You need import SecretKeySpec which is under package javax.crypto.spec.
You're not calling the method correctly in that you're passing in the parameter type with the parameter. Parameter types are only shown when declaring a method, not when calling the method.
In other words, it's not
Key key = new SecretKeySpec(byte[] keyBytes, RC4);
it's instead
Key key = new SecretKeySpec(keyBytes, RC4);
You will of course need to have a keyBytes variable declared and initialized before trying to pass it into the parameter of this method.
package test;
import java.io.*;
import java.math.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class RCC4 {
public RCC4() {
}
public static void main(String[] args) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, IOException {
String test = "testisperfect";
System.out.println(RCC4.keyGet());
byte b[] = RCC4.keyGet().getBytes();
byte plain[] = test.getBytes();
byte c[] = RCC4.encrypt(plain, b);
byte p[] = RCC4.decrypt(c, b);
System.out.println(new String(c));
System.out.println(new String(p));
}
public static byte[] encrypt(byte[] plaintext, byte[] keyBytes) {
byte[] e = null;
try {
Key key = new SecretKeySpec(keyBytes, "RC4");
Cipher enCipher = Cipher.getInstance("RC4");
enCipher.init(Cipher.ENCRYPT_MODE, key);
e = enCipher.doFinal(plaintext);
} catch (Exception ex) {
ex.printStackTrace();
}
return e;
}
public static byte[] decrypt(byte[] ciphertext, byte[] keyBytes) {
byte de[] = null;
try {
Key key = new SecretKeySpec(keyBytes, "RC4");
Cipher deCipher = Cipher.getInstance("RC4");
deCipher.init(Cipher.DECRYPT_MODE, RCC4.getKey());
de = deCipher.doFinal(ciphertext);
} catch (Exception e) {
e.printStackTrace();
}
return de;
}
public static Key getKey() {
Key key = null;
try {
SecureRandom sr = new SecureRandom();
KeyGenerator kg = KeyGenerator.getInstance("RC4");
kg.init(128, sr);
key = kg.generateKey();
} catch (Exception e) {
e.printStackTrace();
}
return key;
}
public static String keyGet() {
Key k = RCC4.getKey();
byte[] b = k.getEncoded();
BigInteger big = new BigInteger(b);
String s = big.toString();
return s;
}
}