Thỉnh thoảng, tôi gặp một điều thú vị, lạ: cùng một khối văn bản được mã hóa có thể được giải mã bằng nhiều phím khác nhau!Hành vi DES lạ - giải mã thành công bằng cách sử dụng các phím khác nhau
Có ai vui lòng cho tôi biết điều gì đang xảy ra không? Cảm ơn rất nhiều.
Xin vui lòng không cố gắng để tôi chuyển sang ba DES/AES vv, tôi chỉ muốn biết vấn đề ở đâu - cách gọi Java SDK, hoặc lỗi trong Java SDK?
Dưới đây là đầu ra trên Windows 7, cùng kết quả trong Linux hộp:
D:\>java -version
java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)
D:\>java DESTest -e 12345678 abcde977
encrypted as [17fd146fa6fdbb5db667efe657dfcb60]
D:\>java DESTest -d 17fd146fa6fdbb5db667efe657dfcb60 abcde977
decryted as [12345678]
D:\>java DESTest -d 17fd146fa6fdbb5db667efe657dfcb60 abcde976
decryted as [12345678]
D:\>java DESTest -d 17fd146fa6fdbb5db667efe657dfcb60 abcde967
decryted as [12345678]
D:\>java DESTest -d 17fd146fa6fdbb5db667efe657dfcb60 abcde867
decryted as [12345678]
D:\>java DESTest -d 17fd146fa6fdbb5db667efe657dfcb60 abcdf867
Exception in thread "main" java.lang.RuntimeException: javax.crypto.BadPaddingEx
ception: Given final block not properly padded
at DESTest.des(DESTest.java:46)
at DESTest.dec(DESTest.java:31)
at DESTest.main(DESTest.java:19)
Caused by: javax.crypto.BadPaddingException: Given final block not properly padd
ed
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.DESCipher.engineDoFinal(DESCipher.java:314)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at DESTest.des(DESTest.java:44)
... 2 more
D:\>java DESTest -e 12345678 abcde976
encrypted as [17fd146fa6fdbb5db667efe657dfcb60]
D:\>java DESTest -e 12345678 abcde967
encrypted as [17fd146fa6fdbb5db667efe657dfcb60]
D:\>
Mã nguồn:
import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
public class DESTest {
public static void main(String[] args) {
if (args.length < 3) {
System.out.println("usage: java " + DESTest.class.getCanonicalName() + " -e|-d text key");
return;
}
String mode = args[0].trim();
String text = args[1].trim();
String key = args[2].trim();
try {
String s = "-d".equalsIgnoreCase(mode) ? dec(text, key) : enc(text, key);
System.out.println("\n" + ("-d".equalsIgnoreCase(mode) ? "decryted as [" : "encrypted as [") + s + "]");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
private static String enc(String plainText, String key) throws UnsupportedEncodingException {
return new String(encHex(des(plainText.getBytes("UTF-8"), key, Cipher.ENCRYPT_MODE)));
}
private static String dec(String encrypted, String key) throws UnsupportedEncodingException {
return new String(des(decHex(encrypted), key, Cipher.DECRYPT_MODE), "UTF-8");
}
private static byte[] des(byte[] bytes, String key, int cipherMode) {
final String encoding = "UTF-8";
try {
DESKeySpec desKey = new DESKeySpec(key.getBytes(encoding));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey securekey = keyFactory.generateSecret(desKey);
// SecretKey securekey = new SecretKeySpec(key.getBytes(encoding), "DES");//same result as the 3 lines above
Cipher cipher = Cipher.getInstance("DES");
SecureRandom random = new SecureRandom();
cipher.init(cipherMode, securekey, random);
return cipher.doFinal(bytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static final char[] HEX_CHARS = "abcdef".toCharArray();
private static String encHex(byte[] bytes) {
final char[] chars = new char[bytes.length * 2];
for (int i = 0, j = 0; i < bytes.length; i++) {
chars[j++] = HEX_CHARS[(0xF0 & bytes[i]) >>> 4];
chars[j++] = HEX_CHARS[0x0F & bytes[i]];
}
return new String(chars);
}
private static byte[] decHex(String hex) {
final int len = hex.length();
final byte[] bytes = new byte[len/2];
for (int i = 0, j = 0; j < len; i++) {
int f = Character.digit(hex.charAt(j), 16) << 4;
j++;
f = f | Character.digit(hex.charAt(j), 16);
j++;
bytes[i] = (byte) (f & 0xFF);
}
return bytes;
}
}
Tôi gỡ lỗi mã, thấy rằng chuỗi khóa khác nhau sẽ tạo cùng một khóa bảo mật (dòng 39), tức là [97, 98, 98, 100, 100, 56, 55, 55], cùng một secureKey gây ra thành công của giải mã . nhưng tôi không biết tại sao khóa khác nhau sẽ tạo ra cùng một khóa bảo mật, và làm thế nào để tránh nó? – reqresp