繁体   English   中英

C 的 Crypt() 像 Java 中的 function

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

我一直在阅读 Java 中有关加密密码的一些代码。 这似乎有点计算密集型。

有没有一种快速的方法来加密类似于 C 或 Ruby 的字符串?

例如,在 Ruby 中:

'hello'.crypt('$6$salt') # => "$6$salt$ghQ6Rhatj/sug12c6v8Ao/bXUoyJ1O1SqdumufgGEO3b3NYPvm/dSWDKWfNm1VxFoFiy/cw9eRaY0xu4GDQSU/"

方法String#crypt()来自 C,在 Linux 中用于将散列密码存储在/etc/shadow中:

$ sudo cat /etc/shadow | grep $USER
sourav:$6$Vx0wkV1M2PM43WOE$b2pYu.funKjk/snGSqiMTgh1e9dGQYDEKrjfuc2T/tP5qs7lXU56MjFvWd35rgzmYBXK33DrjQqnxTcPtcMXi/:18013:0:99999:7:::

这是一个小程序...

知道我的系统密码是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

所以系统可以确认我的密码是55,让我登录。

Java中是否有类似的方法可以加密字符串? 如果给出了帐户密码,我可以类似地运行 'string.crypt("$6$salt")' 并解密/etc/shadow的帐户密码吗?

Java 自 1.4 起包含名为javax.crypto的 package ,它允许您使用密码加密和解密数据。

TutorialsPoint有这个 package 的教程。 这是一个小的 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));
  }
}

没有那么简单,但仍然很简单。

如果给出帐户密码,则解密 /etc/shadow 的帐户密码

crypt() function 没有加密,function 创建一个加盐密码 hash。

Hash 是一种单向 function,其主要功能之一是没有人应该能够根据(加密)hash 值恢复密码。

所以系统可以确认我的密码是55,让我登录。

这个有可能。 实际上,您计算了一个新的盐渍 hash(使用相同的盐)并与存储的值进行比较。

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

crypt C 库 function 使用 DES 作为其加密。 如果您想要 Java 中的结果完全相同,则必须使用相同的算法。

简而言之:

    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());

您可以在这里找到教程: 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