我发现了一个问题,Elephantik的回答基本上回答了我的问题: DES Initialization Vector in C#
我有一个用DES.EXE命令行工具加密的文件。我可以使用以下命令解密它:“des -D -k YSTxyHBH file.cr file.txt”
使用此命令我得到一个解密的file.txt,但我需要用Java解密这个文件。
所以我试图将解决方案从Elephantik转移到Java,但是我的解决方案必须有问题,因为当我调用decryptData(...)方法时,我只得到一些加密文本。
public byte[] decryptData(byte input[], String password) throws Exception {
byte[] result = null;
//Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
//byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] iv = { -128, -128, -128, -128, -128, -128, -128, -128 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, generateSecretKey(passwordToKey(password)), ivspec);
result = cipher.doFinal(input);
return result;
}
protected SecretKey generateSecretKey(byte[] key) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
KeySpec keySpec = new DESKeySpec(key);
SecretKey secretKey = factory.generateSecret(keySpec);
return secretKey;
}
public byte[] passwordToKey(String password) throws Exception
{
if (password == null)
throw new IllegalArgumentException("password");
if (password == "")
throw new IllegalArgumentException("password");
byte[] key = new byte[8];
for (int i = 0; i < password.length(); i++)
{
int c = (int)password.charAt(i);
if ((i % 16) < 8)
{
key[i % 8] ^= (byte)(c << 1);
}
else
{
// reverse bits e.g. 11010010 -> 01001011
c = (((c << 4) & 0xf0) | ((c >> 4) & 0x0f));
c = (((c << 2) & 0xcc) | ((c >> 2) & 0x33));
c = (((c << 1) & 0xaa) | ((c >> 1) & 0x55));
key[7 - (i % 8)] ^= (byte)c;
}
}
addOddParity(key);
byte[] target = new byte[8];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
outputStream.write(password.getBytes("US-ASCII"));
outputStream.write(new byte[8]);
byte[] temp = outputStream.toByteArray();
outputStream = new ByteArrayOutputStream( );
for (int i = 0; i < (password.length() + (8 - (password.length() % 8)) % 8); ++i) {
outputStream.write(temp[i]);
}
byte[] passwordBuffer = outputStream.toByteArray();
Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
//byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] iv = { -128, -128, -128, -128, -128, -128, -128, -128 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, generateSecretKey(key), ivspec);
for (int x = 0; x < passwordBuffer.length / 8; ++x)
{
cipher.update(passwordBuffer, 8 * x, 8, target, 0);
}
addOddParity(target);
return target;
}
private void addOddParity(byte[] buffer)
{
for (int i = 0; i < buffer.length; ++i)
{
buffer[i] = _oddParityTable[buffer[i] & 0xFF];
}
}
private static byte[] _oddParityTable = {
-127,-127,-126,-126,-124,-124,-121,-121,-120,-120,-117,-117,-115,-115,-114,-114,
-112,-112,-109,-109,-107,-107,-106,-106,-103,-103,-102,-102,-100,-100, -97, -97,
-96, -96, -93, -93, -91, -91, -90, -90, -87, -87, -86, -86, -84, -84, -81, -81,
-79, -79, -78, -78, -76, -76, -73, -73, -72, -72, -69, -69, -67, -67, -66, -66,
-64, -64, -61, -61, -59, -59, -58, -58, -55, -55, -54, -54, -52, -52, -49, -49,
-47, -47, -46, -46, -44, -44, -41, -41, -40, -40, -37, -37, -35, -35, -34, -34,
-31, -31, -30, -30, -28, -28, -25, -25, -24, -24, -21, -21, -19, -19, -18, -18,
-16, -16, -13, -13, -11, -11, -10, -10, -7, -7, -6, -6, -4, -4, -1, -1,
0, 0, 3, 3, 5, 5, 6, 6, 9, 9, 10, 10, 12, 12, 15, 15,
17, 17, 18, 18, 20, 20, 23, 23, 24, 24, 27, 27, 29, 29, 30, 30,
33, 33, 34, 34, 36, 36, 39, 39, 40, 40, 43, 43, 45, 45, 46, 46,
48, 48, 51, 51, 53, 53, 54, 54, 57, 57, 58, 58, 60, 60, 63, 63,
65, 65, 66, 66, 68, 68, 71, 71, 72, 72, 75, 75, 77, 77, 78, 78,
80, 80, 83, 83, 85, 85, 86, 86, 89, 89, 90, 90, 92, 92, 95, 95,
96, 96, 99, 99, 101, 101, 102, 102, 105, 105, 106, 106, 108, 108, 111, 111,
113, 113, 114, 114, 116, 116, 119, 119, 120, 120, 123, 123, 125, 125, 126, 126
};
答案 0 :(得分:0)
cipher.init(Cipher.ENCRYPT_MODE, generateSecretKey(key), ivspec);
您需要将相同的 键 作为 初始化向量 传递,但不是IV你有。 des.exe程序基于LibDes库的源代码。您可以在文档和源代码中找到所有详细信息。你提到了des -D
参数。这意味着您需要使用 CBC / NoPadding 模式解密 DES 。还要检查您拥有的_oddParityTable
方法。
如果您的文件不是UUdecoded,请省略我的代码中的相关部分。
这是Java编写的例子:
public class UUDES {
public static void main (String[] args) throws Exception
{
String password = "xxxxxx";
String pathToUUEencodedEncryptedFile = "C:\DES\path-to-decoded-and-encrypted-file";
byte[] secretKey = passwordToKey(password);
byte[] iv = new byte[8];
byte[] uuEncodedFile = Files.readAllBytes(Paths.get(pathToUUEencodedEncryptedFile));
SecretKey key = new SecretKeySpec(secretKey, "DES");
Cipher decryptor = Cipher.getInstance("DES/CBC/NoPadding");
decryptor.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
ByteArrayOutputStream bout = new ByteArrayOutputStream();
InputStream in = null;
try {
in = MimeUtility.decode(new ByteArrayInputStream(uuEncodedFile), "uuencode");
byte[] buf = new byte[1024];
int length;
while (true) {
length = in.read(buf);
if (length == -1) {
break;
}
bout.write(buf, 0, length);
}
byte[] bytesDecrypted = decryptor.doFinal(bout.toByteArray());
ByteArrayInputStream bais = new ByteArrayInputStream(bytesDecrypted);
GZIPInputStream gzis = new GZIPInputStream(bais);
InputStreamReader reader = new InputStreamReader(gzis);
BufferedReader buffer = new BufferedReader(reader);
String readed;
while ((readed = buffer.readLine()) != null) {
System.out.println(readed);
}
}
finally {
if (in != null) {
try {
in.close();
}
catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
}
static SecretKey generateSecretKey(byte[] key) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
KeySpec keySpec = new DESKeySpec(key);
SecretKey secretKey = factory.generateSecret(keySpec);
return secretKey;
}
static byte[] passwordToKey(String password) throws Exception
{
if (password == null)
throw new IllegalArgumentException("password");
if (password == "")
throw new IllegalArgumentException("password");
byte[] key = new byte[8];
for (int i = 0; i < password.length(); i++)
{
int c = (int)password.charAt(i);
if ((i % 16) < 8)
{
key[i % 8] ^= (byte)(c << 1);
}
else
{
// reverse bits e.g. 11010010 -> 01001011
c = (((c << 4) & 0xf0) | ((c >> 4) & 0x0f));
c = (((c << 2) & 0xcc) | ((c >> 2) & 0x33));
c = (((c << 1) & 0xaa) | ((c >> 1) & 0x55));
key[7 - (i % 8)] ^= (byte)c;
}
}
addOddParity(key);
byte[] target = new byte[8];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
outputStream.write(password.getBytes("US-ASCII"));
outputStream.write(new byte[8]);
byte[] temp = outputStream.toByteArray();
outputStream = new ByteArrayOutputStream( );
for (int i = 0; i < (password.length() + (8 - (password.length() % 8)) % 8); ++i) {
outputStream.write(temp[i]);
}
byte[] passwordBuffer = outputStream.toByteArray();
Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
byte[] iv = key;
IvParameterSpec ivspec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, generateSecretKey(key), ivspec);
for (int x = 0; x < passwordBuffer.length / 8; ++x)
{
cipher.update(passwordBuffer, 8 * x, 8, target, 0);
}
addOddParity(target);
return target;
}
static void addOddParity(byte[] buffer)
{
for (int i = 0; i < buffer.length; ++i)
{
buffer[i] = _oddParityTable[buffer[i] & 0xFF];
}
}
static byte[] _oddParityTable = {
(byte)1,(byte)1,(byte)2,(byte)2,(byte)4,(byte)4,(byte)7,(byte)7,(byte)8,(byte)8,(byte)11,(byte)11,(byte)13,(byte)13,(byte)14,(byte)14,
(byte)16,(byte)16,(byte)19,(byte)19,(byte)21,(byte)21,(byte)22,(byte)22,(byte)25,(byte)25,(byte)26,(byte)26,(byte)28,(byte)28,(byte)31,(byte)31,
(byte)32,(byte)32,(byte)35,(byte)35,(byte)37,(byte)37,(byte)38,(byte)38,(byte)41,(byte)41,(byte)42,(byte)42,(byte)44,(byte)44,(byte)47,(byte)47,
(byte)49,(byte)49,(byte)50,(byte)50,(byte)52,(byte)52,(byte)55,(byte)55,(byte)56,(byte)56,(byte)59,(byte)59,(byte)61,(byte)61,(byte)62,(byte)62,
(byte)64,(byte)64,(byte)67,(byte)67,(byte)69,(byte)69,(byte)70,(byte)70,(byte)73,(byte)73,(byte)74,(byte)74,(byte)76,(byte)76,(byte)79,(byte)79,
(byte)81,(byte)81,(byte)82,(byte)82,(byte)84,(byte)84,(byte)87,(byte)87,(byte)88,(byte)88,(byte)91,(byte)91,(byte)93,(byte)93,(byte)94,(byte)94,
(byte)97,(byte)(byte)97,(byte)(byte)98,(byte)(byte)98,(byte)100,(byte)100,(byte)103,(byte)103,(byte)104,(byte)104,(byte)107,(byte)107,(byte)109,(byte)109,(byte)110,(byte)110,
(byte)112,(byte)112,(byte)115,(byte)115,(byte)117,(byte)117,(byte)118,(byte)118,(byte)121,(byte)121,(byte)122,(byte)122,(byte)124,(byte)124,(byte)127,(byte)127,
(byte)128,(byte)128,(byte)131,(byte)131,(byte)133,(byte)133,(byte)134,(byte)134,(byte)137,(byte)137,(byte)138,(byte)138,(byte)140,(byte)140,(byte)143,(byte)143,
(byte)145,(byte)145,(byte)146,(byte)146,(byte)148,(byte)148,(byte)151,(byte)151,(byte)152,(byte)152,(byte)155,(byte)155,(byte)157,(byte)157,(byte)158,(byte)158,
(byte)161,(byte)161,(byte)162,(byte)162,(byte)164,(byte)164,(byte)167,(byte)167,(byte)168,(byte)168,(byte)171,(byte)171,(byte)173,(byte)173,(byte)174,(byte)174,
(byte)176,(byte)176,(byte)179,(byte)179,(byte)181,(byte)181,(byte)182,(byte)182,(byte)185,(byte)185,(byte)186,(byte)186,(byte)188,(byte)188,(byte)191,(byte)191,
(byte)193,(byte)193,(byte)194,(byte)194,(byte)196,(byte)196,(byte)199,(byte)199,(byte)200,(byte)200,(byte)203,(byte)203,(byte)205,(byte)205,(byte)206,(byte)206,
(byte)208,(byte)208,(byte)211,(byte)211,(byte)213,(byte)213,(byte)214,(byte)214,(byte)217,(byte)217,(byte)218,(byte)218,(byte)220,(byte)220,(byte)223,(byte)223,
(byte)224,(byte)224,(byte)227,(byte)227,(byte)229,(byte)229,(byte)230,(byte)230,(byte)233,(byte)233,(byte)234,(byte)234,(byte)236,(byte)236,(byte)239,(byte)239,
(byte)241,(byte)241,(byte)242,(byte)242,(byte)244,(byte)244,(byte)247,(byte)247,(byte)248,(byte)248,(byte)251,(byte)251,(byte)253,(byte)253,(byte)254,(byte)254};
}