【问题标题】:How to verify digest using openssl library?如何使用 openssl 库验证摘要?
【发布时间】:2015-11-04 15:22:45
【问题描述】:

我正在通过以下方式构建许可系统。我生成了一个匹配的公钥和私钥:

openssl genrsa -out mykey.pem 1024
openssl rsa -in mykey.pem -des3 -out prv-key.pem
openssl rsa -in mykey.pem -pubout -out pub-key.pem

现在我收到了一条许可证消息,其中包含有关用户和许可证详细信息的唯一信息。我的产品会读取此消息,验证信息,如果一切按计划进行,它会读取许可策略并相应地运行。

所以我已经获取了该许可证文件并使用我的私钥签名消化它

openssl dgst -sha256 -sign prv-key.pem -out license.secret license

现在我将许可证和签名的许可证文件都发送给客户。

我的问题是:如何在 C 程序中使用客户端的公钥 (pub-key.pem) 验证摘要。 我正在寻找 libssl 和 openssl 库,但找不到摘要验证的好例子

【问题讨论】:

  • 命令openssl dgst -sha256 -signature license.secret -verify pub-key.pem license 会做你想要的。查看apps/dgst.c 中的openssl 源代码以在您自己的代码中重新创建它,特别是查找EVP_Digest 调用。但是,您还需要验证公钥 (pub-key.pem) 是真实的(有人可能篡改了它),这并不容易。见Public key certificate
  • 我可以将公钥作为数组存储在我的 C 程序中吗?
  • 是的,你可以。这将使修改它变得更加困难,但并非不可能。

标签: c openssl key sha256 digest


【解决方案1】:

您将需要使用libopenssl-dev 或 Windows 等效程序来构建类似于此的 C 程序:

#include <stdio.h>
#include <stdlib.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>

// Buffer for file read operations. The buffer must be able to accomodate
// the RSA signature in whole (e.g. 4096-bit RSA key produces 512 byte signature)
#define BUFFER_SIZE 512
static unsigned char buffer[BUFFER_SIZE];

int main(int argc, char *argv[])
{
    if(argc != 4)
    {
        fprintf(stderr, "Usage: %s datafile signature_file public_key\n", argv[0]);
        return -1;
    }
    const char* filename = argv[1];
    const char* sigfile = argv[2];
    const char* pubkeyfile = argv[3];

    unsigned bytes = 0;

    // Calculate SHA256 digest for datafile
    FILE* datafile = fopen(filename , "rb");

    // Buffer to hold the calculated digest
    unsigned char digest[SHA256_DIGEST_LENGTH];
    SHA256_CTX ctx;
    SHA256_Init(&ctx);

    // Read data in chunks and feed it to OpenSSL SHA256
    while((bytes = fread(buffer, 1, BUFFER_SIZE, datafile)))
    {
        SHA256_Update(&ctx, buffer, bytes);
    }

    SHA256_Final(digest, &ctx);
    fclose(datafile);

    // Read signature from file
    FILE* sign = fopen (sigfile , "r");

    bytes = fread(buffer, 1, BUFFER_SIZE, sign);
    fclose(sign);

    // Verify that calculated digest and signature match
    FILE* pubkey = fopen(pubkeyfile, "r"); 

    // Read public key from file
    RSA* rsa_pubkey = PEM_read_RSA_PUBKEY(pubkey, NULL, NULL, NULL);

    // Decrypt signature (in buffer) and verify it matches
    // with the digest calculated from data file.
    int result = RSA_verify(NID_sha256, digest, SHA256_DIGEST_LENGTH,
                            buffer, bytes, rsa_pubkey);
    RSA_free(rsa_pubkey);
    fclose(pubkey);

    if(result == 1)
    {
        printf("Signature is valid\n");
        return 0;
    }
    else
    {
        printf("Signature is invalid\n");
        return 1;
    }
}

除了将公钥作为文件参数传递之外,您还可以通过使用xxd -i pub-key.pem 生成一个漂亮的 C 风格的密钥头来轻松地支持它,程序可以使用它来代替 pubkeyfile .

示例代码来自:https://pagefault.blog/2019/04/22/how-to-sign-and-verify-using-openssl/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-15
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多