我正在尝试学习和测试java 1.6加密/解密API。我想知道我做错了什么以及我在知识方面缺少什么。
在下面的代码中,我创建了两个密码:一个用于加密,另一个用于解密。当我使用这些密码时,我使用不同的SecretKey初始化它们,但我仍然能够获得相同的值。这是为什么?
String algorithm = "DES";
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
byte[] encBytes = "12345678".getBytes("UTF8");
byte[] decBytes = "56781234".getBytes("UTF8");
DESKeySpec keySpecEncrypt = new DESKeySpec(encBytes);
DESKeySpec keySpecDecrypt = new DESKeySpec(decBytes);
SecretKey keyEncrypt = keyFactory.generateSecret(keySpecEncrypt);
SecretKey keyDecrypt = keyFactory.generateSecret(keySpecDecrypt);
Cipher cipherEncrypt = Cipher.getInstance(algorithm);
Cipher cipherDecrypt = Cipher.getInstance(algorithm);
String input = "john doe";
cipherEncrypt.init(Cipher.ENCRYPT_MODE, keyEncrypt);
byte[] inputBytes = cipherEncrypt.doFinal(input.getBytes());
System.out.println("inputBytes: " + new String(inputBytes));
cipherDecrypt.init(Cipher.DECRYPT_MODE, keyDecrypt);
byte[] outputBytes = cipherDecrypt.doFinal(inputBytes);
System.out.println("outputBytes: " + new String(outputBytes));
答案 0 :(得分:16)
欢迎加密!如上所述,DES是对称的,并且需要与解密相同的加密密钥。该密钥需要是您正在使用的密码的正确位数。对于那个56位的DES。在您走得太远之前,您可能需要考虑以下几点:
以下是使用PKCS#5填充在CBC模式下使用128位AES加密的工作示例:
import java.security.MessageDigest;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class EncryptDecrypt {
public static void main(String[] args) throws Exception {
// here are your inputs
String keyString = "averylongtext!@$@#$#@$#*&(*&}{23432432432dsfsdf";
String input = "john doe";
// setup AES cipher in CBC mode with PKCS #5 padding
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// setup an IV (initialization vector) that should be
// randomly generated for each input that's encrypted
byte[] iv = new byte[cipher.getBlockSize()];
new SecureRandom().nextBytes(iv);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
// hash keyString with SHA-256 and crop the output to 128-bit for key
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(keyString.getBytes());
byte[] key = new byte[16];
System.arraycopy(digest.digest(), 0, key, 0, key.length);
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
// encrypt
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encrypted = cipher.doFinal(input.getBytes("UTF-8"));
System.out.println("encrypted: " + new String(encrypted));
// include the IV with the encrypted bytes for transport, you'll
// need the same IV when decrypting (it's safe to send unencrypted)
// decrypt
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] decrypted = cipher.doFinal(encrypted);
System.out.println("decrypted: " + new String(decrypted, "UTF-8"));
}
}
答案 1 :(得分:5)
以下是JDK doc的描述:
DESKeySpec public DESKeySpec(byte[] key) throws InvalidKeyException Creates a DESKeySpec object using the first 8 bytes in key as the key material for the DES key. The bytes that constitute the DES key are those between key[0] and key[7] inclusive.
DESKeySpec仅使用byte []的前8个字节作为键。因此,在您的示例中,使用的实际键是相同的。
答案 2 :(得分:0)
这是使用56位DES加密的一个工作示例。
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class CipherHelper {
// Algorithm used
private final static String ALGORITHM = "DES";
/**
* Encrypt data
* @param secretKey - a secret key used for encryption
* @param data - data to encrypt
* @return Encrypted data
* @throws Exception
*/
public static String cipher(String secretKey, String data) throws Exception {
// Key has to be of length 8
if (secretKey == null || secretKey.length() != 8)
throw new Exception("Invalid key length - 8 bytes key needed!");
SecretKey key = new SecretKeySpec(secretKey.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
return toHex(cipher.doFinal(data.getBytes()));
}
/**
* Decrypt data
* @param secretKey - a secret key used for decryption
* @param data - data to decrypt
* @return Decrypted data
* @throws Exception
*/
public static String decipher(String secretKey, String data) throws Exception {
// Key has to be of length 8
if (secretKey == null || secretKey.length() != 8)
throw new Exception("Invalid key length - 8 bytes key needed!");
SecretKey key = new SecretKeySpec(secretKey.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
return new String(cipher.doFinal(toByte(data)));
}
// Helper methods
private static byte[] toByte(String hexString) {
int len = hexString.length()/2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
return result;
}
public static String toHex(byte[] stringBytes) {
StringBuffer result = new StringBuffer(2*stringBytes.length);
for (int i = 0; i < stringBytes.length; i++) {
result.append(HEX.charAt((stringBytes[i]>>4)&0x0f)).append(HEX.charAt(stringBytes[i]&0x0f));
}
return result.toString();
}
private final static String HEX = "0123456789ABCDEF";
// Helper methods - end
/**
* Quick test
* @param args
*/
public static void main(String[] args) {
try {
String secretKey = "01234567";
String data="test";
String encryptedData = cipher(secretKey, data);
System.out.println("encryptedData: " + encryptedData);
String decryptedData = decipher(secretKey, encryptedData);
System.out.println("decryptedData: " + decryptedData);
} catch (Exception e) {
e.printStackTrace();
}
}
}