我使用 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 文档中找不到正确的命令。
这些例子很有帮助。我认为它不起作用,因为 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();
}
}