我有一个56位二进制字符串,我想用它作为DES加密的密钥。
我在JCA docs网站上找到了以下代码
byte[] desKeyData = { (byte)0x01, (byte)0x02, (byte)0x03,
(byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08 };
DESKeySpec desKeySpec = new DESKeySpec(desKeyData);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
然而,这使用8个字节作为密钥(而不是7个字节)。不清楚desKeyData [0]是对应于最低有效字节还是最高有效字节。另外,是否可以直接使用56位字符串来生成可用于此目的的字节数组?
答案 0 :(得分:7)
来自Wikipedia:
密钥表面上由64位组成;然而,算法实际上只使用了其中的56个。 8位仅用于检查奇偶校验,然后被丢弃。因此,有效密钥长度为56位,并且从未如此引用。所选密钥的每第8位被丢弃,即从64位密钥中移除位置8,16,24,32,40,48,56,64,仅留下56位密钥。
因此,最低有效位(即第0位)不用于密钥构造,它们可用于DESKeySpec.isParityAdjusted()
检查奇偶校验。
编辑:简单测试显示忽略最低有效位:
SecretKeyFactory sf = SecretKeyFactory.getInstance("DES");
byte[] in = "test".getBytes("UTF-8");
Cipher c1 = Cipher.getInstance("DES");
c1.init(Cipher.ENCRYPT_MODE, sf.generateSecret(new DESKeySpec(
new byte[] {0x10,0x20,0x30,0x40,0x50,0x60,0x70,(byte) 0x80})));
byte[] r1 = c1.doFinal(in);
Cipher c2 = Cipher.getInstance("DES");
c2.init(Cipher.ENCRYPT_MODE, sf.generateSecret(new DESKeySpec(
new byte[] {0x11,0x21,0x31,0x41,0x51,0x61,0x71,(byte) 0x81})));
byte[] r2 = c2.doFinal(in);
assertArrayEquals(r1, r2);
答案 1 :(得分:1)
重要一点是改变one或two's complement号码的符号。最高或最低有效位的想法不能应用于字节。
正如axtavt的回答所说,从序列的所有64位中,只有范围:(1..7), (9..15), (17..23), (25..31), (33..39), (41..47), (49..55), (57..63)
中的位被用作实际的密钥。例如,序列上的56个相关位变为1:0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f
,将最高有效位保留为零作为奇偶校验。
要将7字节,56位序列实际转换为8字节序列,您可以使用this code。