区块链学习笔记前置篇之四:基于openssl的数字签名

关于数字签名的原理请自行百度,我们这里使用椭圆曲线加密算法来进行签名,下面上代码

#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>

typedef struct __keydata
{
    int len;
    unsigned char key[256];
} KeyData;

typedef struct __KeyPair
{
    KeyData prikey;
    KeyData pubKey;
} KeyPair;

void Createkey(KeyPair &keyPair)
{
    unsigned char *p = NULL;
    keyPair.prikey.len = -1;
    keyPair.pubKey.len = -1;

    EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp256k1);
    if (!group)
        return ;

    EC_KEY *key = EC_KEY_new();
    if (!key)
    {
        EC_GROUP_free(group);
        return;
    }

    if(!EC_KEY_set_group(key, group))
    {
        EC_GROUP_free(group);
        EC_KEY_free(key);
        return;
    }

    if (!EC_KEY_generate_key(key))
    {
        EC_GROUP_free(group);
        EC_KEY_free(key);
        return;
    }

    if (!EC_KEY_check_key(key))
    {
        EC_GROUP_free(group);
        EC_KEY_free(key);
        return;
    }

    keyPair.prikey.len = i2d_ECPrivateKey(key, NULL);
    if (keyPair.prikey.len > (int)sizeof(keyPair.prikey.key))
    {
        keyPair.prikey.len = -1;
        EC_GROUP_free(group);
        EC_KEY_free(key);
        return;
    }
    p = keyPair.prikey.key;
    keyPair.prikey.len = i2d_ECPrivateKey(key, &p);

    keyPair.pubKey.len = i2o_ECPublicKey(key, NULL);
    if (keyPair.pubKey.len > (int)sizeof(keyPair.pubKey.key))
    {
        keyPair.pubKey.len = -1;
        EC_GROUP_free(group);
        EC_KEY_free(key);
        return;
    }
    p = keyPair.pubKey.key;
    keyPair.pubKey.len = i2o_ECPublicKey(key, &p);

    EC_GROUP_free(group);
    EC_KEY_free(key);
}

int Signature(const KeyData &prikey, const char *data, int datalen, unsigned char *sign, size_t signszie, unsigned int *signlen)
{
    EC_KEY *ec_key = NULL;
    const unsigned char *pp = (const unsigned char *)prikey.key;
    ec_key = d2i_ECPrivateKey(&ec_key, &pp, prikey.len);
    if (!ec_key)
        return 0;

    if (ECDSA_size(ec_key) > (int)signszie)
    {
        EC_KEY_free(ec_key);
        return 0;
    }

    if (!ECDSA_sign(0, (unsigned char *)data, datalen, sign, signlen, ec_key))
    {
        EC_KEY_free(ec_key);
        return 0;
    }

    EC_KEY_free(ec_key);
    return 1;
}

int Verify(const KeyData &pubkey, const char *data, int datalen, const unsigned char *sign, size_t signszie, unsigned int signlen)
{
    int ret = -1;
    EC_KEY *ec_key = NULL;
    EC_GROUP *ec_group = NULL;
    const unsigned char *pp = (const unsigned char *)pubkey.key;

    ec_key = EC_KEY_new();
    if (!ec_key)
        return 0;

    if (ECDSA_size(ec_key) > (int)signszie)
    {
        EC_KEY_free(ec_key);
        return 0;
    }

    ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1);
    if (!ec_group)
    {
        EC_KEY_free(ec_key);
        return 0;
    }

    if (!EC_KEY_set_group(ec_key, ec_group))
    {
        EC_GROUP_free(ec_group);
        EC_KEY_free(ec_key);
        return 0;
    }

    ec_key = o2i_ECPublicKey(&ec_key, &pp, pubkey.len);
    if (!ec_key)
    {
        EC_GROUP_free(ec_group);
        EC_KEY_free(ec_key);
        return 0;
    }

    ret = ECDSA_verify(0, (const unsigned char*)data, datalen, sign,
        signlen, ec_key);

    EC_GROUP_free(ec_group);
    EC_KEY_free(ec_key);
    return ret;
}

猜你喜欢

转载自blog.csdn.net/mumufan05/article/details/82012745
今日推荐