基本上我发现这个代码由某人发布,它允许您使用AES加密消息并对其进行解密。我有点新加密这个加密的东西,我想知道,它使用的种子价值在哪里,每次种子随机化?因为从它的外观来看,相同的String会给出不同的加密结果。
感谢。
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
public class AESGUI extends JPanel {
public static void main(String[] args) {
JFrame frame = new JFrame("AES Encryption");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(600,300));
frame.setLocationRelativeTo(null);
frame.setResizable(false);
AESGUI p = new AESGUI();
frame.getContentPane().add(p);
frame.pack();
frame.setVisible(true);
}
private JTextField in;
private JTextArea out;
public AESGUI() {
JLabel info = new JLabel("Type any String");
in = new JTextField(20);
JButton encrypt = new JButton("Encrypt");
out = new JTextArea(10,40);
out.setEditable(false);
encrypt.addActionListener(new encryptListener());
in.addActionListener(new encryptListener());
add(info);
add(in);
add(encrypt);
add(out);
add(new JScrollPane(out));
}
private class encryptListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String data = in.getText();
if (data.length() == 0) { }
else
try {
String en = encrypt(data);
out.append("Encrypted string: " + en + "\n");
out.append("Original String: " + decrypt(en) + "\n\n");
} catch(Exception ex) { }
}
}
public String asHex(byte[] buf) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}
private SecretKeySpec skeySpec;
private Cipher cipher;
private byte[] encrypted;
public String encrypt(String str) throws Exception {
// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available
// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
skeySpec = new SecretKeySpec(raw, "AES");
// Instantiate the cipher
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
encrypted = cipher.doFinal(str.getBytes());
return asHex(encrypted);
}
public String decrypt(String str) throws Exception {
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] original = cipher.doFinal(encrypted);
String originalString = new String(original);
return originalString;
}
}
没有gui(我希望我删除所有内容)
public String asHex(byte[] buf) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}
private SecretKeySpec skeySpec;
private Cipher cipher;
private byte[] encrypted;
public String encrypt(String str) throws Exception {
// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available
// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
skeySpec = new SecretKeySpec(raw, "AES");
// Instantiate the cipher
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
encrypted = cipher.doFinal(str.getBytes());
return asHex(encrypted);
}
public String decrypt(String str) throws Exception {
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] original = cipher.doFinal(encrypted);
String originalString = new String(original);
return originalString;
}
答案 0 :(得分:5)
是的,它为同一文本提供了不同的结果,原因是每次加密生成密钥的邮件。
// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available
// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
skeySpec = new SecretKeySpec(raw, "AES");
你可以做的是,从encrypt()方法中取出它并使它变得普遍。
答案 1 :(得分:5)
它使用的种子值在哪里,每次种子随机化?
Javadocs是你的朋友年轻的padawan;)从你的代码示例中,我们看到你正在调用keyGenerator.init(int keysize)
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available
检查the javadoc对该类的方法调用,我们得到以下内容:
为某个密钥大小初始化此密钥生成器。如果这个键 生成器需要任何随机字节,它将使用它来获取它们 SecureRandom实施最高优先级的安装提供商 作为随机性的来源。 (如果没有安装的提供商 提供SecureRandom的实现,SecureRandom是系统提供的 随机性将被使用。)
换句话说,正如您最初猜测的那样,对init(int keysize)
的调用意味着每次使用随机种子。如果你有一个特定的种子,1)对你需要的东西有好处,2)你需要使用,那么你需要使用init(int keysize,SecureRandom random)
,或者拨打[init(SecureRandom random)][4]
和你的其他电话一起使用init(int keysize)
。
希望它有所帮助。
顺便说一下,如果你想更深入地介绍密码学,我建议你得到Alfred Menezes,Paul van Oorschot和Scott Vanstone的Handbook of Applied Cryptography (Discrete Mathematics and Its Applications)。虽然1996年出版,但我一直都在谈论这本书。关于密码学理论研究的一本书将是Understanding Cryptography: A Textbook for Students and Practitioners。它是高度数学的,如果你最终想成为一名加密/密码学家,你需要这个。对于加密工具和算法的整体使用和理解,Menezes等上面提到的所有书都是一个好的开始。
为了全面了解计算机安全主题,我建议Edward G. Amoroso Fundamentals of Computer Security Technology。对于它的价值,我总是把这本书和我一起作为参考。
答案 2 :(得分:3)
通常在生成钥匙时使用盐。
private SecretKey getKey(final String passPhrase, final String salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
final PBEKeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt.getBytes(), ITERATIONS, 128); // 128bit key length
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_FACTORY_MODE);
final SecretKey key = keyFactory.generateSecret(keySpec);
return key;
}
然而,该算法也使用初始化矢量“播种”。
private static final SecureRandom random = new SecureRandom();
private IvParameterSpec getIV(final Cipher cipher) {
final byte[] ivBytes = new byte[cipher.getBlockSize()];
random.nextBytes(ivBytes);
return new IvParameterSpec(ivBytes);
}
所以你会按照以下方式传递盐渍键和IV:
final SecretKey key = getKey(passPhrase, salt);
final Cipher cipher = Cipher.getInstance("AES/CTR/NOPADDING");
final IvParameterSpec iv = getIV(cipher);
cipher.init(cipherMode, key, iv, random);