如何在C中使用crypt库来进行DES加密? (setkey,encrypt,crypt等)

我需要在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; } 

因为您只使用字符串"DES"调用Cipher.getInstance ,所以您没有指定密码模式或填充方法。 这意味着您将获得默认值,这取决于您正在使用的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; } 

不要使用crypt()。 它使用一些非标准算法,因此很难与其他系统进行互操作。 此外,DES无论如何都不安全。

我建议你在C中使用OpenSSL。它的大多数密码都与JCE兼容。

如果你真的必须使用crypt,Sun的JRE附带了一个处理crypt的类,

  com.sun.security.auth.module.Crypt 

这是内部类,所以文档不存在。 只需阅读源代码即可。