简体   繁体   English

C 的 Crypt() 像 Java 中的 function

[英]C's Crypt() like function in Java

I have been reading some codes regarding encrypting a password in Java.我一直在阅读 Java 中有关加密密码的一些代码。 Which seems a bit more computing intensive.这似乎有点计算密集型。

Is there a quick way to encrypt a string similar to C or Ruby?有没有一种快速的方法来加密类似于 C 或 Ruby 的字符串?

For example, in Ruby:例如,在 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 :方法String#crypt()来自 C,在 Linux 中用于将散列密码存储在/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:知道我的系统密码是55,在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.所以系统可以确认我的密码是55,让我登录。

Is there a similar method in Java that can encrypt a string? Java中是否有类似的方法可以加密字符串? Can I similarly run 'string.crypt("$6$salt")' and decrypt /etc/shadow 's account password if the account password is given?如果给出了帐户密码,我可以类似地运行 'string.crypt("$6$salt")' 并解密/etc/shadow的帐户密码吗?

Java includes since 1.4 a package named javax.crypto , which allows you to encrypt and decrypt data using a Cipher. Java 自 1.4 起包含名为javax.crypto的 package ,它允许您使用密码加密和解密数据。

TutorialsPoint has a tutorial for this package. TutorialsPoint有这个 package 的教程。 Here is a little Java snippet which first encrypts data, then decrypts it:这是一个小的 Java 片段,它首先加密数据,然后解密它:

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.没有那么简单,但仍然很简单。

and decrypt /etc/shadow's account password if the account password is given如果给出帐户密码,则解密 /etc/shadow 的帐户密码

The crypt() function is not encryption, the function creates a salted password hash. crypt() function 没有加密,function 创建一个加盐密码 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. Hash 是一种单向 function,其主要功能之一是没有人应该能够根据(加密)hash 值恢复密码。

So the system can confirm my password is 55 and let me log in.所以系统可以确认我的密码是55,让我登录。

This is possible.这个有可能。 Effectively you compute a new salted hash (using the same salt) and compare with the stored value.实际上,您计算了一个新的盐渍 hash(使用相同的盐)并与存储的值进行比较。

Is there a similar method in Java that can encrypt a string? Java中是否有类似的方法可以加密字符串?

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");
}

The crypt C library function uses DES as its encryption. crypt C 库 function 使用 DES 作为其加密。 You have to use the same algorithm if you want exactly the same result in Java.如果您想要 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/您可以在这里找到教程: https://www.mkyong.com/java/jce-encryption-data-encryption-standard-des-tutorial/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM