我需要在C中进行一些简单的DES加密,以便与一些旧代码进行交互。根据我的理解,你可以使用“crypt”库,使用函数setkey,encrypt,crypt等等。我一直在搞乱它并且无法正确使用它。缺少setkey / encrypt手册页上的示例。
我希望获得与使用某些java代码相同的输出(见下文)。
所以假设我在C中有两个字符数组。
char *message = "hellothe";
char *key = "iamakey0";
有人可以举例说明如何使用setkey / encrypt对这些进行加密,并获得与java代码相同的结果吗?我意识到你必须将消息和密钥放入一个64字节的数组中,其中每个字符代表一点,但其中一些也令人困惑。显然你必须得到正确的位平价或其他东西吗?
public static byte[] encryptDES(byte[] message, byte[] key) {
byte[] encrypted = new byte[0];
try{
Cipher c = Cipher.getInstance("DES");
c.init(Cipher.ENCRYPT_MODE,new SecretKeySpec(key,"DES"));
encrypted = c.doFinal(message);
}
catch (Exception e) {
e.printStackTrace();
}
return encrypted;
}
答案 0 :(得分:2)
因为您只使用字符串Cipher.getInstance
调用"DES"
,所以您没有指定密码模式或填充方法。这意味着您将获得默认值,这取决于您正在使用的Java加密提供程序 - 您需要确切地知道它们是什么来编写兼容的C.(您确实应该指定它们而不是依赖于默认值。)
如果您使用的是SunJCE提供程序,则DES的默认值为ECB模式和PKCS#5填充。执行此操作的最佳方法可能是使用OpenSSL或其他多脏的加密库 - 但如果要使用通常在UNIX类型平台上的标准C库中找到的函数,ecb_crypt
函数系列将会运行比setkey
/ encrypt
家庭更容易使用。
加密时需要添加PKCS#5填充,并在解密时检查(并丢弃)。以下ecb_pkcs5_encrypt
函数应使用这些函数粗略地等效上述Java代码。
/* Returns a newly-allocated buffer containing the contents of `data',
* padded out to a multiple of 8 bytes using PKCS #5 style padding.
*
* If `padded_len` is non-NULL, the value it points to is updated to
* the size of the padded output data.
*
* Returns NULL on error.
*/
char *pad_pkcs5(const char *data, size_t data_len, size_t *padded_len)
{
char *padded_data;
unsigned padding_len = 8 - (data_len % 8);
const char padding = padding_len;
char *pad_ptr;
/* check for length overflow */
if (data_len + padding_len < data_len)
return NULL;
/* Copy data into a new buffer and pad it out */
padded_data = malloc(data_len + padding_len);
if (!padded_data)
return NULL;
memcpy(padded_data, data, data_len);
if (*padded_len)
{
*padded_len = data_len + padding_len;
}
/* Add the padding bytes */
pad_ptr = padded_data + data_len;
while (padding_len--)
{
*pad_ptr++ = padding;
}
return padded_data;
}
/* Returns a newly-allocated buffer containing the contents of `data',
* encrypted with `key' using DES/ECB/PKCS5.
*
* If `out_len` is non-NULL, the value it points to is updated to
* the size of the encrypted output data (which will always be a
* multiple of 8).
*
* Returns NULL on error.
*/
char *ecb_pkcs5_encrypt(const char *key, const char *data, size_t data_len, size_t *out_len)
{
char des_key[8];
char *padded_data;
size_t padded_len;
int status;
/* One of the few cases where strncpy() is exactly what we want! */
strncpy(des_key, key, sizeof des_key);
des_setparity(des_key);
padded_data = pad_pkcs5(data, data_len, &padded_len);
if (!padded_data)
return NULL;
status = ecb_crypt(des_key, padded_data, padded_len, DES_ENCRYPT);
if (DES_FAILED(status))
return NULL;
if (out_len)
*out_len = padded_len;
return padded_data;
}
答案 1 :(得分:1)
不要使用crypt()。它使用一些非标准算法,因此很难与其他系统进行互操作。此外,DES无论如何都不安全。
我建议你在C中使用OpenSSL。它的大多数密码都与JCE兼容。
如果你真的必须使用crypt,那么Sun的JRE附带了一个处理crypt的类,
com.sun.security.auth.module.Crypt
这是内部类,所以文档不存在。只需阅读源代码。