c++ - 为什么我的 OpenSSL/libcrypto 签名不正确?

标签 c++ openssl cryptography libcrypto

我需要签署一个字符串,将公钥作为字符串发布,然后在其他地方使用公钥来验证签名的消息。这是消息签名的部分:

        // RSA keypair generation
        EVP_PKEY *keypair = NULL;
        EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
        if (1 != EVP_PKEY_keygen_init(ctx)) {
            initFail = true;
        }
        if (1 != EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048)) {
            initFail = true;
        }
        if (1 != EVP_PKEY_keygen(ctx, &keypair)) {
            initFail = true;
        }
        EVP_PKEY_CTX_free(ctx);


        // Create public key string.
        BIO* bo = BIO_new(BIO_s_mem());
        PEM_write_bio_PUBKEY(bo, keypair);
        char buff[1000];
        BIO_read(bo, &buff[0], 1000);
        BIO_free(bo);
        pubkey = buff;


        // Create signature
        size_t *slen = new size_t;
        unsigned char *sig = NULL;
        std::string msg;
        msg = stuffThatCreatesMessage();
        EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
        if (1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), 
                    NULL, keypair)) {
            initFail = true;
        }
        if (1 != EVP_DigestSignUpdate(mdctx, msg.c_str(), msg.length())) {
            initFail = true;
        }
        if (1 != EVP_DigestSignFinal(mdctx, NULL, slen)) {
            initFail = true;
        }
        sig = (unsigned char *) OPENSSL_malloc(
                sizeof(unsigned char) * (*slen));
        if (1 != EVP_DigestSignFinal(mdctx, sig, slen)) {
            initFail = true;
        }
        signature = *sig;
        OPENSSL_free(sig);

        bool isSuccess = verifySignature(signature, pubkey, msg);

这是获取字符串消息和 key 并实际验证签名的代码:

bool verifySignature(std::string sig, std::string key_str, std::string msg) {
    BIO* bo = BIO_new(BIO_s_mem());
    BIO_write(bo, key_str.c_str(), key_str.length());
    EVP_PKEY *key = EVP_PKEY_new();
    PEM_read_bio_PUBKEY(bo, &key, 0, 0);
    BIO_free(bo);

    unsigned char *unsigned_sig = new unsigned char[sig.length()+1];
    strcpy((char *) unsigned_sig, sig.c_str());
    EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
    if (1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, key))    {  
        return false;
    }
    if (1 != EVP_DigestVerifyUpdate(mdctx, msg.c_str(), msg.length())) {
        return false;
    }
    bool retval = (1 == EVP_DigestVerifyFinal(mdctx, unsigned_sig, 
                sig.length()));
    delete unsigned_sig;
    return retval;
}

每次我这样做时,后一个函数都会告诉我签名无效,isSuccess 变量等于 0。这是因为 EVP_DigestSignFinal 返回 0,表示签名不正确。我哪里错了?

最佳答案

@jww 指出的问题是行 signature = *sig。我最终只有第一个字节作为我的签名字符串。正确的做法是:

std::string temp_sig = reinterpret_cast<char*>(sig);
signature = temp_sig.substr(0, *slen);

关于c++ - 为什么我的 OpenSSL/libcrypto 签名不正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44081897/

相关文章:

ios - IBM Worklight 6.0 - 段错误

c++ - Z3 C++ API : set parameter for tactic

c++ - 从模板类赋值运算符访问私有(private)成员变量

c++ - 在没有 move 构造函数或 move 赋值的情况下调用 std::move

ssl - 带有 CA :TRUE and Key Usage not set to sign certificates - is it safe? 的自签名证书

ruby - 加密空字符串

java - AES-256 可以在 API 级别 26+ 的 Android 设备上工作吗?

javascript - 无法解密 openSSL AES CTR 加密文本

.net - 有哪些工具可用于生成 key 对、注册 SCEP、用于 .Net 上的 TLS 服务器?

c++ - 学习多线程。试图做一个质数查找器