Created
March 1, 2020 17:36
-
-
Save devendranaga/ba702d1b1dc42d0639b090b5ad6c94a8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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