15 Volts
15 Volts

Reputation: 2077

C's Crypt() like function in Java

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

Answers (3)

gusto2
gusto2

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

jbx
jbx

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

Yassine Badache
Yassine Badache

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

Related Questions