Reputation: 2077
I have been reading some codes regarding encrypting a password in Java. Which seems a bit more computing intensive.
Is there a quick way to encrypt a string similar to C or Ruby?
For example, in Ruby:
'hello'.crypt('$6$salt') # => "$6$salt$ghQ6Rhatj/sug12c6v8Ao/bXUoyJ1O1SqdumufgGEO3b3NYPvm/dSWDKWfNm1VxFoFiy/cw9eRaY0xu4GDQSU/"
The method String#crypt()
is from C, which is used in Linux to store hashed password in /etc/shadow
:
$ sudo cat /etc/shadow | grep $USER
sourav:$6$Vx0wkV1M2PM43WOE$b2pYu.funKjk/snGSqiMTgh1e9dGQYDEKrjfuc2T/tP5qs7lXU56MjFvWd35rgzmYBXK33DrjQqnxTcPtcMXi/:18013:0:99999:7:::
Here's a small program...
Knowing that my system password is 55, in Ruby:
pass = IO.readlines('/etc/shadow').find { |x| x.start_with?(ENV['USER']) }
=> "sourav:$6$Vx0wkV1M2PM43WOE$b2pYu.funKjk/snGSqiMTgh1e9dGQYDEKrjfuc2T/tP5qs7lXU56MjFvWd35rgzmYBXK33DrjQqnxTcPtcMXi/:18013:0:99999:7:::\n"
h = ?$ + pass.split(?$)[1..2].join(?$)
=> "$6$Vx0wkV1M2PM43WOE"
s = pass.split(?$)[-1].split(?:)[0]
=> "b2pYu.funKjk/snGSqiMTgh1e9dGQYDEKrjfuc2T/tP5qs7lXU56MjFvWd35rgzmYBXK33DrjQqnxTcPtcMXi/"
hs = h + ?$ + s
=> "$6$Vx0wkV1M2PM43WOE$b2pYu.funKjk/snGSqiMTgh1e9dGQYDEKrjfuc2T/tP5qs7lXU56MjFvWd35rgzmYBXK33DrjQqnxTcPtcMXi/"
'55'.crypt(h) == hs
=> true
So the system can confirm my password is 55 and let me log in.
Is there a similar method in Java that can encrypt a string? Can I similarly run 'string.crypt("$6$salt")' and decrypt /etc/shadow
's account password if the account password is given?
Upvotes: 2
Views: 1030
Reputation: 12085
and decrypt /etc/shadow's account password if the account password is given
The crypt() function is not encryption, the function creates a salted password hash.
Hash is a one-way function and one of its primary features is that nobody should be able to recover password based from the (cryptographic) hash value.
So the system can confirm my password is 55 and let me log in.
This is possible. Effectively you compute a new salted hash (using the same salt) and compare with the stored value.
Is there a similar method in Java that can encrypt a string?
import org.apache.commons.codec.digest.Crypt;
...
String hash = Crypt.crypt("password".getBytes());
System.out.println("salted hash: "+hash);
// salt is $X$some_bytes
String salt = hash.substring(0, hash.indexOf("$", 3));
System.out.println("salt: "+salt);
// validation:
String testString = Crypt.crypt("password", salt);
if(testString.equals(hash)) {
System.out.println("Password match");
} else {
System.out.println("Invalid password");
}
Upvotes: 2
Reputation: 22168
The crypt C library function uses DES as its encryption. You have to use the same algorithm if you want exactly the same result in Java.
In a nutshell:
KeyGenerator keygenerator = KeyGenerator.getInstance("DES");
SecretKey desKey = keygenerator.generateKey();
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, desKey);
byte[] encrypted = desCipher.doFinal(clearText.getBytes());
You can find a tutorial here: https://www.mkyong.com/java/jce-encryption-data-encryption-standard-des-tutorial/
Upvotes: -2
Reputation: 1851
Java includes since 1.4 a package named javax.crypto
, which allows you to encrypt and decrypt data using a Cipher.
TutorialsPoint has a tutorial for this package. Here is a little Java snippet which first encrypts data, then decrypts it:
public class CipherSample {
public static void main(String args[]) throws Exception{
//Creating a Signature object
Signature sign = Signature.getInstance("SHA256withRSA");
//Creating KeyPair generator object
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
//Initializing the key pair generator
keyPairGen.initialize(2048);
//Generating the pair of keys
KeyPair pair = keyPairGen.generateKeyPair();
//Creating a Cipher object
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
//Initializing a Cipher object
cipher.init(Cipher.ENCRYPT_MODE, pair.getPublic());
//Adding data to the cipher
byte[] input = "Welcome to Tutorialspoint".getBytes();
cipher.update(input);
//encrypting the data
byte[] cipherText = cipher.doFinal();
System.out.println(new String(cipherText, "UTF8"));
//Initializing the same cipher for decryption
cipher.init(Cipher.DECRYPT_MODE, pair.getPrivate());
//Decrypting the text
byte[] decipheredText = cipher.doFinal(cipherText);
System.out.println(new String(decipheredText));
}
}
Not as straightforward, but still simple.
Upvotes: 2