使用 C/OpenSSL 验证签名

问题描述 投票:0回答:1

我使用 PHP 生成了密钥对:

$options = [
    'digest_alg' => 'SHA256',
    'private_key_type' => OPENSSL_KEYTYPE_EC,
    'private_key_bits' => 2048,
    'curve_name' => 'secp384r1'];

这给了我:

-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEieSNdLKtNPdLIo9Y+f1DTfjnpZ4NFMXc
qVV2epFEWdtCyzhZnMubQDtpmhcycVZM+aPELe0dVWvwkFAY+VO0SpLT4I+cVkar
FSkjtp84jWZsWj8DT+7S0ukoEJzraeff
-----END PUBLIC KEY-----

-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDAUQuV5RcleR29UgIK0bjczEHctb6TK5z3PesxjT2R8A3B7iQDl0/I9
bkFjLyMYyFOgBwYFK4EEACKhZANiAASJ5I10sq0090sij1j5/UNN+Oelng0Uxdyp
VXZ6kURZ20LLOFmcy5tAO2maFzJxVkz5o8Qt7R1Va/CQUBj5U7RKktPgj5xWRqsV
KSO2nziNZmxaPwNP7tLS6SgQnOtp598=
-----END EC PRIVATE KEY-----

msg: Hello World!

sig: MGYCMQDa3+Nz6zxJOkvLjI2AVFXb4zfoYuFzy79Hg2bKq3El93oQwNleUgV
k1TuS8ptSj5kCMQCYVyplp5/yoCBLQpwsQw+MKlJ78ncQgiyh9UIBOFHTQvMjWiZ
BvOQ/B0VsZY7xoeo=

如何读取C/OpenSSL中的公钥并检查签名是否正确?我在 OpenSSL 文档中找不到正确的命令。

openssl public-key-encryption
1个回答
0
投票

这些例子很有帮助。我认为它不起作用,因为 base64 转换为二进制,以及“=”字符。这是一个工作示例:

#include <iostream>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/decoder.h>

void errors() {
    int r;
    char error[256];
    while ((r = ERR_get_error()) != 0) {
        ERR_error_string_n(r, error, 256);
        std::cout << "Error " << r << ": " << error << "\n";
    }
}

int pubKeyFromPem(EVP_PKEY** pkey, const unsigned char* data, size_t datalen) {
    const char* keytype = "EC";
    int selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
    OSSL_DECODER_CTX* dctx = OSSL_DECODER_CTX_new_for_pkey(pkey, "PEM", NULL, keytype, selection, NULL, NULL);
    if (dctx == NULL) {
        return __LINE__;
    }
    if (!OSSL_DECODER_from_data(dctx, &data, &datalen)) {
        return __LINE__;
    }
    OSSL_DECODER_CTX_free(dctx);
    return 0;
}

int base64ToSig(const char* sig64, int sig64len, unsigned char** sig, size_t* siglen) {
    int memory = sig64len / 4 * 3;
    *sig = (unsigned char*)malloc(memory);
    if (*sig == NULL)
        return __LINE__;
    int len = EVP_DecodeBlock(*sig, (const unsigned char*)sig64, sig64len);
    if (len == -1)
        return __LINE__;
    if (sig64[sig64len - 1] == '=')
        len--;
    if (sig64[sig64len - 2] == '=')
        len--;
    *siglen = len;
    return 0;
}

int verify(EVP_PKEY* key, const char* msg, unsigned char* sig, size_t siglen) {
    EVP_MD_CTX* mdctx;
    if (!(mdctx = EVP_MD_CTX_create()))
        return __LINE__;
    if (1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, key))
        return __LINE__;
    if (1 != EVP_DigestVerifyUpdate(mdctx, msg, strlen(msg)))
        return __LINE__;
    int r = EVP_DigestVerifyFinal(mdctx, sig, siglen);
    if (1 == r) {
        std::cout << "Success!\n";
    } else if (0 == r) {
        std::cout << "Failure!\n";
    } else {
        std::cout << "Error!\n";
        errors();
    }
    EVP_MD_CTX_free(mdctx);
    return 0;
}

int check() {
    int line;
    const char* msg = "Hello World!";
    const char* pubKeyPem =
        "-----BEGIN PUBLIC KEY-----\n"
        "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEQl0DmsjriyNARf16wXp8+S3qEkwKHOl4\n"
        "0kSfEo48e67oF03vjUyWKVl/FMnjpzMV9O6UpKUAR19svqJwa6iihhbBRU9PsfGO\n"
        "dGgCwedB85QrwtlJ9UZSrYQ93r9tUha3\n"
        "-----END PUBLIC KEY-----";
    const char* sig64 =
        "MGYCMQDkL/SH5FKGJSUkEWUhUgwvVTgQUg3jd49280/oTuu+EuwNzFiHhKo"
        "NXAeDqzW8r+4CMQDPVRoKGRI/a7qSZQZQuHFmh5kK9Wp9wY2+dvLb/4lCrW+PHM8"
        "Vs0S+ORkp1uoMUDY=";
    unsigned char* sig;
    size_t siglen;

    EVP_PKEY* key = NULL;
    line = pubKeyFromPem(&key, (const unsigned char*)pubKeyPem, strlen(pubKeyPem));
    if (line != 0)
        return line;
    line = base64ToSig(sig64, strlen(sig64), &sig, &siglen);
    if (line != 0)
        return line;
    std::cout << "Verifying with PEM key: ";
    line = verify(key, msg, sig, siglen);
    if (line != 0)
        return line;
    return 0;
}

int main() {
    int line = check();
    if (line != 0) {
        std::cout << __FILE__ << ":" << line << "\n";
        errors();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.