如何使用 ECDSA 以编程方式创建自签名数字证书
how to use ECDSA to create a self signed digital certificate programatically
我正在尝试创建一个数字证书,该证书将使用 EC 密钥而不是来自 RSA 的密钥进行自签名,并遵循这些 SO link1 and link2。我将 link1 中给出的 RSA 的签名算法替换为 EC 为
EC_KEY *ecc = NULL;
int eccgrp = OBJ_txt2nid("secp256k1");
ecc = EC_KEY_new_by_curve_name(eccgrp);
EC_KEY_set_asn1_flag(ecc, OPENSSL_EC_NAMED_CURVE);
if(!(EC_KEY_generate_key(ecc))) {
BIO_printf(out, "Error in generating key");
printf("Error 1\n");
}
if(!EVP_PKEY_assign_EC_KEY(pk, ecc)) {
BIO_printf(out, "Error assigning EC_KEY to EVP_PKEY");
printf("Error 2\n");
}
.
.
X509_set_pubkey(x,pk);
.
.
if (!X509_sign(x,pk,EVP_md5()))
goto err;
.
.
其余代码与链接 1 中给出的相同。没有打印错误,但是当我尝试打印 x509 证书 X509_print_fp(stdout,x509);
时出现段错误。这样做的正确方法是什么?
您更改 that code 比您说的要多,因为它没有变量 'pk' 或 'x'。
任何时候你从 libcrypto 例程中得到 error/failure return 你应该总是查看错误队列;请参阅 https://www.openssl.org/docs/faq.html#PROG6 and https://www.openssl.org/docs/faq.html#PROG7 . (For libssl routines you should do so depending on the return from SSL_get_error。)如果您按照我下面针对 'bad' 案例的代码这样做,您会看到 X509_sign
失败并显示
140018941793960:error:100C508A:elliptic curve routines:PKEY_EC_CTRL:invalid digest type:ec_pmeth.c:388:
因为标准 ECDSA 签名方案不包括 MD5。 您必须使用 SHA1 或 SHA2,并且您应该使用与 ECC 密钥强度匹配的散列,在本例中为 SHA256。由于签名失败,x509
结构不包含有效数据,无法成功打印。
另请注意:自 1.0.0(2010 年)起,PEM_write_PrivateKey
with enc
nonnull 使用 'new'(约 2000 年!)PKCS#8/PBES2 格式,这需要一个OpenSSL_add_all_algorithms
.
的合适变体
完整的工作演示质量代码:
/* SO #35899969 */
#include <stdio.h>
#include <stdlib.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#ifdef _WIN32
#include <openssl/applink.c>
#endif
/* minimal error handling for demo; real code do better */
void err (const char *label)
{
fprintf (stderr, "Error in %s:\n", label);
ERR_print_errors_fp (stderr);
exit (1);
}
int main (int argc, char**argv)
{
int bad = argc>1;
ERR_load_crypto_strings(); /* or SSL_load_error_strings */
OPENSSL_add_all_algorithms_noconf(); /* for PKCS8 w PBES2 */
EVP_PKEY * pkey = EVP_PKEY_new();
EC_KEY *ecc = EC_KEY_new_by_curve_name(NID_secp256k1);
/* simpler than going through OBJ_txt2nid */
if(!ecc) err("ECCnewbyname");
EC_KEY_set_asn1_flag(ecc, OPENSSL_EC_NAMED_CURVE);
if(!(EC_KEY_generate_key(ecc))) err("ECCgen");
if(!EVP_PKEY_assign_EC_KEY(pkey, ecc)) err("PKEYassign");
X509 * x509 = X509_new();
/* REALLY shouldn't use fixed serial if DN isn't unique */
ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
X509_gmtime_adj(X509_get_notBefore(x509), 0);
X509_gmtime_adj(X509_get_notAfter(x509), 365L*86400);
X509_set_pubkey(x509, pkey);
X509_NAME * name = X509_get_subject_name(x509);
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC,
(unsigned char *)"CA", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
(unsigned char *)"MyCompany Inc.", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
(unsigned char *)"localhost", -1, -1, 0);
X509_set_issuer_name(x509, name);
if(!X509_sign(x509, pkey, bad? EVP_md5(): EVP_sha256())) err("X509sign");
/* simplified */
if(!PEM_write_PrivateKey(stdout, pkey, EVP_des_ede3_cbc(),
NULL,0,NULL,"passphrase"))
err("writeKey");
if(!PEM_write_X509(stdout, x509))
err("writeCert");
/* added */
X509_print_fp (stdout, x509);
return 0;
}
我正在尝试创建一个数字证书,该证书将使用 EC 密钥而不是来自 RSA 的密钥进行自签名,并遵循这些 SO link1 and link2。我将 link1 中给出的 RSA 的签名算法替换为 EC 为
EC_KEY *ecc = NULL;
int eccgrp = OBJ_txt2nid("secp256k1");
ecc = EC_KEY_new_by_curve_name(eccgrp);
EC_KEY_set_asn1_flag(ecc, OPENSSL_EC_NAMED_CURVE);
if(!(EC_KEY_generate_key(ecc))) {
BIO_printf(out, "Error in generating key");
printf("Error 1\n");
}
if(!EVP_PKEY_assign_EC_KEY(pk, ecc)) {
BIO_printf(out, "Error assigning EC_KEY to EVP_PKEY");
printf("Error 2\n");
}
.
.
X509_set_pubkey(x,pk);
.
.
if (!X509_sign(x,pk,EVP_md5()))
goto err;
.
.
其余代码与链接 1 中给出的相同。没有打印错误,但是当我尝试打印 x509 证书 X509_print_fp(stdout,x509);
时出现段错误。这样做的正确方法是什么?
您更改 that code 比您说的要多,因为它没有变量 'pk' 或 'x'。
任何时候你从 libcrypto 例程中得到 error/failure return 你应该总是查看错误队列;请参阅 https://www.openssl.org/docs/faq.html#PROG6 and https://www.openssl.org/docs/faq.html#PROG7 . (For libssl routines you should do so depending on the return from SSL_get_error。)如果您按照我下面针对 'bad' 案例的代码这样做,您会看到 X509_sign
失败并显示
140018941793960:error:100C508A:elliptic curve routines:PKEY_EC_CTRL:invalid digest type:ec_pmeth.c:388:
因为标准 ECDSA 签名方案不包括 MD5。 您必须使用 SHA1 或 SHA2,并且您应该使用与 ECC 密钥强度匹配的散列,在本例中为 SHA256。由于签名失败,x509
结构不包含有效数据,无法成功打印。
另请注意:自 1.0.0(2010 年)起,PEM_write_PrivateKey
with enc
nonnull 使用 'new'(约 2000 年!)PKCS#8/PBES2 格式,这需要一个OpenSSL_add_all_algorithms
.
完整的工作演示质量代码:
/* SO #35899969 */
#include <stdio.h>
#include <stdlib.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#ifdef _WIN32
#include <openssl/applink.c>
#endif
/* minimal error handling for demo; real code do better */
void err (const char *label)
{
fprintf (stderr, "Error in %s:\n", label);
ERR_print_errors_fp (stderr);
exit (1);
}
int main (int argc, char**argv)
{
int bad = argc>1;
ERR_load_crypto_strings(); /* or SSL_load_error_strings */
OPENSSL_add_all_algorithms_noconf(); /* for PKCS8 w PBES2 */
EVP_PKEY * pkey = EVP_PKEY_new();
EC_KEY *ecc = EC_KEY_new_by_curve_name(NID_secp256k1);
/* simpler than going through OBJ_txt2nid */
if(!ecc) err("ECCnewbyname");
EC_KEY_set_asn1_flag(ecc, OPENSSL_EC_NAMED_CURVE);
if(!(EC_KEY_generate_key(ecc))) err("ECCgen");
if(!EVP_PKEY_assign_EC_KEY(pkey, ecc)) err("PKEYassign");
X509 * x509 = X509_new();
/* REALLY shouldn't use fixed serial if DN isn't unique */
ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
X509_gmtime_adj(X509_get_notBefore(x509), 0);
X509_gmtime_adj(X509_get_notAfter(x509), 365L*86400);
X509_set_pubkey(x509, pkey);
X509_NAME * name = X509_get_subject_name(x509);
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC,
(unsigned char *)"CA", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
(unsigned char *)"MyCompany Inc.", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
(unsigned char *)"localhost", -1, -1, 0);
X509_set_issuer_name(x509, name);
if(!X509_sign(x509, pkey, bad? EVP_md5(): EVP_sha256())) err("X509sign");
/* simplified */
if(!PEM_write_PrivateKey(stdout, pkey, EVP_des_ede3_cbc(),
NULL,0,NULL,"passphrase"))
err("writeKey");
if(!PEM_write_X509(stdout, x509))
err("writeCert");
/* added */
X509_print_fp (stdout, x509);
return 0;
}