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

时间:2009-09-13 21:11:39

标签: java c encryption des

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

2 个答案:

答案 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

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