Nano Hash - криптовалюты, майнинг, программирование

Как использовать PKCS5_PBKDF2_HMAC_SHA1()

Я пытаюсь использовать PKCS5_PBKDF2_HMAC_SHA1(), и ниже приведен пример моей программы. Я хотел убедиться, что мой результат PKCS5_PBKDF2_HMAC_SHA1() верен, поэтому я проверил то же самое на веб-сайте http://anandam.name/pbkdf2/ и я вижу другой результат. Правильно ли я использую API?

У меня есть сомнения, правильно ли я передаю значение соли.

Я вставил свой результат и результат веб-сайта после программы.

Пожалуйста, помогите мне понять это.

#include <stdio.h>     
#include <types.h> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 

#include <malloc.h> 

#include <openssl/hmac.h> 
#include <openssl/evp.h> 
#include <openssl/engine.h> 
#include <openssl/aes.h>
#include <openssl/rand.h> 

#include <proto.h> 
#define KEY_LEN    32// 32 bytes - 256 bits 
#define KEK_KEY_LEN   5 
#define ITERATION   1000 

unsigned char salt_value[KEY_LEN]; 
unsigned char AESkey[KEY_LEN]; 
unsigned char XTSkey[KEY_LEN]; 
u8 fuse_key[KEY_LEN]; 

void main() 
{ 
    s32 i=0; 
    s32 len =0; 
    u8 *out; 
    u8 *rspHMAC; 
    const s8 pwd[] = "test"; 
    s8 rspPKCS5[KEK_KEY_LEN * 2]; 
    s32 ret; 

    rspHMAC = (unsigned char *) malloc(sizeof(char) * KEY_LEN); 
    out = (unsigned char *) malloc(sizeof(char) * KEK_KEY_LEN); 

    RAND_bytes(salt_value, KEY_LEN); 

    printf("\n salt_value[0] = %x; salt_value[31]= %x", salt_value[0], salt_value[31]); 
    printf("\n strlen(salt_value) = %d; sizeof(salt_value) = %d\n", strlen(salt_value), sizeof(salt_value));  

    for(i = 0; i < KEY_LEN; i++) { 
        printf("%02x", salt_value[i]); 
    } 

    ret = PKCS5_PBKDF2_HMAC_SHA1(pwd, strlen(pwd), salt_value, strlen(salt_value), ITERATION, KEK_KEY_LEN, out); 
    printf("\n PKCS#5 :"); 

    for(len = 0; len < KEK_KEY_LEN; len++){ 
        printf("%02x", out[len]);

        sprintf(&rspPKCS5[len * 2], "%02x", out[len]); 
    } 

    printf("\n"); 
} 

Пример вывода:

salt_value[0] = e2; salt_value[31]= 12 
strlen(salt_value) = 32; sizeof(salt_value) = 32 
e258017933f3e629a4166cece78f3162a3b0b7edb2e94c93d76fe6c38198ea12 
PKCS#5 :7d7ec9f411 

Результат сайта:

The derived 40-bit key is: a5caf6a0d3 
19.03.2012

  • В связи с этим теперь есть справочная страница для PKCS5_PBKDF2_HMAC и PKCS5_PBKDF2_HMAC_SHA1. См. PKCS5_PBKDF2_HMAC (3). 13.04.2015

Ответы:


1

Во-первых, давайте посмотрим на официальный тестовый вектор для PBKDF2. HMAC-SHA1:

Input:
   P = "password" (8 octets)
   S = "salt" (4 octets)
   c = 1
   dkLen = 20

 Output:
   DK = 0c 60 c8 0f 96 1f 0e 71
        f3 a9 b5 24 af 60 12 06
        2f e0 37 a6             (20 octets)

Так что теперь мы знаем, что мы снимаем как в Интернете, так и в вашей программе. Таким образом, используя эту информацию, мы узнаем, что веб-сайт хочет, чтобы ваша соль была представлена ​​в виде строки ASCII, которую он затем преобразует в байты. Это важно, потому что вы никогда не сможете сопоставить вывод веб-страницы, если используете RAND_bytes для создания соли.

