簡體   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