Я пытаюсь реализовать функцию, при которой сервер Linux отправляет случайные данные вместе с некоторой информацией о сертификате (например, тема или вопрос) клиенту OSx, а клиент OSx получает сертификат из хранилища цепочки для ключей, фильтрует на основе информации о сертификате, извлекаетзакрытый ключ и подпишите случайные данные с помощью алгоритма SHA256.
Затем клиент отправляет сертификат в кодировке base64 и подписанные данные (в кодировке base64) обратно на сервер.Сервер Linux использует библиотеку OpenSSL (получить открытый ключ из сертификата) для проверки подписанных данных.
Проблема, с которой я сталкиваюсь, заключается в том, что сервер не позволяет проверять подписанные данные, в то время как для клиента Windows Server может проверять подписанные данные.data.
Я использую приведенный ниже API безопасности на macOS (10.13.4)
std::string osxPrivateKey::signData(const uint8_t* pData, uint32_t nDataSize, vector<uint8_t>& aSignature) {
const char* str = (const char*)pData;
unsigned char *result = new unsigned char[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(str, strlen(str), result);
CFDataRef myData = CFDataCreate(NULL, result, CC_SHA256_DIGEST_LENGTH);
CFErrorRef error;
osxObject<SecTransformRef> signer;
SecTransformRef signerRef = SecSignTransformCreate(m_oKey.get(), &error);
signer.set(signerRef);
//SecTransformSetAttribute(signer.get(), kSecTransformDebugAttributeName, kCFBooleanTrue, &error);
SecTransformSetAttribute(signer.get(), kSecTransformInputAttributeName, myData, &error);
//SecTransformSetAttribute(signer.get(), kSecInputIsAttributeName , kSecInputIsPlainText, &error);
SecTransformSetAttribute(signer.get(), kSecInputIsAttributeName , kSecInputIsDigest, &error);
//SecTransformSetAttribute(signer.get(), kSecInputIsAttributeName , kSecInputIsRaw, &error);
SecTransformSetAttribute(signer.get(), kSecPaddingKey, kSecPaddingPKCS1Key, &error);
//SecTransformSetAttribute(signer.get(), kSecPaddingKey, kSecPaddingPKCS5Key, &error);
SecTransformSetAttribute(signer.get(), kSecEncodeLineLengthAttribute, kSecLineLength64, &error);
SecTransformSetAttribute(signer.get(), kSecDigestTypeAttribute, kSecDigestSHA2, NULL);
int digestLength = 256;
CFNumberRef dLen = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &digestLength);
SecTransformSetAttribute(signer.get(), kSecDigestLengthAttribute, dLen, &error);
CFRelease(dLen);
CFDataRef signature = (CFDataRef)SecTransformExecute(signer.get(), &error);
unsigned char* signData = new unsigned char[1024];
int size = CFDataGetLength(signature);
CFDataGetBytes(signature, CFRangeMake(0,CFDataGetLength(signature)), (UInt8*)(signData));
char* encodeBase64SignData = new char[1024];
//internal library to convert binary to base64 encoding
hc::encodeBase64((const char*)signData, size, encodeBase64SignData, 1023);
encodeBase64SignData[1023] = '\0';
delete encodeBase64SignData;
delete signData;
return string(encodeBase64SignData);
}
На сервере для проверки подписи используется следующий код
bool verifySignature(const EVP_PKEY * pkey, const BLOB & data, const BLOB & signature, size_t signatureLen, DSStr & strErr)
{
bool result = false;
EVP_MD_CTX* ctx = NULL;
{// scope
OSSL_CHECK(ctx = EVP_MD_CTX_create());
const EVP_MD* md = NULL;;
OSSL_CHECK(md = EVP_get_digestbyname("SHA256"));
OSSL_CHECK(EVP_DigestInit_ex(ctx, md, NULL) == 1);
OSSL_CHECK(EVP_DigestVerifyInit(ctx, NULL, md, NULL, (EVP_PKEY*)pkey) == 1);
if (EVP_PKEY_id((EVP_PKEY*)pkey) == EVP_PKEY_RSA) {
OSSL_CHECK(EVP_PKEY_CTX_set_rsa_padding(ctx->pctx, RSA_PKCS1_PADDING) == 1);
}
OSSL_CHECK(EVP_DigestVerifyUpdate(ctx, &data[0], data.size()) == 1);
ERR_clear_error();
OSSL_CHECK(EVP_DigestVerifyFinal(ctx, (unsigned char*)&signature[0], signatureLen) == 1);
result = true;
}// scope
OSSL_CHECK_failed:
if (ctx) EVP_MD_CTX_destroy(ctx);
return result;
}
Поскольку я новичок в macOS, я не уверен, что что-то упустил.Я действительно ценю любую помощь, поскольку я блокирую это от недели.