Стоит задача подписать строку приватным ключем на PHP и проверить подпись публичным ключем на C++. openssl сгенерил пару ключей. подписываю строку на PHP
<?php
$filename = "my_priv.key";
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);
$pkeyid = openssl_pkey_get_private($contents);
openssl_sign("my test line", $signature, $pkeyid, OPENSSL_ALGO_SHA256);
openssl_free_key($pkeyid);
echo base64_encode($signature);
?>
Получаю сигнатуру. Пытаюсь делать проверку на С++. Сам класс:
#include "Sign.h"
RSA* Sign::createPrivateRSA(std::string key) {
RSA *rsa = NULL;
const char* c_string = key.c_str();
BIO * keybio = BIO_new_mem_buf((void*)c_string, -1);
if (keybio == NULL) {
return 0;
}
rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);
return rsa;
}
RSA* Sign::createPublicRSA(std::string key) {
RSA *rsa = NULL;
BIO *keybio;
const char* c_string = key.c_str();
keybio = BIO_new_mem_buf((void*)c_string, -1);
if (keybio == NULL) {
return 0;
}
rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
return rsa;
}
bool Sign::RSASign(RSA* rsa,
const unsigned char* Msg,
size_t MsgLen,
unsigned char** EncMsg,
size_t* MsgLenEnc) {
EVP_MD_CTX* m_RSASignCtx = EVP_MD_CTX_create();
EVP_PKEY* priKey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(priKey, rsa);
if (EVP_DigestSignInit(m_RSASignCtx, NULL, EVP_sha256(), NULL, priKey) <= 0) {
return false;
}
if (EVP_DigestSignUpdate(m_RSASignCtx, Msg, MsgLen) <= 0) {
return false;
}
if (EVP_DigestSignFinal(m_RSASignCtx, NULL, MsgLenEnc) <= 0) {
return false;
}
*EncMsg = (unsigned char*)malloc(*MsgLenEnc);
if (EVP_DigestSignFinal(m_RSASignCtx, *EncMsg, MsgLenEnc) <= 0) {
return false;
}
EVP_MD_CTX_cleanup(m_RSASignCtx);
return true;
}
bool Sign::RSAVerifySignature(RSA* rsa,
unsigned char* MsgHash,
size_t MsgHashLen,
const char* Msg,
size_t MsgLen,
bool* Authentic) {
*Authentic = false;
EVP_PKEY* pubKey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(pubKey, rsa);
EVP_MD_CTX* m_RSAVerifyCtx = EVP_MD_CTX_create();
if (EVP_DigestVerifyInit(m_RSAVerifyCtx, NULL, EVP_sha256(), NULL, pubKey) <= 0) {
return false;
}
if (EVP_DigestVerifyUpdate(m_RSAVerifyCtx, Msg, MsgLen) <= 0) {
return false;
}
int AuthStatus = EVP_DigestVerifyFinal(m_RSAVerifyCtx, MsgHash, MsgHashLen);
if (AuthStatus == 1) {
*Authentic = true;
EVP_MD_CTX_cleanup(m_RSAVerifyCtx);
return true;
}
else if (AuthStatus == 0) {
*Authentic = false;
EVP_MD_CTX_cleanup(m_RSAVerifyCtx);
return true;
}
else {
*Authentic = false;
EVP_MD_CTX_cleanup(m_RSAVerifyCtx);
return false;
}
}
void Sign::Base64Encode(const unsigned char* buffer,
size_t length,
char** base64Text) {
BIO *bio, *b64;
BUF_MEM *bufferPtr;
b64 = BIO_new(BIO_f_base64());
bio = BIO_new(BIO_s_mem());
bio = BIO_push(b64, bio);
BIO_write(bio, buffer, length);
BIO_flush(bio);
BIO_get_mem_ptr(bio, &bufferPtr);
BIO_set_close(bio, BIO_NOCLOSE);
BIO_free_all(bio);
*base64Text = (*bufferPtr).data;
}
size_t Sign::calcDecodeLength(const char* b64input) {
size_t len = strlen(b64input), padding = 0;
if (b64input[len - 1] == '=' && b64input[len - 2] == '=') //last two chars are =
padding = 2;
else if (b64input[len - 1] == '=') //last char is =
padding = 1;
return (len * 3) / 4 - padding;
}
void Sign::Base64Decode(const char* b64message, unsigned char** buffer, size_t* length) {
BIO *bio, *b64;
int decodeLen = calcDecodeLength(b64message);
*buffer = (unsigned char*)malloc(decodeLen + 1);
(*buffer)[decodeLen] = '\0';
bio = BIO_new_mem_buf(b64message, -1);
b64 = BIO_new(BIO_f_base64());
bio = BIO_push(b64, bio);
*length = BIO_read(bio, *buffer, strlen(b64message));
BIO_free_all(bio);
}
char* Sign::signMessage(std::string TermId, std::string plainText) {
std::string privateKey;
bool read_res = FUNC.ReadFile(std::string(GlobalSett.GetSetConfig("KEYS_path")) + "/public/" + TermId + ".key", privateKey, false, "\n");
std::cout << privateKey << std::endl;
if (read_res == true) {
RSA* privateRSA = createPrivateRSA(privateKey);
unsigned char* encMessage;
char* base64Text;
size_t encMessageLength;
RSASign(privateRSA, (unsigned char*)plainText.c_str(), plainText.length(), &encMessage, &encMessageLength);
Base64Encode(encMessage, encMessageLength, &base64Text);
free(encMessage);
return base64Text;
}
else
{
return "";
}
}
bool Sign::verifySignature(std::string TermId, std::string plainText, char* signatureBase64) {
std::string publicKey;
bool read_res = FUNC.ReadFile(std::string(GlobalSett.GetSetConfig("KEYS_path"))+"/public/"+ TermId+".key", publicKey, false, "\n");
if (read_res == true) {
RSA* publicRSA = createPublicRSA(publicKey);
unsigned char* encMessage;
size_t encMessageLength;
bool authentic;
Base64Decode(signatureBase64, &encMessage, &encMessageLength);
bool result = RSAVerifySignature(publicRSA, encMessage, encMessageLength, plainText.c_str(), plainText.length(), &authentic);
return result & authentic;
}
else
{
return false;
}
}
И далее проверка:
bool authentic = Sign.verifySignature(root.get("terminal_id", 0).asString(), plainText, signature);
if (authentic) {
std::cout << "ok" << std::endl;
}
else {
std::cout << "err" << std::endl;
}
Если я просто читаю файл ключа, сгенерированого openssl, как есть то получаю ошибку Segmentation fault на строку
int AuthStatus = EVP_DigestVerifyFinal(m_RSAVerifyCtx, MsgHash, MsgHashLen);
Если же при чтении добавлять в конце каждой строки \n то ключ вгружается нормально, но верификация не проходит.
При подписи- проверки PHP - PHP или C++ - C++, все нормально. Думаю, что я как то не так вгружаю файл ключа.
В чем может быть проблема?
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
как такой массив Insert в mysql ? Задача такова, что мне нужно данные пропарсить в БД, а как это сделать не соображаю, так как с такой задачей не сталкивался
Как правильно наследовать сущность от другой сущности? У меня есть абстрактная сущность AbstractPerson в которой есть определенные свойства, есть...
Вообщем народ есть такая задача, нужно подсчитать количество уникальных активных посетителей на сайте в данный момент, уникальность определяется...