Java - 将字符串转换为DES密钥

3
我得到了一个字符串密钥和一个使用DES加密的文件,这就是我所知道的全部。我不知道密钥是如何编码的。
还有一个des.exe可以用来解密,这是我在互联网上找到的: http://knowledge-republic.com/CRM/2011/07/how-to-decrypt-extract-recreate-thecus-storage-firmware/ 使用des.exe,唯一有效的命令是"-D",而不是"-d"。
我的目标是使用Java完成同样的事情。我从某个地方复制并粘贴了这段代码。
    String key = "blah";
    DESKeySpec dks = new DESKeySpec(key.getBytes());
    SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
    SecretKey desKey = skf.generateSecret(dks);
    System.out.println(desKey);

    Cipher cipher = Cipher.getInstance("DES"); // DES/ECB/PKCS5Padding for SunJCE

    if (mode == Cipher.DECRYPT_MODE) {
        cipher.init(Cipher.DECRYPT_MODE, desKey);
        CipherOutputStream cos = new CipherOutputStream(os, cipher);
        doCopy(is, cos);
    }

它不起作用。

将字符串转换为密钥的其他选项有哪些?

可能应该补充说明我对密码学完全是新手。


你收到的密钥是如何编码的?是十六进制还是base64?在将该字符串传递给DESKeySpec构造函数之前,您必须将其转换为解码后的字节数组。 - stevevls
key.getBytes() 不就是做这个的吗?我手头的密钥只是一个字符串,我不确定它被处理过什么。我刚刚尝试使用 Base64 进行解码,但它抱怨说有“Base64 编码数据中存在非法字符”。 - kouri
我已经尝试使用UTF8、UTF16、ISO、HEX进行解码,但都无法成功。还有其他的编码方式吗? - kouri
如果您的意思是将这些值指定为字符串的“编码”,则不要这样做。如果数据以十六进制表示,则需要进行实际转换。 - aaron
密钥长度是多少?它包含哪些字符?(仅限0-9和A-F吗?大小写字母都有吗?ASCII值> 127的字符?控制字符(ASCII值<20)? - Rasmus Faber
3个回答

2
太阳操作系统(SunOS)的des手册(似乎是您的des.exe基于此?)指出,密钥生成如下:
DES算法需要一个8字节的密钥,其中低位被认为是奇校验位。用户提供的ASCII密钥将填充为8个字节,并且高位将设置为奇校验位。然后,DES算法忽略每个ASCII字符的低位,但由于奇偶校验,该位的信息已保存在高位中。
它还提到初始向量始终为零,无论您运行的是哪种模式。
CBC模式始终使用全零的初始值作为初始化向量,因此文件的前8个字节在CBC或ECB模式下加密时相同。
它还提到所使用的填充方式是最后一个字节始终是0-7之间的值,表示使用的填充字节数。这类似于PKCS5Padding,因此可能适用。
由于DES的CBC和ECB模式需要加密8字节为一个单位,因此通过des命令加密的文件会附加1到8个字节,使其成为8字节的倍数。当解密时,最后一个字节给出了要保存的最后8个字节中的字节数(0至7)。输入附加的其他字节在加密之前被随机化。
根据您指定使用的选项,听起来您正在使用DES/CBC/PKCS5Padding进行密码编码。
我认为这只剩下确定如何实际派生密钥了。我在exampledepot上找到了这个示例代码,可能适用于您。我认为您只需要将字符串密码转换为8个字节(每个字符1个字节,因此没有UTF编码),然后将其通过示例中的代码以派生密钥。无论如何,值得一试。

如果这只是一个“练习”,那么这将是相当恶意的。从所引用可执行文件的文档中可以看出,加密算法可能是DES或3DES CBC模式。在尝试暴力破解之前,我建议先测试这些密码算法。 - aaron
我尝试了你建议的方法,但是不行。我尝试使用“des -E -k“hello”进行加密/解密,其中“hello”是密钥,但它仍然有效。所以如果它是一个字符,一个字节,那么它会用0填充吗?它肯定会先将其转换为其他东西。@_@ 完全卡住了。我想我必须调用“des.exe”而不是自己解密它。 - kouri
是的,文档上说它用0字节填充密码,使其成为完整的8个字节。如果不这样做,那么密钥将不同,您将无法解密。您还需要确保使用零IV,尽管这可能会自动发生(不确定)。 - senecaso
所以我已经确保我的密钥大小为8个字节,我的iv为0,加密方式为"DES/CBC/PKCS5Padding",但是没有成功。我可能在中间某个地方做错了什么 @_@。我想现在只能先调用"des.exe"了。 :) - kouri

0

我在使用C#时遇到了同样的问题,最终解决了。你可以在这里查看我的答案:C#中的DES初始化向量

通常,des.exe所做的是使用DES计算校验和。因此,每个加密步骤都使用先前的结果而不是在输出数组中前进。


0

DES密钥是7个字节(显然SunJCE使用7个字节?)或者8个字节。请检查您所提供的字符串是否是7个或8个字节。如果是,那么很有可能它就是原始密钥。如果不是,那么它可能以某种方式进行编码。十六进制编码的标志通常是前缀为0x或后缀为h,并且所有字符都在0-9、A-F范围内。您可以自行将其转换为十六进制,也可以使用网络上的一些代码,但我通常使用Apache commons lib(http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Hex.html)。

话虽如此,这只是猜测,我不确定我们是否能断定这仅仅是密钥的问题。您是否有关于所谓的加密算法的其他信息?如果您引用的可执行文件可以使用“-d”,那么似乎加密采用的是普通DES CBC模式:

-b : 使用DES ECB加密模式进行加密,默认是CBC模式

(有多种可能的模式,请参见http://download.oracle.com/javase/1.4.2/docs/guide/security/jce/JCERefGuide.html#AppA

我建议将您的密码设置为“DES/CBC”。

但我不确定如何解释这句话:

默认是三重cbc

您可以使用以下代码片段查看系统上可用的密码列表:http://www.java2s.com/Code/Java/Security/ListAllProviderAndItsAlgorithms.htm


我刚刚使用了des.exe进行了解密和加密,唯一产生相同结果的命令是“-E”和“-D”,只有最后几个字符不同,使用我所拥有的相同密钥。其他命令则产生完全不同的结果。 :( “-d”根本不起作用。你所说的原始密钥是什么意思? - kouri
密钥有8个普通字符,那么如果是普通的UTF8编码,它就是8个字节吗? - kouri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接