Skip to content

Instantly share code, notes, and snippets.

@devendranaga
Created March 1, 2020 17:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devendranaga/ba702d1b1dc42d0639b090b5ad6c94a8 to your computer and use it in GitHub Desktop.
Save devendranaga/ba702d1b1dc42d0639b090b5ad6c94a8 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <stdint.h>
#include <string.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
class sm2_crypto {
public:
explicit sm2_crypto() {
OpenSSL_add_all_algorithms();
}
~sm2_crypto() {
}
int generate_key(std::string pubkeyfile, std::string privkeyfile);
int sign(const uint8_t *text_msg, size_t text_msg_len, uint8_t *signature, size_t *signature_len);
int verify(const uint8_t *text_msg, int text_msg_len, uint8_t *signature, size_t signature_len);
};
int sm2_crypto::generate_key(std::string pubkeyfile, std::string privkeyfile)
{
EC_KEY *key;
key = EC_KEY_new_by_curve_name(NID_sm2);
if (!key) {
return -1;
}
int ret = EC_KEY_generate_key(key);
if (ret != 1) {
return -1;
}
ret = EC_KEY_check_key(key);
if (ret != 1) {
return -1;
}
FILE *fp = fopen(pubkeyfile.c_str(), "w");
if (!fp) {
return -1;
}
PEM_write_EC_PUBKEY(fp, key);
fflush(fp);
fclose(fp);
fp = fopen(privkeyfile.c_str(), "w");
if (!fp) {
return -1;
}
PEM_write_ECPrivateKey(fp, key, nullptr, nullptr, 0, nullptr, nullptr);
fflush(fp);
fclose(fp);
printf("SM2 key is created\n");
return 0;
}
int sm2_crypto::sign(const uint8_t *text_msg, size_t text_msg_len, uint8_t *signature, size_t *signature_len)
{
int ret;
FILE *fp = fopen("./sm2_priv.key", "r");
if (!fp) {
return -1;
}
EC_KEY *key = PEM_read_ECPrivateKey(fp, nullptr, nullptr, nullptr);
if (!key) {
return -1;
}
fclose(fp);
EVP_PKEY *evp_key = EVP_PKEY_new();
if (!evp_key) {
return -1;
}
ret = EVP_PKEY_assign_EC_KEY(evp_key, key);
if (ret != 1) {
return -1;
}
EVP_PKEY_CTX *sign_ctx = EVP_PKEY_CTX_new(evp_key, nullptr);
if (!sign_ctx) {
return -1;
}
ret = EVP_PKEY_sign_init(sign_ctx);
if (ret != 1) {
return -1;
}
ret = EVP_PKEY_CTX_set_signature_md(sign_ctx, EVP_sha256());
if (ret != 1) {
return -1;
}
ret = EVP_PKEY_sign(sign_ctx, signature, signature_len, (uint8_t *)text_msg, text_msg_len);
if (ret != 1) {
return -1;
}
printf("signature ");
for (int i = 0; i < *signature_len; i ++) {
printf("%02x", signature[i]);
}
printf("\n");
EVP_PKEY_free(evp_key);
EVP_PKEY_CTX_free(sign_ctx);
return 0;
}
int sm2_crypto::verify(const uint8_t *text_msg, int text_msg_len, uint8_t *signature, size_t signature_len)
{
int ret;
FILE *fp = fopen("./sm2_pub.key", "r");
if (!fp) {
return -1;
}
EC_KEY *key = PEM_read_EC_PUBKEY(fp, nullptr, nullptr, nullptr);
if (!key) {
return -1;
}
EVP_PKEY *pkey = EVP_PKEY_new();
if (!pkey) {
return -1;
}
ret = EVP_PKEY_assign_EC_KEY(pkey, key);
if (ret != 1) {
return -1;
}
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, nullptr);
if (!ctx) {
return -1;
}
ret = EVP_PKEY_verify_init(ctx);
if (ret != 1) {
return -1;
}
ret = EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256());
if (ret != 1) {
return -1;
}
ret = EVP_PKEY_verify(ctx, signature, signature_len, text_msg, text_msg_len);
if (ret != 1) {
return -1;
}
fclose(fp);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return 0;
}
int main()
{
char *text_msg = "test message for sm2";
uint8_t signature[128];
size_t signature_len = sizeof(signature);
int ret;
sm2_crypto sm2;
ret = sm2.generate_key("./sm2_pub.key", "./sm2_priv.key");
ret = sm2.sign((uint8_t *)text_msg, strlen(text_msg), signature, &signature_len);
if (ret != 0) {
printf("failed to sign\n");
} else {
printf("sign ok\n");
ret = sm2.verify((uint8_t *)text_msg, strlen(text_msg), signature, signature_len);
if (ret != 0) {
printf("failed to verify\n");
} else {
printf("verify ok\n");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment