OpenSSL 椭圆曲线(ECDSA)签名与验证示例

基于命令行参数

  • 生成 secp256k1 椭圆曲线参数

openssl ecparam -out demo.param -name secp256k1

  • 生成椭圆曲线密钥

openssl genpkey -paramfile demo.param -out demo.pem

  • 提取密钥

openssl ec -in demo.pem -text

  • 提取私钥 pem

openssl ec -in demo.pem

  • 提取公钥 pem

openssl ec -in demo.pem -pubout -out ec-pub.pem

  • 对待签名数据生成摘要(data.txt 文件里的内容即签名的原文)

openssl dgst -sha256 -binary -out data.sha256 data.txt

  • 基于摘要执行签名

openssl pkeyutl -sign -inkey demo.pem -in data.sha256 -out data.sig

  • 基于签名数据与原文执行签名验证

openssl dgst -sha256 -verify ec-pub.pem -signature data.sig data.txt

基于 C 语言编程接口

以下 TestEcdsa 函数演示了多种密钥生成与初始化的方法,以及签名、验证签名。可对应改变注释代码块进行验证。注意,函数最后未做严格的内存清理。

#include <openssl/obj_mac.h>
#include <openssl/ecdsa.h>

void TestEcdsa() {
  BIO *key_bio = NULL;
  EC_KEY *eckey;

  // // 生成密钥
  // eckey = EC_KEY_new_by_curve_name(NID_secp192k1);
  // if (!eckey) {
  // }
  // if (!EC_KEY_generate_key(eckey)) {
  // }

  // // 从文件读入密钥
  // // openssl ecparam -out demo.param -name secp256k1
  // // openssl genpkey -paramfile demo.param -out demo.pem
  // key_bio = BIO_new(BIO_s_file());
  // if (!key_bio) {
  //   printf("BIO_new failed!\n");
  //   return;
  // }
  // BIO_read_filename(key_bio, "demo.pem");
  // eckey = PEM_read_bio_ECPrivateKey(key_bio, NULL, NULL, NULL);
  // if (!eckey) {
  //   printf("PEM_read_bio_ECPrivateKey failed!\n");
  //   return;
  // }

  // 从 PEM 形式私钥字符串初始化
  // openssl ec -in demo.pem
  char *pri_key = "-----BEGIN EC PRIVATE KEY-----\n\
MHQCAQEEIKg5Yz8JR2POo8dbgxCi0ycU9PB840tuYX2duY/esnbxoAcGBSuBBAAK\n\
oUQDQgAEfkHkd/srpr+qnv5mYR1/MccSTyZXJ5ph4DJbJsL7tin8FxM8nmob/CQf\n\
uDfP+cZ3ixqjNAHL3TJGQ8axs8ydbw==\n\
-----END EC PRIVATE KEY-----";
  key_bio = BIO_new_mem_buf(pri_key, strlen(pri_key));
  if (!key_bio){
    printf("BIO_new_mem_buf failed!\n");
    return;
  }
  eckey = PEM_read_bio_ECPrivateKey(key_bio, NULL, NULL, NULL);
  if (!eckey) {
    printf("PEM_read_bio_EC_PUBKEY failed!\n");
    return;
  }

  // 执行签名
  char *digest = "Ia4TUC6Yo+H1LNLYlrEMxecXmLeD38foe593nQTb9t8=";
  ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)digest, strlen(digest), eckey);
  if (!sig) {
    printf("ECDSA_do_sign failed!\n");
    return;
  }

//   // 从 PEM 形式公钥字符串初始化
//   // openssl ec -in demo.pem -pubout
//   BIO *pub_bio = NULL;
//   EC_KEY    *eckey_pub;
//   char *pub_key = "-----BEGIN PUBLIC KEY-----\n\
// MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEfkHkd/srpr+qnv5mYR1/MccSTyZXJ5ph\n\
// 4DJbJsL7tin8FxM8nmob/CQfuDfP+cZ3ixqjNAHL3TJGQ8axs8ydbw==\n\
// -----END PUBLIC KEY-----";
//   pub_bio = BIO_new_mem_buf(pub_key, strlen(pub_key));
//   if (!pub_bio){
//     printf("BIO_new_mem_buf failed!\n");
//     return;
//   }
//   eckey_pub = PEM_read_bio_EC_PUBKEY(pub_bio, NULL, NULL, NULL);
//   if (!eckey_pub) {
//     printf("PEM_read_bio_EC_PUBKEY failed!\n");
//     return;
//   }

  // 从原始数据格式公钥初始化
  // openssl ec -in demo.pem -text
  unsigned char raw[65] = {0x04, 0x7e, 0x41, 0xe4, 0x77, 0xfb, 0x2b, 0xa6, 0xbf, 0xaa, 0x9e, 0xfe, 0x66, 0x61, 0x1d,
    0x7f, 0x31, 0xc7, 0x12, 0x4f, 0x26, 0x57, 0x27, 0x9a, 0x61, 0xe0, 0x32, 0x5b, 0x26, 0xc2,
    0xfb, 0xb6, 0x29, 0xfc, 0x17, 0x13, 0x3c, 0x9e, 0x6a, 0x1b, 0xfc, 0x24, 0x1f, 0xb8, 0x37,
    0xcf, 0xf9, 0xc6, 0x77, 0x8b, 0x1a, 0xa3, 0x34, 0x01, 0xcb, 0xdd, 0x32, 0x46, 0x43, 0xc6,
    0xb1, 0xb3, 0xcc, 0x9d, 0x6f};
  EC_KEY *eckey_pub = EC_KEY_new_by_curve_name(NID_secp256k1);
  const unsigned char *ptr = raw;
  o2i_ECPublicKey(&eckey_pub, &ptr, sizeof(raw));

  // 验证签名
  int ret = ECDSA_do_verify((unsigned char*)digest, strlen(digest), sig, eckey_pub);
  // int ret = ECDSA_do_verify((unsigned char*)digest, strlen(digest), sig, eckey);
  if (ret == -1) {
    printf("verify failed!\n");
  }
  else if (ret == 0) {
    printf("incorrect signature!\n");
  }
  else { /* ret == 1 */
    printf("signature ok\n");
  }
  //TODO clean up
}

参考

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jackindata

多谢认可!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值