Написание функции Hmac в Vala - PullRequest
1 голос
/ 13 марта 2012

Я пишу кроссплатформенное приложение на Vala для Windows и Linux. Мне нужно реализовать Hmac для безопасности; но, к сожалению, класс GHmac ( ссылка ) еще не был перенесен в windows. Я нашел алгоритм для Hmac в Википедии ( ссылка ) и считаю, что реализовал его правильно, но по сравнению со встроенным классом я не получаю тот же результат. Вот моя функция ниже, если кто-нибудь может помочь мне найти баг (ы), которые были бы удивительны.

public static string compute_for_data(ChecksumType type, uint8[] key,
                                                            uint8[] data) {
    int block_size = 64;
    uint8[] mod_key = key;
    uint8[] outer = new uint8[block_size];
    uint8[] inner = new uint8[block_size];

    if (mod_key.length > block_size) {
        mod_key = Checksum.compute_for_data(type, key).data;
    }
    mod_key.resize(block_size);

    for (int i=0; i < mod_key.length; i++) {
        outer[i] = mod_key[i] ^ 0x5c;
        inner[i] = mod_key[i] ^ 0x36;
    }

    int i = inner.length;
    inner.resize(i + data.length);
    for (int j=0; j < data.length; j++) {
        inner[i + j] = data[j];
    }

    inner = Checksum.compute_for_data(type, inner).data;

    i = outer.length;
    outer.resize(i + inner.length);
    for (int j=0; j < inner.length; j++) {
        outer[i + j] = inner[j];
    }

    return Checksum.compute_for_data(type, outer);
}

1 Ответ

2 голосов
/ 15 марта 2012

Я знаю, как глупо отвечать на свой вопрос, но мне удалось разгадать его с помощью друга, так что вот решение. В основном, когда я использовал функцию Checksum.compute_for_data, она возвращала шестнадцатеричную строку, а не шестнадцатеричные данные, и это нарушало алгоритм. Вот исправленная версия:

public static string compute_for_data(ChecksumType type, uint8[] key,
                                                            uint8[] data) {
    int block_size = 64;
    switch (type) {
        case ChecksumType.MD5:
        case ChecksumType.SHA1:
            block_size = 64; /* RFC 2104 */
            break;
        case ChecksumType.SHA256:
            block_size = 64; /* RFC draft-kelly-ipsec-ciph-sha2-01 */
            break;
    }

    uint8[] buffer = key;
    if (key.length > block_size) {
        buffer = Checksum.compute_for_data(type, key).data;
    }
    buffer.resize(block_size);

    Checksum inner = new Checksum(type);
    Checksum outer = new Checksum(type);

    uint8[] padding = new uint8[block_size];
    for (int i=0; i < block_size; i++) {
        padding[i] = 0x36 ^ buffer[i];
    }
    inner.update(padding, padding.length);
    for (int i=0; i < block_size; i++) {
        padding[i] = 0x5c ^ buffer[i];
    }
    outer.update(padding, padding.length);

    size_t length = buffer.length;
    inner.update(data, data.length);
    inner.get_digest(buffer, ref length);

    outer.update(buffer, length);
    return outer.get_string();
}
...