代码之家  ›  专栏  ›  技术社区  ›  Sardeep Lakhera

使用安全变换生成RSA签名并使用OpenSSL/C++进行验证

  •  3
  • Sardeep Lakhera  · 技术社区  · 8 年前

    然后,客户机将base64编码的证书和签名数据(base64编码)发送回服务器。Linux服务器使用OpenSSL库(从证书中获取公钥)来验证签名的数据。

    我面临的问题是服务器无法验证签名数据,而对于windows客户机,服务器可以验证签名数据。

    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的新手,我不确定我是否遗漏了什么。我真的很感谢任何帮助,因为我从一个星期阻止了这个。

    1 回复  |  直到 8 年前
        1
  •  0
  •   bartonjs    8 年前

    您接受了一个名为 pHash ,然后将其分解为 result

    此外,您使用 strlen(pHash) 作为长度,完全忽略 nHashSize

    因为你的函数被命名为 signHash 参数名为

    CFDataRef myData = CFDataCreate(NULL, pHash, nHashSize);