1. 参考相关内容,在 Ubuntu或openEuler中(推荐 openEuler)中使用OpenSSL库编程实现调用SM2(加密解密,签名验签),SM3(摘要计算,HMAC 计算),SM4(加密解密)算法,使用Markdown记录详细记录实践过程,每完成一项git commit 一次。(5’)
SM2
加密解密
djy666@ubuntu:~/djy$ openssl ecparam -genkey -name SM2 -out private_key.pem
djy666@ubuntu:~/djy$ cat private_key.pem
-----BEGIN SM2 PARAMETERS-----
BggqgRzPVQGCLQ==
-----END SM2 PARAMETERS-----
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgdyzordRMyhIe5PmF
Y5oPPok6e3Vlii2CLSIs3E5GoUehRANCAAT0bfIm3qIYFxltwUQ3igqUIFCBjKiY
kmD6wHzJh76wChldmcH5XVIiBVTXqtK/3RxyjLJEVuT1M269U/FMOUn5
-----END PRIVATE KEY-----
djy666@ubuntu:~/djy$ vim encrypted_file
djy666@ubuntu:~/djy$ vim decrypted_file
djy666@ubuntu:~/djy$ vim sm2_encrypt.c
djy666@ubuntu:~/djy$ gcc -o sm2_encrypt sm2_encrypt.c -lcrypto
djy666@ubuntu:~/djy$ vim sm2_decrypt.c
djy666@ubuntu:~/djy$ gcc -o sm2_decrypt sm2_decrypt.c -lcrypto
djy666@ubuntu:~/djy$ openssl pkey -in private_key.pem -pubout -out public_key.pem
djy666@ubuntu:~/djy$ cat public_key.pem
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE9G3yJt6iGBcZbcFEN4oKlCBQgYyo
mJJg+sB8yYe+sAoZXZnB+V1SIgVU16rSv90ccoyyRFbk9TNuvVPxTDlJ+Q==
-----END PUBLIC KEY-----
djy666@ubuntu:~/djy$ vim plain.txt
djy666@ubuntu:~/djy$ ./sm2_encrypt public_key.pem plain.txt encrypted_file
Encryption complete.
djy666@ubuntu:~/djy$ ./sm2_decrypt private_key.pem encrypted_file decrypted_file
Decryption successful.
git commit
djy666@ubuntu:~/djy$ git commit -m "sm2_test"
[master d747d30] sm2_test
19 files changed, 409 insertions(+)
create mode 100644 decrypted_file
create mode 100644 encrypted_file
create mode 100644 plain.txt
create mode 100644 private_key.pem
create mode 100644 public_key.pem
create mode 100755 sm2_decrypt
create mode 100644 sm2_decrypt.c
create mode 100755 sm2_encrypt
create mode 100644 sm2_encrypt.c
create mode 100644 sm2_test/private_key.pem
代码
- sm2_encrypt.c
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <stdio.h>
#include <stdlib.h>
void handleErrors(void) {
fprintf(stderr, "An error occurred.\n");
exit(1);
}
int main(int argc, char *argv[]) {
if (argc != 4) {
fprintf(stderr, "Usage: %s <public_key.pem> <input file> <output file>\n", argv[0]);
return 1;
}
char *public_key_filename = argv[1];
char *input_file = argv[2];
char *output_file = argv[3];
FILE *f_input, *f_output, *f_public_key;
unsigned char buffer[1024];
unsigned char *ciphertext;
size_t ciphertext_len;
size_t bytes_read;
EVP_PKEY *public_key = NULL;
EVP_PKEY_CTX *ctx = NULL;
if (!(f_public_key = fopen(public_key_filename, "r"))) {
fprintf(stderr, "Unable to open public key file %s\n", public_key_filename);
return 1;
}
if (!(public_key = PEM_read_PUBKEY(f_public_key, NULL, NULL, NULL))) {
fprintf(stderr, "Error loading public key\n");
fclose(f_public_key);
return 1;
}
fclose(f_public_key);
if (!OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL))
handleErrors();
if (!(ctx = EVP_PKEY_CTX_new(public_key, NULL)))
handleErrors();
if (EVP_PKEY_encrypt_init(ctx) <= 0)
handleErrors();
if (!(f_input = fopen(input_file, "rb"))) {
fprintf(stderr, "Could not open %s for reading\n", input_file);
return 1;
}
if (!(f_output = fopen(output_file, "wb"))) {
fprintf(stderr, "Could not open %s for writing\n", output_file);
return 1;
}
if (EVP_PKEY_encrypt(ctx, NULL, &ciphertext_len, buffer, sizeof(buffer)) <= 0)
handleErrors();
ciphertext = malloc(ciphertext_len);
if (!ciphertext) {
fprintf(stderr, "Memory allocation failed\n");
return 1;
}
while ((bytes_read = fread(buffer, 1, sizeof(buffer), f_input)) > 0) {
if (EVP_PKEY_encrypt(ctx, ciphertext, &ciphertext_len, buffer, bytes_read) <= 0)
handleErrors();
fwrite(ciphertext, 1, ciphertext_len, f_output);
}
EVP_PKEY_free(public_key);
EVP_PKEY_CTX_free(ctx);
fclose(f_input);
fclose(f_output);
free(ciphertext);
printf("Encryption complete.\n");
return 0;
}
- sm2_decrypt.c
#include <openssl/ec.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <stdio.h>
#include <stdlib.h>
void handle_errors() {
ERR_print_errors_fp(stderr);
abort();
}
int main(int argc, char **argv) {
if (argc != 4) {
fprintf(stderr, "Usage: %s <private_key.pem> <encrypted_file> <decrypted_file>\n", argv[0]);
return EXIT_FAILURE;
}
const char *private_key_file = argv[1];
const char *encrypted_file = argv[2];
const char *decrypted_file = argv[3];
EVP_PKEY *private_key = NULL;
FILE *fp;
fp = fopen(private_key_file, "r");
if (!fp) {
perror("Error opening private key file");
return EXIT_FAILURE;
}
private_key = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
fclose(fp);
if (!private_key) {
handle_errors();
return EXIT_FAILURE;
}
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(private_key, NULL);
if (!ctx) {
handle_errors();
return EXIT_FAILURE;
}
if (EVP_PKEY_decrypt_init(ctx) <= 0) {
handle_errors();
return EXIT_FAILURE;
}
FILE *fin = fopen(encrypted_file, "rb");
if (!fin) {
perror("Error opening encrypted file");
return EXIT_FAILURE;
}
fseek(fin, 0, SEEK_END);
long encrypted_data_size = ftell(fin);
fseek(fin, 0, SEEK_SET);
unsigned char *encrypted_data = malloc(encrypted_data_size);
fread(encrypted_data, 1, encrypted_data_size, fin);
fclose(fin);
unsigned char *decrypted_data = NULL;
size_t decrypted_data_size = 0;
if (EVP_PKEY_decrypt(ctx, NULL, &decrypted_data_size, encrypted_data, encrypted_data_size) <= 0) {
handle_errors();
return EXIT_FAILURE;
}
decrypted_data = malloc(decrypted_data_size);
if (EVP_PKEY_decrypt(ctx, decrypted_data, &decrypted_data_size, encrypted_data, encrypted_data_size) <= 0) {
handle_errors();
return EXIT_FAILURE;
}
FILE *fout = fopen(decrypted_file, "wb");
if (!fout) {
perror("Error opening decrypted file");
return EXIT_FAILURE;
}
fwrite(decrypted_data, 1, decrypted_data_size, fout);
fclose(fout);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(private_key);
free(encrypted_data);
free(decrypted_data);
printf("Decryption successful.\n");
return EXIT_SUCCESS;
}
签名验签
djy666@ubuntu:~/djy$ vim sign.c
djy666@ubuntu:~/djy$ gcc sign.c -o sign -lcrypto
djy666@ubuntu:~/djy$ vim sign_file
djy666@ubuntu:~/djy$ ./sign private_key.pem plain.txt sign_file
Signature successfully written to sign_file
djy666@ubuntu:~/djy$ vim verify.c
djy666@ubuntu:~/djy$ gcc verify.c -o verify -lcrypto
djy666@ubuntu:~/djy$ ./verify public_key.pem plain.txt sign_file
Signature verification successful!
git commit
djy666@ubuntu:~/djy$ git commit -m "sm2_test"
[master 097fb6a] sm2_test
5 files changed, 208 insertions(+)
create mode 100755 sign
create mode 100644 sign.c
create mode 100644 sign_file
create mode 100755 verify
create mode 100644 verify.c
代码
- sign.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>
void handle_errors() {
ERR_print_errors_fp(stderr);
abort();
}
void sign_file(const char *private_key_file, const char *input_file, const char *output_file) {
FILE *fp = fopen(input_file, "rb");
if (!fp) {
perror("Unable to open input file");
exit(EXIT_FAILURE);
}
fseek(fp, 0, SEEK_END);
long file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
unsigned char *data = malloc(file_size);
if (!data) {
perror("Unable to allocate memory");
fclose(fp);
exit(EXIT_FAILURE);
}
fread(data, 1, file_size, fp);
fclose(fp);
FILE *key_fp = fopen(private_key_file, "r");
if (!key_fp) {
perror("Unable to open private key file");
free(data);
exit(EXIT_FAILURE);
}
EVP_PKEY *pkey = PEM_read_PrivateKey(key_fp, NULL, NULL, NULL);
fclose(key_fp);
if (!pkey) {
handle_errors();
}
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
if (!ctx) {
handle_errors();
}
if (EVP_DigestSignInit(ctx, NULL, EVP_sm3(), NULL, pkey) != 1) {
handle_errors();
}
if (EVP_DigestSignUpdate(ctx, data, file_size) != 1) {
handle_errors();
}
size_t sig_len;
if (EVP_DigestSignFinal(ctx, NULL, &sig_len) != 1) {
handle_errors();
}
unsigned char *sig = malloc(sig_len);
if (!sig) {
perror("Unable to allocate memory for signature");
EVP_MD_CTX_free(ctx);
EVP_PKEY_free(pkey);
free(data);
exit(EXIT_FAILURE);
}
if (EVP_DigestSignFinal(ctx, sig, &sig_len) != 1) {
handle_errors();
}
FILE *out_fp = fopen(output_file, "wb");
if (!out_fp) {
perror("Unable to open output file");
free(sig);
EVP_MD_CTX_free(ctx);
EVP_PKEY_free(pkey);
free(data);
exit(EXIT_FAILURE);
}
fwrite(sig, 1, sig_len, out_fp);
fclose(out_fp);
printf("Signature successfully written to %s\n", output_file);
free(sig);
EVP_MD_CTX_free(ctx);
EVP_PKEY_free(pkey);
free(data);
}
int main(int argc, char **argv) {
if (argc != 4) {
fprintf(stderr, "Usage: %s <private_key.pem> <input_file> <output_file>\n", argv[0]);
return EXIT_FAILURE;
}
sign_file(argv[1], argv[2], argv[3]);
return EXIT_SUCCESS;
}
- verify.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>
void handle_errors() {
ERR_print_errors_fp(stderr);
abort();
}
int verify_signature(const char *public_key_file, const char *input_file, const char *signature_file) {
FILE *fp = fopen(input_file, "rb");
if (!fp) {
perror("Unable to open input file");
return EXIT_FAILURE;
}
fseek(fp, 0, SEEK_END);
long file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
unsigned char *data = malloc(file_size);
if (!data) {
perror("Unable to allocate memory");
fclose(fp);
return EXIT_FAILURE;
}
fread(data, 1, file_size, fp);
fclose(fp);
FILE *sig_fp = fopen(signature_file, "rb");
if (!sig_fp) {
perror("Unable to open signature file");
free(data);
return EXIT_FAILURE;
}
fseek(sig_fp, 0, SEEK_END);
long sig_size = ftell(sig_fp);
fseek(sig_fp, 0, SEEK_SET);
unsigned char *signature = malloc(sig_size);
if (!signature) {
perror("Unable to allocate memory for signature");
fclose(sig_fp);
free(data);
return EXIT_FAILURE;
}
fread(signature, 1, sig_size, sig_fp);
fclose(sig_fp);
FILE *key_fp = fopen(public_key_file, "r");
if (!key_fp) {
perror("Unable to open public key file");
free(signature);
free(data);
return EXIT_FAILURE;
}
EVP_PKEY *pkey = PEM_read_PUBKEY(key_fp, NULL, NULL, NULL);
fclose(key_fp);
if (!pkey) {
handle_errors();
}
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
if (!ctx) {
handle_errors();
}
if (EVP_DigestVerifyInit(ctx, NULL, EVP_sm3(), NULL, pkey) != 1) {
handle_errors();
}
if (EVP_DigestVerifyUpdate(ctx, data, file_size) != 1) {
handle_errors();
}
int ret = EVP_DigestVerifyFinal(ctx, signature, sig_size);
if (ret == 1) {
printf("Signature verification successful!\n");
} else {
printf("Signature verification failed!\n");
}
EVP_MD_CTX_free(ctx);
EVP_PKEY_free(pkey);
free(signature);
free(data);
return ret == 1 ? EXIT_SUCCESS : EXIT_FAILURE;
}
int main(int argc, char **argv) {
if (argc != 4) {
fprintf(stderr, "Usage: %s <public_key.pem> <input_file> <signature_file>\n", argv[0]);
return EXIT_FAILURE;
}
return verify_signature(argv[1], argv[2], argv[3]);
}
SM3
摘要计算
djy666@ubuntu:~/djy/sm3_openssl$ vim hmac.c
djy666@ubuntu:~/djy/sm3_openssl$ vim hash.c
djy666@ubuntu:~/djy/sm3_openssl$ gcc -o hash hash.c -lcrypto
djy666@ubuntu:~/djy/sm3_openssl$ ./hash
Usage: ./hash <string_to_hash>
djy666@ubuntu:~/djy/sm3_openssl$ ./hash "20221413djy"
SM3 hash: 96f664b88bf6c381bd9af7ceda65641db5b32253b268d1a697c67284b35eec02
代码
- digest.c
#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
void sm3_hash(const char* data) {
EVP_MD_CTX* mdctx;
const EVP_MD* md;
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len;
OpenSSL_add_all_digests();
md = EVP_get_digestbyname("sm3");
if (md == NULL) {
printf("Unknown message digest sm3\n");
return;
}
mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, data, strlen(data));
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
printf("SM3 hash: ");
for (int i = 0; i < md_len; i++) {
printf("%02x", md_value[i]);
}
printf("\n");
EVP_MD_CTX_free(mdctx);
EVP_cleanup();
}
int main(int argc, char* argv[]) {
if (argc < 2) {
printf("Usage: %s <string_to_hash>\n", argv[0]);
return 1;
}
sm3_hash(argv[1]);
return 0;
}
HMAC计算
djy666@ubuntu:~/djy/sm3_openssl$ vim hmac.c
djy666@ubuntu:~/djy/sm3_openssl$ gcc -o hmac hmac.c -lcrypto
djy666@ubuntu:~/djy/sm3_openssl$ ./hmac
Usage: ./hmac <key> <data>
djy666@ubuntu:~/djy/sm3_openssl$ ./hmac "1413" "dujiayan"
HMAC: 8ef98d45b1a83432d935be9d87d028376151f3360051f72b72b6cc5b64f29629
代码
- hmac.c
#include <stdio.h>
#include <openssl/evp.h>
#include <string.h>
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <key> <data>\n", argv[0]);
return 1;
}
unsigned char *key = (unsigned char *)argv[1];
unsigned char *data = (unsigned char *)argv[2];
size_t key_len = strlen((char *)key);
size_t data_len = strlen((char *)data);
EVP_MAC_CTX *ctx;
EVP_MAC *mac;
OSSL_PARAM params[2];
unsigned char *out;
size_t out_len;
mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
ctx = EVP_MAC_CTX_new(mac);
params[0] = OSSL_PARAM_construct_utf8_string("digest", "SM3", 0);
params[1] = OSSL_PARAM_construct_end();
if (!EVP_MAC_init(ctx, key, key_len, params)) {
fprintf(stderr, "Failed to initialize HMAC\n");
return 1;
}
if (!EVP_MAC_update(ctx, data, data_len)) {
fprintf(stderr, "Failed to update HMAC\n");
return 1;
}
EVP_MAC_final(ctx, NULL, &out_len, 0);
out = malloc(out_len);
if (!EVP_MAC_final(ctx, out, &out_len, out_len)) {
fprintf(stderr, "Failed to finalize HMAC\n");
return 1;
}
printf("HMAC: ");
for (size_t i = 0; i < out_len; i++) {
printf("%02x", out[i]);
}
printf("\n");
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
free(out);
return 0;
}
SM4
加密解密
djy666@ubuntu:~/djy/sm4_test$ vim plaint.txt
djy666@ubuntu:~/djy/sm4_test$ vim encrypt.c
djy666@ubuntu:~/djy/sm4_test$ gcc -o encrypt encrypt.c -lcrypto
djy666@ubuntu:~/djy/sm4_test$ touch encrypt.bin
djy666@ubuntu:~/djy/sm4_test$ ./encrypt
Usage: ./encrypt <key> <iv> <input file> <output file>
djy666@ubuntu:~/djy/sm4_test$ ./encrypt 1234567812345678 1111111111111111 plain.txt encrypt.bin
Encryption complete.
djy666@ubuntu:~/djy/sm4_test$ vim decrypt.c
djy666@ubuntu:~/djy/sm4_test$ vim decrypt_file
djy666@ubuntu:~/djy/sm4_test$ gcc -o decrypt decrypt.c -lcrypto
djy666@ubuntu:~/djy/sm4_test$ ./decrypt 1234567812345678 1111111111111111 encrypt.bin decrypt_file
Decryption complete.
git commit
djy666@ubuntu:~/djy/sm4_test$ git commit -m "sm4_test"
[master 1802d70] sm4_test
9 files changed, 132 insertions(+)
create mode 100755 sm4_test/decrypt
create mode 100644 sm4_test/decrypt.c
create mode 100644 sm4_test/decrypt_file
create mode 100755 sm4_test/encrypt
create mode 100644 sm4_test/encrypt.bin
create mode 100644 sm4_test/encrypt.c
create mode 100644 sm4_test/encrypt_file
create mode 100644 sm4_test/plain.txt
create mode 100644 sm4_test/plaint.txt
代码
- encrypt.c
#include <openssl/evp.h>
#include <stdio.h>
#include <stdlib.h>
void handleErrors(void) {
fprintf(stderr, "An error occurred.\n");
exit(1);
}
int main(int argc, char *argv[]) {
if (argc != 5) {
fprintf(stderr, "Usage: %s <key> <iv> <input file> <output file>\n", argv[0]);
return 1;
}
char *key = argv[1];
char *iv = argv[2];
char *input_file = argv[3];
char *output_file = argv[4];
FILE *f_input, *f_output;
unsigned char buffer[1024];
unsigned char ciphertext[1024 + EVP_MAX_BLOCK_LENGTH];
int bytes_read, ciphertext_len;
EVP_CIPHER_CTX *ctx;
// Initialise the library
if(!OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL))
handleErrors();
// Create and initialise the context
if(!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
// Initialise the encryption operation.
if(1 != EVP_EncryptInit_ex(ctx, EVP_sm4_cbc(), NULL, (unsigned char*)key, (unsigned char*)iv))
handleErrors();
// Open files
if(!(f_input = fopen(input_file, "rb"))) {
fprintf(stderr, "Could not open %s for reading\n", input_file);
return 1;
}
if(!(f_output = fopen(output_file, "wb"))) {
fprintf(stderr, "Could not open %s for writing\n", output_file);
return 1;
}
// Provide the message to be encrypted
while((bytes_read = fread(buffer, 1, 1024, f_input)) > 0) {
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &ciphertext_len, buffer, bytes_read))
handleErrors();
fwrite(ciphertext, 1, ciphertext_len, f_output);
}
// Finalise the encryption
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + ciphertext_len, &ciphertext_len))
handleErrors();
fwrite(ciphertext, 1, ciphertext_len, f_output);
// Clean up
EVP_CIPHER_CTX_free(ctx);
fclose(f_input);
fclose(f_output);
printf("Encryption complete.\n");
return 0;
}
- decrypt.c
#include <openssl/evp.h>
#include <stdio.h>
#include <stdlib.h>
void handleErrors(void) {
fprintf(stderr, "An error occurred.\n");
exit(1);
}
int main(int argc, char *argv[]) {
if (argc != 5) {
fprintf(stderr, "Usage: %s <key> <iv> <input file> <output file>\n", argv[0]);
return 1;
}
char *key = argv[1];
char *iv = argv[2];
char *input_file = argv[3];
char *output_file = argv[4];
FILE *f_input, *f_output;
unsigned char buffer[1024];
unsigned char plaintext[1024 + EVP_MAX_BLOCK_LENGTH];
int bytes_read, plaintext_len;
EVP_CIPHER_CTX *ctx;
// Initialise the library
if(!OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL))
handleErrors();
// Create and initialise the context
if(!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
// Initialise the decryption operation.
if(1 != EVP_DecryptInit_ex(ctx, EVP_sm4_cbc(), NULL, (unsigned char*)key, (unsigned char*)iv))
handleErrors();
// Open files
if(!(f_input = fopen(input_file, "rb"))) {
fprintf(stderr, "Could not open %s for reading\n", input_file);
return 1;
}
if(!(f_output = fopen(output_file, "wb"))) {
fprintf(stderr, "Could not open %s for writing\n", output_file);
return 1;
}
// Provide the message to be decrypted
while((bytes_read = fread(buffer, 1, 1024, f_input)) > 0) {
if(1 != EVP_DecryptUpdate(ctx, plaintext, &plaintext_len, buffer, bytes_read))
handleErrors();
fwrite(plaintext, 1, plaintext_len, f_output);
}
// Finalise the decryption
if(1 != EVP_DecryptFinal_ex(ctx, plaintext + plaintext_len, &plaintext_len))
handleErrors();
fwrite(plaintext, 1, plaintext_len, f_output);
// Clean up
EVP_CIPHER_CTX_free(ctx);
fclose(f_input);
fclose(f_output);
printf("Decryption complete.\n");
return 0;
}
2. 参考相关内容,在 Ubuntu或openEuler中(推荐 openEuler)中使用GmSSL库编程实现调用SM2(加密解密,签名验签),SM3(摘要计算,HMAC 计算),SM4(加密解密)算法,使用Markdown记录详细记录实践过程,每完成一项git commit 一次。(5’)
SM2
加密
djy666@ubuntu:~/djy/sm2_gmssl$ vim sm2_keygen.c
djy666@ubuntu:~/djy/sm2_gmssl$ gcc -o sm2_keygen sm2_keygen.c -lgmssl
djy666@ubuntu:~/djy/sm2_gmssl$ ./sm2_keygen
Usage: ./sm2_keygen <private_key_file> <public_key_file>
djy666@ubuntu:~/djy/sm2_gmssl$ ./sm2_keygen sm2_private_key.pem sm2_public_key.pem
SM2 key pair generated successfully.
djy666@ubuntu:~/djy/sm2_gmssl$ vim sm2_encrypt.c
djy666@ubuntu:~/djy/sm2_gmssl$ gcc -o sm2_encrypt sm2_encrypt.c -lgmssl
djy666@ubuntu:~/djy/sm2_gmssl$ ls
plain.txt sm2_encrypt sm2_encrypt.c sm2_keygen sm2_keygen.c sm2_private_key.pem sm2_public_key.pem
djy666@ubuntu:~/djy/sm2_gmssl$ ./sm2_encrypt
Usage: sm2_encrypt <public_key.pem> <input_file> <output_file>
djy666@ubuntu:~/djy/sm2_gmssl$ touch encrypt_file.bin
djy666@ubuntu:~/djy/sm2_gmssl$ ./sm2_encrypt sm2_public_key.pem plain.txt encrypt_file.bin
Encryption successful, output written to encrypt_file.bin
djy666@ubuntu:~/djy/sm2_gmssl$ vim encrypt_file.bin
代码
- keygen.c
#include <stdio.h>
#include <stdlib.h>
#include <gmssl/sm2.h>
#include <gmssl/error.h>
#include <gmssl/pem.h>
int main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <private_key_file> <public_key_file>\n", argv[0]);
return 1;
}
const char *private_key_file = argv[1];
const char *public_key_file = argv[2];
SM2_KEY sm2_key;
FILE *fp;
if (sm2_key_generate(&sm2_key) != 1) {
fprintf(stderr, "Failed to generate SM2 key pair.\n");
return 1;
}
if (!(fp = fopen(private_key_file, "wb"))) {
perror("Failed to open private key file");
return 1;
}
if (sm2_private_key_info_to_pem(&sm2_key, fp) != 1) {
fprintf(stderr, "Failed to write private key to file.\n");
fclose(fp);
return 1;
}
fclose(fp);
if (!(fp = fopen(public_key_file, "wb"))) {
perror("Failed to open public key file");
return 1;
}
if (sm2_public_key_info_to_pem(&sm2_key, fp) != 1) {
fprintf(stderr, "Failed to write public key to file.\n");
fclose(fp);
return 1;
}
fclose(fp);
printf("SM2 key pair generated successfully.\n");
return 0;
}
- sm2_encrypt.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/sm2.h>
#include <gmssl/pem.h>
#define SM2_CIPHERTEXT_SIZE 1024
void print_usage() {
printf("Usage: sm2_encrypt <public_key.pem> <input_file> <output_file>\n");
}
int main(int argc, char *argv[]) {
if (argc != 4) {
print_usage();
return 1;
}
const char *public_key_file = argv[1];
const char *input_file = argv[2];
const char *output_file = argv[3];
SM2_KEY sm2_key;
FILE *fp = fopen(public_key_file, "r");
if (!fp) {
perror("Failed to open public key file");
return 1;
}
if (sm2_public_key_info_from_pem(&sm2_key, fp) != 1) {
fprintf(stderr, "Failed to read public key from PEM\n");
fclose(fp);
return 1;
}
fclose(fp);
FILE *in_fp = fopen(input_file, "rb");
if (!in_fp) {
perror("Failed to open input file");
return 1;
}
fseek(in_fp, 0, SEEK_END);
long input_len = ftell(in_fp);
fseek(in_fp, 0, SEEK_SET);
unsigned char *input_data = malloc(input_len);
if (fread(input_data, 1, input_len, in_fp) != input_len) {
perror("Failed to read input file");
free(input_data);
fclose(in_fp);
return 1;
}
fclose(in_fp);
unsigned char ciphertext[SM2_CIPHERTEXT_SIZE];
size_t ciphertext_len = sizeof(ciphertext);
if (sm2_encrypt(&sm2_key, input_data, input_len, ciphertext, &ciphertext_len) != 1) {
fprintf(stderr, "SM2 encryption failed\n");
free(input_data);
return 1;
}
free(input_data);
FILE *out_fp = fopen(output_file, "wb");
if (!out_fp) {
perror("Failed to open output file");
return 1;
}
if (fwrite(ciphertext, 1, ciphertext_len, out_fp) != ciphertext_len) {
perror("Failed to write output file");
fclose(out_fp);
return 1;
}
fclose(out_fp);
printf("Encryption successful, output written to %s\n", output_file);
return 0;
}
解密
djy666@ubuntu:~/djy/sm2_gmssl$ vim sm2_decrypt.c
djy666@ubuntu:~/djy/sm2_gmssl$ rm sm2_decrypt.c
djy666@ubuntu:~/djy/sm2_gmssl$ vim sm2_decrypt.c
djy666@ubuntu:~/djy/sm2_gmssl$ rm sm2_decrypt.c
djy666@ubuntu:~/djy/sm2_gmssl$ vim sm2_decrypt.c
djy666@ubuntu:~/djy/sm2_gmssl$ gcc -o sm2_decrypt sm2_decrypt.c -lgmssl
djy666@ubuntu:~/djy/sm2_gmssl$ ls
encrypt_file.bin sm2_decrypt sm2_encrypt sm2_keygen sm2_private_key.pem
plain.txt sm2_decrypt.c sm2_encrypt.c sm2_keygen.c sm2_public_key.pem
djy666@ubuntu:~/djy/sm2_gmssl$ ./sm2_decrypt
Usage: sm2_decrypt <private_key.pem> <input_file> <output_file>
djy666@ubuntu:~/djy/sm2_gmssl$ touch decrypt_file.bin
djy666@ubuntu:~/djy/sm2_gmssl$ ./sm2_decrypt sm2_private_key.pem encrypt_file.bin decrypt_file.bin
/home/djy/GmSSL/src/asn1.c:1932:asn1_length_is_zero():
/home/djy/GmSSL/src/sm2_enc.c:517:sm2_decrypt():
SM2 decryption failed
djy666@ubuntu:~/djy/sm2_gmssl$ ./sm2_encrypt sm2_public_key.pem plain.txt encrypt_file.bin
Encryption successful, output written to encrypt_file.bin
djy666@ubuntu:~/djy/sm2_gmssl$ ./sm2_decrypt sm2_private_key.pem encrypt_file.bin decrypt_file.bin
Decryption successful, output written to decrypt_file.bin
djy666@ubuntu:~/djy/sm2_gmssl$ vim decrypt_file.bin
代码
- sm2_decrypt.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/sm2.h>
#include <gmssl/pem.h>
#define SM2_CIPHERTEXT_SIZE 1024
void print_usage() {
printf("Usage: sm2_decrypt <private_key.pem> <input_file> <output_file>\n");
}
int main(int argc, char *argv[]) {
if (argc != 4) {
print_usage();
return 1;
}
const char *private_key_file = argv[1];
const char *input_file = argv[2];
const char *output_file = argv[3];
SM2_KEY sm2_key;
FILE *fp = fopen(private_key_file, "r");
if (!fp) {
perror("Failed to open private key file");
return 1;
}
if (sm2_private_key_info_from_pem(&sm2_key, fp) != 1) {
fprintf(stderr, "Failed to read private key from PEM\n");
fclose(fp);
return 1;
}
fclose(fp);
FILE *in_fp = fopen(input_file, "rb");
if (!in_fp) {
perror("Failed to open input file");
return 1;
}
fseek(in_fp, 0, SEEK_END);
long input_len = ftell(in_fp);
fseek(in_fp, 0, SEEK_SET);
unsigned char *ciphertext = malloc(input_len);
if (fread(ciphertext, 1, input_len, in_fp) != input_len) {
perror("Failed to read input file");
free(ciphertext);
fclose(in_fp);
return 1;
}
fclose(in_fp);
unsigned char decrypted[SM2_CIPHERTEXT_SIZE];
size_t decrypted_len = sizeof(decrypted);
if (sm2_decrypt(&sm2_key, ciphertext, input_len, decrypted, &decrypted_len) != 1) {
fprintf(stderr, "SM2 decryption failed\n");
free(ciphertext);
return 1;
}
free(ciphertext);
FILE *out_fp = fopen(output_file, "wb");
if (!out_fp) {
perror("Failed to open output file");
return 1;
}
if (fwrite(decrypted, 1, decrypted_len, out_fp) != decrypted_len) {
perror("Failed to write output file");
fclose(out_fp);
return 1;
}
fclose(out_fp);
printf("Decryption successful, output written to %s\n", output_file);
return 0;
}
签名验签
djy666@ubuntu:~/djy/sm2_gmssl$ ls
decrypt_file.bin plain.txt sm2_decrypt.c sm2_encrypt.c sm2_keygen.c sm2_public_key.pem
encrypt_file.bin sm2_decrypt sm2_encrypt sm2_keygen sm2_private_key.pem sm2_sign.c
djy666@ubuntu:~/djy/sm2_gmssl$ vim sm2_sign.c
djy666@ubuntu:~/djy/sm2_gmssl$ gcc -o sm2_sign sm2_sign.c -lgmssl
djy666@ubuntu:~/djy/sm2_gmssl$ ./sm2_sign
Usage: ./sm2_sign <private_key.pem> <input.txt> <signature.sig>
djy666@ubuntu:~/djy/sm2_gmssl$ touch signature.sig
djy666@ubuntu:~/djy/sm2_gmssl$ ./sm2_sign sm2_private_key.pem plain.txt signature.sig
Signature generated and saved to signature.sig
djy666@ubuntu:~/djy/sm2_gmssl$ vim sm2_verify.c
djy666@ubuntu:~/djy/sm2_gmssl$ gcc -o sm2_verify sm2_verify.c -lgmssl
djy666@ubuntu:~/djy/sm2_gmssl$ ls
decrypt_file.bin signature.sig sm2_encrypt sm2_keygen.c sm2_sign sm2_verify.c
encrypt_file.bin sm2_decrypt sm2_encrypt.c sm2_private_key.pem sm2_sign.c
plain.txt sm2_decrypt.c sm2_keygen sm2_public_key.pem sm2_verify
djy666@ubuntu:~/djy/sm2_gmssl$ ./sm2_verify
Usage: ./sm2_verify <public key PEM file> <input file> <signature file>
djy666@ubuntu:~/djy/sm2_gmssl$ ./sm2_verify sm2_public_key.pem plain.txt signature.sig
Signature is valid.
git commit
djy666@ubuntu:~/djy/sm2_gmssl$ git add .
djy666@ubuntu:~/djy/sm2_gmssl$ git commit -m "sm2_sign & sm2_verify"
[master a18c4fd] sm2_sign & sm2_verify
5 files changed, 162 insertions(+)
create mode 100644 sm2_gmssl/signature.sig
create mode 100755 sm2_gmssl/sm2_sign
create mode 100644 sm2_gmssl/sm2_sign.c
create mode 100755 sm2_gmssl/sm2_verify
create mode 100644 sm2_gmssl/sm2_verify.c
代码
- sm2_sign.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/sm2.h>
#include <gmssl/pem.h>
#include <gmssl/error.h>
#include <gmssl/sm3.h>
int main(int argc, char **argv)
{
if (argc != 4) {
printf("Usage: %s <private_key.pem> <input.txt> <signature.sig>\n", argv[0]);
return 1;
}
const char *private_key_file = argv[1];
const char *input_file = argv[2];
const char *signature_file = argv[3];
SM2_KEY sm2_key;
FILE *key_fp = NULL;
FILE *input_fp = NULL;
FILE *sig_fp = NULL;
unsigned char dgst[32];
unsigned char sig[SM2_MAX_SIGNATURE_SIZE];
size_t siglen;
unsigned char buffer[1024];
size_t len;
key_fp = fopen(private_key_file, "r");
if (!key_fp) {
perror("Failed to open private key file");
return 1;
}
if (sm2_private_key_info_from_pem(&sm2_key, key_fp) != 1) {
fprintf(stderr, "Failed to read private key from PEM\n");
fclose(key_fp);
return 1;
}
fclose(key_fp);
input_fp = fopen(input_file, "r");
if (!input_fp) {
fprintf(stderr, "Error opening input file: %s\n", input_file);
return 1;
}
SM3_CTX sm3_ctx;
sm3_init(&sm3_ctx);
while ((len = fread(buffer, 1, sizeof(buffer), input_fp)) > 0) {
sm3_update(&sm3_ctx, buffer, len);
}
fclose(input_fp);
sm3_finish(&sm3_ctx, dgst);
siglen = sizeof(sig);
if (sm2_sign(&sm2_key, dgst, sig, &siglen) != 1) {
fprintf(stderr, "Error generating SM2 signature\n");
return 1;
}
sig_fp = fopen(signature_file, "wb");
if (!sig_fp) {
fprintf(stderr, "Error opening signature file: %s\n", signature_file);
return 1;
}
if (fwrite(sig, 1, siglen, sig_fp) != siglen) {
fprintf(stderr, "Error writing signature to file: %s\n", signature_file);
fclose(sig_fp);
return 1;
}
fclose(sig_fp);
printf("Signature generated and saved to %s\n", signature_file);
return 0;
}
- sm2_verify.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/sm2.h>
#include <gmssl/sm3.h>
#include <gmssl/pem.h>
#include <gmssl/error.h>
int main(int argc, char **argv) {
if (argc != 4) {
fprintf(stderr, "Usage: %s <public key PEM file> <input file> <signature file>\n", argv[0]);
return 1;
}
const char *pubkey_filename = argv[1];
const char *input_filename = argv[2];
const char *signature_filename = argv[3];
SM2_KEY key;
FILE *fp;
SM3_CTX sm3_ctx;
uint8_t dgst[32];
if (!(fp = fopen(pubkey_filename, "r"))) {
perror("Error opening public key file");
return 1;
}
if (!sm2_public_key_info_from_pem(&key, fp)) {
fprintf(stderr, "Error reading public key from PEM file %s\n", pubkey_filename);
fclose(fp);
return 1;
}
fclose(fp);
if (!(fp = fopen(input_filename, "rb"))) {
perror("Error opening input file");
return 1;
}
sm3_init(&sm3_ctx);
unsigned char buf[1024];
size_t len;
while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) {
sm3_update(&sm3_ctx, buf, len);
}
if (ferror(fp)) {
fprintf(stderr, "Error reading input file %s\n", input_filename);
fclose(fp);
return 1;
}
sm3_finish(&sm3_ctx, dgst);
fclose(fp);
unsigned char signature[256];
size_t siglen;
if (!(fp = fopen(signature_filename, "rb"))) {
perror("Error opening signature file");
return 1;
}
siglen = fread(signature, 1, sizeof(signature), fp);
if (ferror(fp)) {
fprintf(stderr, "Error reading signature file %s\n", signature_filename);
fclose(fp);
return 1;
}
fclose(fp);
if (siglen == 0) {
fprintf(stderr, "Signature file %s is empty or could not be read.\n", signature_filename);
return 1;
}
int verify_result = sm2_verify(&key, dgst, signature, siglen);
if (verify_result == 1) {
printf("Signature is valid.\n");
} else {
fprintf(stderr, "Signature is invalid. Please check the public key, input file, and signature file.\n");
return 1;
}
return 0;
}
SM3
摘要
djy666@ubuntu:~/djy/sm3_gmssl$ vim plain.txt
djy666@ubuntu:~/djy/sm3_gmssl$ vim sm3_hash.c
djy666@ubuntu:~/djy/sm3_gmssl$ ls
plain.txt sm3_hash.c
djy666@ubuntu:~/djy/sm3_gmssl$ gcc -o sm3_hash sm3_hash.c -lgmssl
djy666@ubuntu:~/djy/sm3_gmssl$ ./sm3_hash
Usage: sm3_digest <input_file> <output_file>
djy666@ubuntu:~/djy/sm3_gmssl$ touch hash.bin
djy666@ubuntu:~/djy/sm3_gmssl$ ./sm3_hash plain.txt hash.bin
SM3 digest computed and written to hash.bin
git commit
djy666@ubuntu:~/djy/sm3_gmssl$ git add .
djy666@ubuntu:~/djy/sm3_gmssl$ git commit -m "sm3_hash"
[master df327da] sm3_hash
4 files changed, 66 insertions(+)
create mode 100644 sm3_gmssl/hash.bin
create mode 100644 sm3_gmssl/plain.txt
create mode 100755 sm3_gmssl/sm3_hash
create mode 100644 sm3_gmssl/sm3_hash.c
代码
- sm3_hash.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/sm3.h>
#define SM3_DIGEST_LENGTH 32
void print_usage() {
fprintf(stderr, "Usage: sm3_digest <input_file> <output_file>\n");
}
int main(int argc, char *argv[]) {
if (argc != 3) {
print_usage();
return EXIT_FAILURE;
}
const char *input_file = argv[1];
const char *output_file = argv[2];
FILE *fp_input = fopen(input_file, "rb");
if (!fp_input) {
perror("Error opening input file");
return EXIT_FAILURE;
}
unsigned char buffer[1024];
size_t bytes_read;
SM3_CTX ctx;
unsigned char digest[SM3_DIGEST_LENGTH];
sm3_init(&ctx);
while ((bytes_read = fread(buffer, 1, sizeof(buffer), fp_input)) > 0) {
sm3_update(&ctx, buffer, bytes_read);
}
if (ferror(fp_input)) {
perror("Error reading input file");
fclose(fp_input);
return EXIT_FAILURE;
}
sm3_finish(&ctx, digest);
fclose(fp_input);
FILE *fp_output = fopen(output_file, "wb");
if (!fp_output) {
perror("Error opening output file");
return EXIT_FAILURE;
}
if (fwrite(digest, 1, sizeof(digest), fp_output) != sizeof(digest)) {
perror("Error writing output file");
fclose(fp_output);
return EXIT_FAILURE;
}
fclose(fp_output);
printf("SM3 digest computed and written to %s\n", output_file);
return EXIT_SUCCESS;
}
HMAC
djy666@ubuntu:~/djy/sm3_gmssl$ vim sm3_hmac.c
djy666@ubuntu:~/djy/sm3_gmssl$ gcc -o sm3_hmac sm3_hmac.c -lgmssl
djy666@ubuntu:~/djy/sm3_gmssl$ ./sm3_hmac
Usage: ./sm3_hmac <key_hex> <input_string>
djy666@ubuntu:~/djy/sm3_gmssl$ ./sm3_hmac "0123456789abcdef0123456789abcdef" "HelloWorld"
HMAC-SM3 result: 8aa2abfb3b902b1693e5af68821cade9ed6f3011d4e52e31f511e9bc57594dd5
git commit
djy666@ubuntu:~/djy/sm3_gmssl$ git add .
djy666@ubuntu:~/djy/sm3_gmssl$ git commit -m "hmac"
[master e9e03aa] hmac
2 files changed, 38 insertions(+)
create mode 100755 sm3_gmssl/sm3_hmac
create mode 100644 sm3_gmssl/sm3_hmac.c
代码
- sm3_hmac.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HMAC_COMMAND_FORMAT "gmssl sm3hmac -key %s -in_str %s"
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <key_hex> <input_string>\n", argv[0]);
return EXIT_FAILURE;
}
const char *key_hex = argv[1];
const char *input_string = argv[2];
char command[512];
snprintf(command, sizeof(command), HMAC_COMMAND_FORMAT, key_hex, input_string);
FILE *fp = popen(command, "r");
if (fp == NULL) {
perror("popen failed");
return EXIT_FAILURE;
}
char buffer[128];
printf("HMAC-SM3 result: ");
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf("%s", buffer);
}
if (pclose(fp) == -1) {
perror("pclose failed");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
SM4
加密
djy666@ubuntu:~/djy/sm4_gmssl$ mv sm4_encrypt.c sm4_keygen.c
djy666@ubuntu:~/djy/sm4_gmssl$ gcc -o sm4_keygen sm4_keygen.c -lgmssl
djy666@ubuntu:~/djy/sm4_gmssl$ ls
sm4_keygen sm4_keygen.c
djy666@ubuntu:~/djy/sm4_gmssl$ ./sm4_keygen
Usage: ./sm4_keygen <output_filename>
djy666@ubuntu:~/djy/sm4_gmssl$ ./sm4_keygen sm4_key.pem
Key generated and saved to sm4_key.pem
djy666@ubuntu:~/djy/sm4_gmssl$ vim sm4_encrypt.c
djy666@ubuntu:~/djy/sm4_gmssl$ ls
sm4_encrypt.c sm4_key.pem sm4_keygen sm4_keygen.c
djy666@ubuntu:~/djy/sm4_gmssl$ gcc -o sm4_encrypt sm4_encrypt.c -lgmssl
djy666@ubuntu:~/djy/sm4_gmssl$ ls
sm4_encrypt sm4_encrypt.c sm4_key.pem sm4_keygen sm4_keygen.c
djy666@ubuntu:~/djy/sm4_gmssl$ vim plain.txt
djy666@ubuntu:~/djy/sm4_gmssl$ ls
plain.txt sm4_encrypt sm4_encrypt.c sm4_key.pem sm4_keygen sm4_keygen.c
djy666@ubuntu:~/djy/sm4_gmssl$ ./sm4_encrypt
Usage: ./sm4_encrypt <key_file> <input_file> <output_file>
djy666@ubuntu:~/djy/sm4_gmssl$ touch encry_file.bin
djy666@ubuntu:~/djy/sm4_gmssl$ ./sm4_encrypt sm4_key.pem plain.txt encry_file.bin
Encryption completed successfully.
代码
- sm4_keygen.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/sm4.h>
#include <gmssl/rand.h>
void generate_key(const char *filename) {
unsigned char key[16];
FILE *file;
if (rand_bytes(key, sizeof(key)) != 1) {
fprintf(stderr, "Error generating random bytes for the key.\n");
exit(EXIT_FAILURE);
}
file = fopen(filename, "wb");
if (!file) {
fprintf(stderr, "Error opening file %s for writing.\n", filename);
exit(EXIT_FAILURE);
}
size_t written = fwrite(key, sizeof(unsigned char), sizeof(key), file);
if (written != sizeof(key)) {
fprintf(stderr, "Error writing key to file.\n");
fclose(file);
exit(EXIT_FAILURE);
}
fclose(file);
printf("Key generated and saved to %s\n", filename);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <output_filename>\n", argv[0]);
return EXIT_FAILURE;
}
generate_key(argv[1]);
return EXIT_SUCCESS;
}
- sm4_encrypt.c
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "gmssl/sm4.h"
void handleErrors(const char *message);
void sm4_encrypt_file(const char *key_file, const char *input_file, const char *output_file);
int main(int argc, char *argv[]) {
if (argc != 4) {
fprintf(stderr, "Usage: %s <key_file> <input_file> <output_file>\n", argv[0]);
return EXIT_FAILURE;
}
sm4_encrypt_file(argv[1], argv[2], argv[3]);
return EXIT_SUCCESS;
}
void sm4_encrypt_file(const char *key_file, const char *input_file, const char *output_file) {
FILE *kf, *inf, *outf;
SM4_KEY sm4_key;
uint8_t key[SM4_KEY_SIZE];
uint8_t input[SM4_BLOCK_SIZE];
uint8_t output[SM4_BLOCK_SIZE];
size_t bytes_read;
kf = fopen(key_file, "rb");
if (!kf) {
handleErrors("Failed to open key file");
}
if (fread(key, 1, SM4_KEY_SIZE, kf) != SM4_KEY_SIZE) {
fclose(kf);
handleErrors("Failed to read key from file");
}
fclose(kf);
sm4_set_encrypt_key(&sm4_key, key);
inf = fopen(input_file, "rb");
if (!inf) {
handleErrors("Failed to open input file");
}
outf = fopen(output_file, "wb");
if (!outf) {
fclose(inf);
handleErrors("Failed to open output file");
}
while ((bytes_read = fread(input, 1, SM4_BLOCK_SIZE, inf)) > 0) {
if (bytes_read < SM4_BLOCK_SIZE) {
memset(input + bytes_read, 0, SM4_BLOCK_SIZE - bytes_read);
}
sm4_encrypt(&sm4_key, input, output);
fwrite(output, 1, SM4_BLOCK_SIZE, outf);
}
fclose(inf);
fclose(outf);
printf("Encryption completed successfully.\n");
}
void handleErrors(const char *message) {
fprintf(stderr, "Error: %s\n", message);
exit(EXIT_FAILURE);
}
解密
djy666@ubuntu:~/djy/sm4_gmssl$ gcc -o sm4_decrypt sm4_decrypt.c -lgmssl
djy666@ubuntu:~/djy/sm4_gmssl$ ls
encry_file.bin sm4_decrypt sm4_encrypt sm4_key.pem sm4_keygen.c
plain.txt sm4_decrypt.c sm4_encrypt.c sm4_keygen
djy666@ubuntu:~/djy/sm4_gmssl$ touch decrypt_file.bin
djy666@ubuntu:~/djy/sm4_gmssl$ ./sm4_decrypt
Usage: ./sm4_decrypt <key_file> <input_file> <output_file>
djy666@ubuntu:~/djy/sm4_gmssl$ ./sm4_decrypt sm4_key.pem encry_file.bin decrypt_file.bin
Decryption completed successfully.
djy666@ubuntu:~/djy/sm4_gmssl$ cat decrypt_file.bin
20221413djy
git commit
djy666@ubuntu:~/djy/sm4_gmssl$ git add .
djy666@ubuntu:~/djy/sm4_gmssl$ git commit -m "sm4_encrypt & sm4_decrypt"
[master e4c3218] sm4_encrypt & sm4_decrypt
10 files changed, 183 insertions(+)
create mode 100644 sm4_gmssl/decrypt_file.bin
create mode 100644 sm4_gmssl/encry_file.bin
create mode 100644 sm4_gmssl/plain.txt
create mode 100755 sm4_gmssl/sm4_decrypt
create mode 100644 sm4_gmssl/sm4_decrypt.c
create mode 100755 sm4_gmssl/sm4_encrypt
create mode 100644 sm4_gmssl/sm4_encrypt.c
create mode 100644 sm4_gmssl/sm4_key.pem
create mode 100755 sm4_gmssl/sm4_keygen
create mode 100644 sm4_gmssl/sm4_keygen.c
代码
- sm4_decrypt.c
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "gmssl/sm4.h"
void handleErrors(const char *message);
void sm4_decrypt_file(const char *key_file, const char *input_file, const char *output_file);
int main(int argc, char *argv[]) {
if (argc != 4) {
fprintf(stderr, "Usage: %s <key_file> <input_file> <output_file>\n", argv[0]);
return EXIT_FAILURE;
}
sm4_decrypt_file(argv[1], argv[2], argv[3]);
return EXIT_SUCCESS;
}
void sm4_decrypt_file(const char *key_file, const char *input_file, const char *output_file) {
FILE *kf, *inf, *outf;
SM4_KEY sm4_key;
uint8_t key[SM4_KEY_SIZE];
uint8_t input[SM4_BLOCK_SIZE];
uint8_t output[SM4_BLOCK_SIZE];
size_t bytes_read;
kf = fopen(key_file, "rb");
if (!kf) {
handleErrors("Failed to open key file");
}
if (fread(key, 1, SM4_KEY_SIZE, kf) != SM4_KEY_SIZE) {
fclose(kf);
handleErrors("Failed to read key from file");
}
fclose(kf);
sm4_set_decrypt_key(&sm4_key, key);
inf = fopen(input_file, "rb");
if (!inf) {
handleErrors("Failed to open input file");
}
outf = fopen(output_file, "wb");
if (!outf) {
fclose(inf);
handleErrors("Failed to open output file");
}
while ((bytes_read = fread(input, 1, SM4_BLOCK_SIZE, inf)) > 0) {
sm4_encrypt(&sm4_key, input, output);
fwrite(output, 1, SM4_BLOCK_SIZE, outf);
}
fclose(inf);
fclose(outf);
printf("Decryption completed successfully.\n");
}
void handleErrors(const char *message) {
fprintf(stderr, "Error: %s\n", message);
exit(EXIT_FAILURE);
}
3. 两人一组,在 Ubuntu或openEuler中(推荐 openEuler)中使用OpenSSL编程实现带签名的数字信封协议。使用OpenSSL库时,Alice发送,Bob接收。Ailice,Bob在实验中要替换为自己的8位学号+姓名。 使用Markdown记录详细记录实践过程,每完成一项git commit 一次。(5分)
- Alice,Bob生成自己的公私钥匙对,记作:(PKa,SKa),(PKb,SKb),Alice,Bob分别拥有:(PKa,SKa,PKb),(PKb,SKb,PKa),实验中把公钥文件拷贝给对方
- Alice发给Bob的明文plain.txt,内容为自己的姓名学号
- Alice:sm4 key使用gmssl rand 产生,16字节,记作k
- Alice:Sm4Enc(k,P) = C
- Alice:Sm2Enc(PKb,k) = KC
- Alice:Sm2Sign(SKa,C)= S1
- Alice: 数字信封 C||KC||S1 发给Bob
- Bob:Sm2Very(PKa,S1)
- Bob:Sm2Dec(SKb,KC)= k
- Bob:Sm4Dec(k,C)= P
交换密钥
djy666@ubuntu:~/djy/email$ ./sm2_keygen bob_private.pem bob_public.pem
SM2 key pair generated successfully.
djy666@ubuntu:~/djy/email$ cp ./bob_public.pem /mnt/c/1020
djy666@ubuntu:~/djy/email$ ls
bob_private.pem encrypt_file.bin sm2_decrypt sm2_encrypt.c sm2_private_key.pem sm2_sign.c
bob_public.pem plain.txt sm2_decrypt.c sm2_keygen sm2_public_key.pem sm2_verify
decrypt_file.bin signature.sig sm2_encrypt sm2_keygen.c sm2_sign sm2_verify.c
djy666@ubuntu:~/djy/email$ cp /mnt/c/1020/alice_pub.pem ./
djy666@ubuntu:~/djy/email$ ls
alice_pub.pem decrypt_file.bin signature.sig sm2_encrypt sm2_keygen.c sm2_sign sm2_verify.c
bob_private.pem encrypt_file.bin sm2_decrypt sm2_encrypt.c sm2_private_key.pem sm2_sign.c
bob_public.pem plain.txt sm2_decrypt.c sm2_keygen sm2_public_key.pem sm2_verify
djy666@ubuntu:~/djy/email$ cat alice_pub.pem
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEuY8HKqctI6rfYtqEy/6dhxaHk0GZ
EJJayFj2dNehonL3tkzFi8ADsV4vpwGG+whXz+ZRUfxyetnxQkWtqsrQbA==
-----END PUBLIC KEY-----
git commit
djy666@ubuntu:~/djy/email$ git add .
djy666@ubuntu:~/djy/email$ git commit -m "keyburn & changepublickey"
[master 9e03dcd] keyburn & changepublickey
20 files changed, 399 insertions(+)
create mode 100644 email/.swp
create mode 100755 email/alice_pub.pem
create mode 100644 email/bob_private.pem
create mode 100644 email/bob_public.pem
create mode 100644 email/decrypt_file.bin
create mode 100644 email/encrypt_file.bin
create mode 100644 email/plain.txt
create mode 100644 email/signature.sig
create mode 100755 email/sm2_decrypt
create mode 100644 email/sm2_decrypt.c
create mode 100755 email/sm2_encrypt
create mode 100644 email/sm2_encrypt.c
create mode 100755 email/sm2_keygen
create mode 100644 email/sm2_keygen.c
create mode 100644 email/sm2_private_key.pem
create mode 100644 email/sm2_public_key.pem
create mode 100755 email/sm2_sign
create mode 100644 email/sm2_sign.c
create mode 100755 email/sm2_verify
create mode 100644 email/sm2_verify.c
验签
djy666@ubuntu:~/djy/email$ cp /mnt/c/1020/* ./
djy666@ubuntu:~/djy/email$ ls
alice_pub.pem encrypt_file.bin signature.sig sm2_encrypt sm2_private_key.pem sm2_verify
bob_private.pem encrypted_plain.bin signed_encrypted_plain.sig sm2_encrypt.c sm2_public_key.pem sm2_verify.c
bob_public.pem encrypted_sm4_key.bin sm2_decrypt sm2_keygen sm2_sign
decrypt_file.bin plain.txt sm2_decrypt.c sm2_keygen.c sm2_sign.c
djy666@ubuntu:~/djy/email$ ./sm2_verify alice_pub.pem signed_encrypted_plain.sig
Usage: ./sm2_verify <public key PEM file> <input file> <signature file>
djy666@ubuntu:~/djy/email$ ./sm2_verify alice_pub.pem encrypted_plain.bin signed_encrypted_plain.sig
Signature is valid.
git commit
djy666@ubuntu:~/djy/email$ git add .
djy666@ubuntu:~/djy/email$ git commit -m "verify"
[master 0ee9d8b] verify
3 files changed, 2 insertions(+)
create mode 100755 email/encrypted_plain.bin
create mode 100755 email/encrypted_sm4_key.bin
create mode 100755 email/signed_encrypted_plain.sig
解密SM4密钥
djy666@ubuntu:~/djy/email$ touch decrypted_key.bin
djy666@ubuntu:~/djy/email$ ./sm2_decrypt bob_private.pem encrypted_sm4_key.bin decrypted_key.bin
/home/djy/GmSSL/src/sm2_enc.c:517:sm2_decrypt():
SM2 decryption failed
djy666@ubuntu:~/djy/email$ cp /mnt/c/1020/encrypted_sm4_key.bin ./
djy666@ubuntu:~/djy/email$ ls
alice_pub.pem decrypted_key.bin plain.txt sm2_decrypt.c sm2_keygen.c sm2_sign.c
bob_private.pem encrypt_file.bin signature.sig sm2_encrypt sm2_private_key.pem sm2_verify
bob_public.pem encrypted_plain.bin signed_encrypted_plain.sig sm2_encrypt.c sm2_public_key.pem sm2_verify.c
decrypt_file.bin encrypted_sm4_key.bin sm2_decrypt sm2_keygen sm2_sign
djy666@ubuntu:~/djy/email$ ./sm2_decrypt bob_private.pem encrypted_sm4_key.bin decrypted_key.bin
Decryption successful, output written to decrypted_key.bin
djy666@ubuntu:~/djy/email$ hexdump decrypt_key.bin
hexdump: decrypt_key.bin: No such file or directory
hexdump: all input file arguments failed
djy666@ubuntu:~/djy/email$ hexdump decrypted_key.bin
0000000 d68d 774e 764a 008e 1893 a6ca 8fc0 27d8
0000010
解密明文
djy666@ubuntu:~/djy/email$ vim sm4_decrypt.c
djy666@ubuntu:~/djy/email$ gcc -o sm4_decrypt sm4_decrypt.c -lgmssl
djy666@ubuntu:~/djy/email$ ./sm4_decrypt decrypted_key.bin encrypted_plain.bin output.txt
Decryption completed successfully.
djy666@ubuntu:~/djy/email$ cat output.txt
20221413djy&20221422glx
git commit
djy666@ubuntu:~/djy/email$ git add .
djy666@ubuntu:~/djy/email$ git commit -m "sm4_decrypted"
[master 3fd84d2] sm4_decrypted
3 files changed, 65 insertions(+)
create mode 100644 email/output.txt
create mode 100755 email/sm4_decrypt
create mode 100644 email/sm4_decrypt.c