password
salt
1
20
0c60c80f961f0e71f3a9b524af6012062fe037a6

И вы используете соль неправильно. В вашей строке комментариев вы создаете строку с символами ASCII. Если вы хотите использовать эту соль, вам придется объявить ее как массив байтов. К тому же у вас пропущена цифра.

unsigned char salt_value[]= { 0x5d, 0x85, 0x94, 0x7b, … /* and so on */ };

А в раскомментированном коде вы генерируете массив байтов, но обрабатываете его как строку. Вы не вызываете strlen для массива байтов, потому что массивы байтов могут содержать 0, который strlen будет интерпретировать как нулевой терминатор. Таким образом, вы либо отслеживаете размер вручную (например, ваш KEK_KEY_LEN определяет для массива, который вы malloc), либо используете sizeof, когда это уместно.

PKCS5_PBKDF2_HMAC_SHA1(pwd, strlen(pwd), salt_value, sizeof(salt_value), ITERATION, KEK_KEY_LEN, out);

Итак, теперь, когда мы знаем все эти вещи, мы можем собрать полную программу, которая соответствует выходным данным как веб-сайта, так и официального тестового вектора.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <openssl/evp.h>

#define KEY_LEN      32
#define KEK_KEY_LEN  20
#define ITERATION     1 

int main()
{
    size_t i;
    unsigned char *out;
    const char pwd[] = "password";
    unsigned char salt_value[] = {'s','a','l','t'};

    out = (unsigned char *) malloc(sizeof(unsigned char) * KEK_KEY_LEN);

    printf("pass: %s\n", pwd);
    printf("ITERATION: %u\n", ITERATION);
    printf("salt: "); for(i=0;i<sizeof(salt_value);i++) { printf("%02x", salt_value[i]); } printf("\n");

    if( PKCS5_PBKDF2_HMAC_SHA1(pwd, strlen(pwd), salt_value, sizeof(salt_value), ITERATION, KEK_KEY_LEN, out) != 0 )
    {
        printf("out: "); for(i=0;i<KEK_KEY_LEN;i++) { printf("%02x", out[i]); } printf("\n");
    }
    else
    {
        fprintf(stderr, "PKCS5_PBKDF2_HMAC_SHA1 failed\n");
    }

    free(out);

    return 0;
}

(и обратите внимание, что main должен вернуть int, и вы должны освободить выделенную память)

gcc pkcs5.c -o pkcs5 -g -lcrypto -Wall
./pkcs5
pass: password
ITERATION: 1
salt: 73616c74
out: 0c60c80f961f0e71f3a9b524af6012062fe037a6
20.03.2012
  • Спасибо инди за ответ. Когда я генерирую соль, используя RAND_bytes(), конвертирую ее в ASCII, я могу сопоставить результат (как это делает моя программа), но я смотрю на использование двоичных значений для PKCS5_PBKDF2_HMAC_SHA1(). Есть ли способ проверить, совпадает ли результат, сгенерированный с использованием двоичного кода, с выводом программы? 20.03.2012
  • В документе, на который я ссылаюсь, есть тестовый вектор, который выявляет ошибки в двоичной реализации с помощью пароля pass\0word и соли sa\0lt. \0 представляет байт 0x00. Если ваша реализация может пройти все тестовые примеры тестового вектора, то она считается функционально правильной. 20.03.2012
  • Спасибо за ответ, @indiv. Ваше решение сработало для меня, но мне пришлось использовать strlen(salt_value) вместо sizeof(salt_value) при вызове PKCS5_PBKDF2_HMAC_SHA1(). 07.06.2017
  • @MaxMarchuk: я не знаю, почему это так (но я предполагаю, что вы используете sizeof для указателя вместо массива), но будьте осторожны с strlen. strlen останавливает сканирование на первом байте 0x00. Если вы используете двоичную (нетекстовую) соль, любые байты со значением 0 сломают ее. Например, для этой соли unsigned char salt_value[] = {0x00, 0x01, 0x02}; вы получите strlen 0, что неверно. Если вы используете только текстовые (ASCII) строки для соли, все должно быть в порядке. 07.06.2017
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..