Как вы используете библиотеку crypt в C для шифрования DES? (setkey, encrypt, crypt и т. д.) - PullRequest
0 голосов
/ 14 сентября 2009

Мне нужно сделать простое шифрование DES на C, чтобы взаимодействовать со старым кодом. Из того, что я понимаю, вы можете использовать для этого библиотеку «crypt» с функциями setkey, encrypt, crypt и т.д. Пример на странице man для 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 ]

2 голосов
/ 14 сентября 2009

Поскольку вы вызываете Cipher.getInstance только со строкой "DES", вы не указываете режим шифрования или метод заполнения. Это означает, что вы получаете значения по умолчанию, которые зависят от того, какого провайдера криптографии Java вы используете - вам нужно точно знать, для чего они пишут совместимый C. (Вы действительно должны указывать их, а не полагаться на значения по умолчанию).

Если вы используете провайдера SunJCE, то по умолчанию для DES используются режим ECB и заполнение PKCS # 5. Лучшим способом сделать это, вероятно, является использование OpenSSL или другой мясной криптографической библиотеки - но если вы хотите использовать функции, которые обычно находятся в стандартной библиотеке C на платформах типа UNIX, семейство функций 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 голос
/ 14 сентября 2009

Не используйте crypt (). Он использует некоторый нестандартный алгоритм, поэтому будет очень сложно взаимодействовать с другими системами. Кроме того, DES в любом случае не является безопасным.

Я предлагаю вам использовать OpenSSL в C. Большинство его шифров совместимы с JCE.

Если вам действительно нужно использовать crypt, Sun JRE поставляется с классом для работы с crypt,

   com.sun.security.auth.module.Crypt

Это внутренний класс, поэтому документации там нет. Просто прочитайте исходный код.

...