SM2
1 在 Ubuntu 或 openEuler 中完成任务(推荐openEuler)
2 生成一个文档 sn.txt,内容为全班同学的 8 位学号,把你的学号排到第一个
echo -e “20221327\n$(seq -f “202213%02g” 1 29 | grep -v 20221327 | paste -sd ‘\n’ -)” > sn.txt
3 使用 GmSSL 命令产生一对公私钥对。(4 分)
gmssl genrsa -out private_key.pem 2048
gmssl rsa -in private_key.pem -pubout -out public_key.pem
4 使用 GmSSL 编程对sn.txt进行加密解密,提交代码或代码链接,以及编译运行过程(文本或截图)(10 分)
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <stdio.h>
#include <stdlib.h>
void handleErrors() {
ERR_print_errors_fp(stderr);
abort();
}
int main() {
FILE *fp;
RSA *rsa = NULL;
unsigned char *encrypted = NULL;
unsigned char *decrypted = NULL;
int encrypted_len, decrypted_len;
// 读取公钥
fp = fopen(“public_key.pem”, “rb”);
rsa = RSA_new();
rsa = PEM_read_RSA_PUBKEY(fp, &rsa, NULL, NULL);
fclose(fp);
// 读取要加密的数据
FILE *file = fopen(“sn.txt”, “rb”);
fseek(file, 0, SEEK_END);
long numbytes = ftell(file);
fseek(file, 0, SEEK_SET);
unsigned char *data = malloc(numbytes);
fread(data, 1, numbytes, file);
fclose(file);
// 加密
encrypted_len = RSA_public_encrypt(numbytes, data, encrypted, rsa, RSA_PKCS1_OAEP_PADDING);
if (encrypted_len == -1) handleErrors();
// 保存加密数据
FILE *encrypted_file = fopen(“encrypted.txt”, “wb”);
fwrite(encrypted, 1, encrypted_len, encrypted_file);
fclose(encrypted_file);
// 读取私钥
fp = fopen(“private_key.pem”, “rb”);
rsa = PEM_read_RSA_PEM(fp, &rsa, NULL, NULL);
fclose(fp);
// 分配内存以保存解密数据
decrypted = malloc(numbytes);
// 读取加密数据
file = fopen(“encrypted.txt”, “rb”);
fseek(file, 0, SEEK_END);
numbytes = ftell(file);
fseek(file, 0, SEEK_SET);
encrypted = malloc(numbytes);
fread(encrypted, 1, numbytes, file);
fclose(file);
// 解密
decrypted_len = RSA_private_decrypt(numbytes, encrypted, decrypted, rsa, RSA_PKCS1_OAEP_PADDING);
if (decrypted_len == -1) handleErrors();
// 保存解密数据
FILE *decrypted_file = fopen(“decrypted.txt”, “wb”);
fwrite(decrypted, 1, decrypted_len, decrypted_file);
fclose(decrypted_file);
// 清理
free(data);
free(encrypted);
free(decrypted);
RSA_free(rsa);
return 0;
}
编译和运行
lzj@lzj-VirtualBox: ~$ gcc -o encrypt_decrypt encrypt_decrypt.c -lssl -lcrypto
lzj@lzj-VirtualBox: ./encrypt_decrypt
5 使用 GmSSL 编程对sn.txt进行签名验签,提交代码或代码链接,以及编译运行过程(文本或截图)(10 分)
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <stdio.h>
#include <stdlib.h>
void handleErrors() {
ERR_print_errors_fp(stderr);
abort();
}
int main() {
FILE *fp;
RSA *rsa = NULL;
unsigned char *signature = NULL;
unsigned char *data = NULL;
int signature_len, data_len;
// 读取私钥
fp = fopen(“private_key.pem”, “rb”);
rsa = PEM_read_RSA_PEM(fp, &rsa, NULL, NULL);
fclose(fp);
// 读取要签名的数据
FILE *file = fopen(“sn.txt”, “rb”);
fseek(file, 0, SEEK_END);
data_len = ftell(file);
fseek(file, 0, SEEK_SET);
data = malloc(data_len);
fread(data, 1, data_len, file);
fclose(file);
// 签名
signature_len = RSA_sign(NID_sha256, data, data_len, NULL, NULL, rsa);
signature = malloc(signature_len);
RSA_sign(NID_sha256, data, data_len, signature, &signature_len, rsa);
// 保存签名
FILE *signature_file = fopen(“signature.txt”, “wb”);
fwrite(signature, 1, signature_len, signature_file);
fclose(signature_file);
// 读取公钥
fp = fopen(“public_key.pem”, “rb”);
rsa = PEM_read_RSA_PUBKEY(fp, &rsa, NULL, NULL);
fclose(fp);
// 读取签名
file = fopen(“signature.txt”, “rb”);
fseek(file, 0, SEEK_END);
signature_len = ftell(file);
fseek(file, 0, SEEK_SET);
signature = malloc(signature_len);
fread(signature, 1, signature_len, file);
fclose(file);
// 验证签名
int result = RSA_verify(NID_sha256, data, data_len, signature, signature_len, rsa);
if (result == 1) {
printf(“Signature verified successfully.\n”);
} else {
printf(“Signature verification failed.\n”);
}
// 清理
free(data);
free(signature);
RSA_free(rsa);
return 0;
}
编译和运行
lzj@lzj-VirtualBox: gcc -o sign_verify sign_verify.c -lssl -lcrypto
lzj@lzj-VirtualBox: ./sign_verify