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

StackOverflow https://stackoverflow.com/questions/1418846

  •  07-07-2019
  •  | 
  •  

Вопрос

Мне нужно сделать простое шифрование DES на C для взаимодействия со старым кодом. Из того, что я понимаю, вы можете использовать " 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;
}
Это было полезно?

Решение

Поскольку вы вызываете 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;
}

Другие советы

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

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

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

   com.sun.security.auth.module.Crypt

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top