RSA 数学只需要n 和d 来实现签名。此外,OpenSSL 的实现也只需要n 和d 进行签名。您可以直接在 RSA 结构中设置这些值。此示例仅显示“...在 C 代码中使用带有 openssl ... 的 RSA 私钥签名文本”的示例,并忽略您的 PEM 查询。
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
static void printerrors() {
char errbuf[1024];
while (1) {
unsigned long error = ERR_get_error();
if (error == 0) {
break;
}
ERR_error_string(error, errbuf);
fputs(errbuf, stderr);
}
fflush(stderr);
}
static void sign(RSA *rsa, const char *message) {
EVP_PKEY *pkey = EVP_PKEY_new();
if (!EVP_PKEY_set1_RSA(pkey, rsa)) goto err;
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
if (!EVP_DigestSignInit(ctx, NULL, EVP_sha256(), NULL, pkey)) goto err;
if (!EVP_DigestSignUpdate(ctx, (const void * ) message, strlen(message))) goto err;
size_t siglen;
if (!EVP_DigestSignFinal(ctx, NULL, &siglen)) goto err;
unsigned char *signature = malloc(siglen);
if (signature == NULL) goto err;
if (!EVP_DigestSignFinal(ctx, signature, &siglen)) goto err;
for (int i = 0; i < siglen; i++) {
printf("%02x", signature[i]);
}
printf("\n");
free(signature);
EVP_MD_CTX_destroy(ctx);
EVP_PKEY_free(pkey);
return;
err:
printerrors();
exit(1);
}
int main(int argc, char *argv[]) {
const int BITS = 1024;
const int PUBLIC_EXPONENT = 65537;
OpenSSL_add_all_algorithms();
RSA *rsa = RSA_generate_key(BITS, PUBLIC_EXPONENT, NULL, NULL);
RSA *rsa2 = RSA_new();
rsa2->n = BN_dup(rsa -> n);
rsa2->e = BN_dup(rsa -> e);
rsa2->d = BN_dup(rsa -> d);
RSA_print_fp(stdout, rsa2, 0);
sign(rsa2, "Sign me, please");
RSA_free(rsa2);
RSA_free(rsa);
}
通常与私钥相关联的其他值,p、q 等并非绝对必要。如果存在,它们可用于加速私钥操作,包括利用中国剩余定理进行签名。此外,如果需要,它们可以很容易地从 n、d 和 e 派生出来:例如参见 section 8.2.2 (i) of the Handbook Of Applied Cryptography。