SM2算法测试

1 在 Ubuntu 或 openEuler 中完成任务(推荐openEuler)
2 生成一个文档 sn.txt,内容为全班同学的 8 位学号,把你的学号排到第一个
3 使用 GmSSL 命令产生一对公私钥对。(4 分)
4 使用 GmSSL 编程对sn.txt进行加密解密,提交代码或代码链接,以及编译运行过程(文本或截图)(10 分)
5 使用 GmSSL 编程对sn.txt进行签名验签,提交代码或代码链接,以及编译运行过程(文本或截图)(10 分)

生成sn.txt

在这里插入图片描述

使用 GmSSL 命令产生一对公私钥对

在这里插入图片描述

加密
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ vim sm2_keygen.c
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ gcc -o sm2_keygen sm2_keygen.c -lgmssl
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ ./sm2_keygen
Usage: ./sm2_keygen <private_key_file> <public_key_file>
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ ./sm2_keygen sm2_private_key.pem sm2_public_key.pem
SM2 key pair generated successfully.
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ vim sm2_encrypt.c
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ gcc -o sm2_encrypt sm2_encrypt.c -lgmssl
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ ls
sn.txt  sm2_encrypt  sm2_encrypt.c  sm2_keygen  sm2_keygen.c  sm2_private_key.pem  sm2_public_key.pem
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ ./sm2_encrypt
Usage: sm2_encrypt <public_key.pem> <input_file> <output_file>
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ touch encrypt_file.bin
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ ./sm2_encrypt sm2_public_key.pem sn.txt encrypt_file.bin
Encryption successful, output written to encrypt_file.bin
dujiayan@dujiayan-VMware-Virtual-Platform:~/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;
}
解密
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ vim sm2_decrypt.c
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ gcc -o sm2_decrypt sm2_decrypt.c -lgmssl
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ ls
encrypt_file.bin  sm2_decrypt    sm2_encrypt    sm2_keygen    sm2_private_key.pem
sn.txt         sm2_decrypt.c  sm2_encrypt.c  sm2_keygen.c  sm2_public_key.pem
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ ./sm2_decrypt
Usage: sm2_decrypt <private_key.pem> <input_file> <output_file>
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ touch decrypt_file.bin
dujiayan@dujiayan-VMware-Virtual-Platform:~/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
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ ./sm2_encrypt sm2_public_key.pem sn.txt encrypt_file.bin
Encryption successful, output written to encrypt_file.bin
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ ./sm2_decrypt sm2_private_key.pem encrypt_file.bin decrypt_file.bin
Decryption successful, output written to decrypt_file.bin
dujiayan@dujiayan-VMware-Virtual-Platform:~/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;
}
签名验签
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ ls
decrypt_file.bin  sn.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
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ vim sm2_sign.c
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ gcc -o sm2_sign sm2_sign.c -lgmssl
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ ./sm2_sign
Usage: ./sm2_sign <private_key.pem> <input.txt> <signature.sig>
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ touch signature.sig
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ ./sm2_sign sm2_private_key.pem sn.txt signature.sig
Signature generated and saved to signature.sig
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ vim sm2_verify.c
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ gcc -o sm2_verify sm2_verify.c -lgmssl
dujiayan@dujiayan-VMware-Virtual-Platform:~/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
sn.txt         sm2_decrypt.c  sm2_keygen     sm2_public_key.pem   sm2_verify
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ ./sm2_verify
Usage: ./sm2_verify <public key PEM file> <input file> <signature file>
dujiayan@dujiayan-VMware-Virtual-Platform:~/sm2_gmssl$ ./sm2_verify sm2_public_key.pem sn.txt signature.sig
Signature is valid.

代码

  • 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;
}
Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