Я использую функцию RSA_verify() для проверки SHA, который я подписал с помощью программы openssl (через консоль). RSA_verify() всегда возвращает неудачную проверку, поэтому я думаю, что отправляю ему неверные параметры.
Следующие консольные команды выполняются в Linux Ubuntu с OpenSSL 0.9.8k.
Насколько я помню, функции C скомпилированы для Android с использованием OpenSSL 1.0.1...c. Это определенно 1.0.1 (мы обновляем его, чтобы избежать проблемы с Heartbleed).
Это то, что я делаю ... пожалуйста, простите любую ошибку, поскольку я учусь этому сам.
Сгенерировать закрытый ключ
openssl genrsa -out private.key 2048
Извлечь открытый ключ из закрытого ключа
openssl rsa -in private.key -out public.key -outform PEM -pubout
Рассчитайте SHA из файла с именем разрешения, а затем подпишите его с помощью private.key, на выходе будет SHA, но с шифрованием RSA (permissions.sign)
openssl dgst -sha256 -sign private.key -out permissions.sign permissions
Проверить полученную подпись SHA на соответствие файлу разрешений (успешно в консоли Ubuntu)
openssl dgst -sha256 -verify public.key -signature permissions.sign permissions
Я копирую файл разрешений, файл permissions.sign и файл public.key в файловую систему Android.
Я проверяю, что permissions.sign был создан с разрешениями и с соответствующим private.key... все это с моим public.key (у меня нет закрытого ключа в Android).
Это функция С.
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
...
/* Initialize the public key */
RSA *pub_key = RSA_new();
if(NULL == pub_key)
{
ANDROID_LOGE("RSA_new failed");
result = 0;
}
else
{
FILE* fp = fopen(public_key, "r");
if(NULL == fp)
{
ANDROID_LOGE_P("fopen [%s] failed", public_key);
result = 0;
}
else
{
/* Read it from the passed path */
if(PEM_read_RSA_PUBKEY(fp, &pub_key, NULL, NULL) == NULL)
{
ANDROID_LOGE_P("[%s] can't be read", public_key);
result = 0;
fclose(fp);
}
else
{
/* Verify the file and its SHA with the public key */
int verified = RSA_verify(
NID_sha256,
file, /* message digest (message to validate) */
file_size, /* message size */
sign, /* signature (signed SHA) */
sign_size, /* signature size */
pub_key);
ANDROID_LOGD("NID_sha256");
if(verified)
{
result = 1;
ANDROID_LOGD_P("[%s] is valid", file_to_verify);
}
else
{
ANDROID_LOGE_P("[%s] is NOT valid", file_to_verify);
}
fclose(fp);
}
RSA_free(pub_key);
}
}
- public_key — это путь к public.key
- PEM_read_RSA_PUBKEY завершается успешно
- NID_sha256 - это то, что я думаю, я должен использовать для проверки
- файл представляет собой массив байтов с содержимым разрешений
- file_size - размер массива файла
- sign — массив байтов с содержимым разрешения.sign
- sign_size — размер массива знаков
- RSA_verify() не работает, возвращает 0
Отсюда вопрос, правильно ли:
сгенерировать ключи с помощью команд, которые я использовал,
подпишите файл разрешений (который генерирует разрешения.sign),
а затем попытаться проверить файлы с помощью PEM_read_RSA_PUBKEY() и RSA_verify()?
Эквивалентны ли команды, которые я использовал для процесса подписи, функциям C, которые я использовал для процесса проверки?
Пожалуйста, дайте мне знать, если требуется дополнительная информация или где я могу узнать больше об этом.
Спасибо!
РЕДАКТИРОВАТЬ: я добавил печать ошибок после вызова RSA_Verify():
ANDROID_LOGE_P("openssl: %s", ERR_reason_error_string(ERR_get_error()));
Он печатает:
openssl: плохая подпись
Все еще исследую.
EVP_DigestSign*
иEVP_DigestVerify*
. См. Подписание и проверка EVP. Вики также предоставляет код, который вы можете скопировать/вставить, чтобы сделать это. - person jww   schedule 12.04.2015