铜锁探“密”训练营实验手册
铜锁探“密”活动由开放原子开源基金会和铜锁社区共同举办,包含5次课程,以“抽丝剥茧,循序渐进,一起揭开商用密码的面纱”为主题,旨在让参与者更加深入地了解商用密码的原理和应用方法。 录播链接如下:
- 商用密码介绍和铜锁密码库入门,https://live.csdn.net/room/csdnnews/NJPxluNk
- 常用国密算法编程入门与实战,https://live.csdn.net/room/csdnnews/hZel8pLF
- 实战国密证书和国密传输协议,https://live.csdn.net/room/csdnnews/8fs5oVfT
- 实战铜锁国密应用和结营作业说明,https://live.csdn.net/room/csdnnews/BzeD1mGt
- 训练营结营&作品点评,https://live.csdn.net/room/csdnnews/fsZDshwb
实验环境说明
实验手册中大部分实验以docker环境为主,基于Ubuntu 20.04容器镜像。或者直接运行于Ubuntu 20.04操作系统或虚拟机也可以。比如电脑使用的Windows系统,可以通过安装Docker环境、Linux虚拟机、或者Linux子系统进行实验。其他Linux系统或者macOS系统可以参考本实验内容。
安装docker:
可以参考docker官方安装教程,详见https://docs.docker.com/engine/install/。
创建docker容器:
docker run -d -it --name tongsuolab ubuntu:20.04 bash
执行所有实验,都需要先进入docker容器。进入docker容器:
docker exec -it tongsuolab bash
其他软件,直接在操作系统上安装即可。
- 支持国密协议的浏览器,比如360企业安全浏览器。
- Wireshark,用于抓包分析国密协议。
构建铜锁密码库
基于铜锁密码库源代码进行构建和安装。代码下载地址:
AtomGit地址(推荐):https://atomgit.com/tongsuo/Tongsuo
GitHub地址:https://github.com/Tongsuo-Project/Tongsuo
下载代码需要使用git工具;构建铜锁密码库需要使用perl、gcc、make等基础开发工 具。
安装依赖:
# 需要先更新软件包索引
apt update
apt install git gcc make -y
进入Shell终 端执行以下命令:
git clone https://github.com/Tongsuo-Project/Tongsuo
cd Tongsuo
./config --prefix=/opt/tongsuo enable-ntls enable-ssl-trace -Wl,-rpath,/opt/tongsuo/lib64 --debug
make -j
make install
查看安装情况:
ls -l /opt/tongsuo
产看铜锁版本,执行如下命令:
/opt/tongsuo/bin/tongsuo version
SM2&SM3&SM4算法实战
实战SM4加解密算法
echo "hello tongsuo" > msg.bin
# SM4-CBC加密
/opt/tongsuo/bin/tongsuo enc -K "3f342e9d67d6ce7be701756af7bac8f2" -e -sm4-cbc -in msg.bin -iv "1fb2d42fb36e2e88a220b04f2e49aa13" -nosalt -out cipher.bin
# SM4-CBC解密
/opt/tongsuo/bin/tongsuo enc -K "3f342e9d67d6ce7be701756af7bac8f2" -d -sm4-cbc -in cipher.bin -iv "1fb2d42fb36e2e88a220b04f2e49aa13" -nosalt -out msg2.bin
# 比较解密的明文和原来的消息是否一样
diff msg.bin msg2.bin
实战SM3杂凑算法
echo -n "hello tongsuo" | /opt/tongsuo/bin/tongsuo dgst -sm3
结果如下:
实战SM2签名和验签
# 生成一个随机内容文件
dd if=/dev/urandom of=msg.bin bs=1024 count=1
# SM2私钥签名,签名算法为SM2withSM3,Tongsuo/test/certs/sm2.key来自Tongsuo源代码仓库
/opt/tongsuo/bin/tongsuo dgst -sm3 -sign Tongsuo/test/certs/sm2.key -out sigfile msg.bin
# SM2公钥验签,Tongsuo/test/certs/sm2pub.key来自Tongsuo源代码仓库
/opt/tongsuo/bin/tongsuo dgst -sm3 -verify Tongsuo/test/certs/sm2pub.key -signature sigfile msg.bin
签名正确时,验证成功可以看到:
SM2&SM3&SM4算法编程入门
SM4加解密算法编程入门
SM4加密
#include <openssl/evp.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
static int sm4_enc(const unsigned char *key, const unsigned char *iv,
unsigned char *in, int inlen, unsigned char *out,
int *outlen)
{
EVP_CIPHER_CTX *ctx = NULL;
int outl, tmplen;
if ((ctx = EVP_CIPHER_CTX_new()) == NULL
|| !EVP_EncryptInit_ex(ctx, EVP_sm4_cbc(), NULL, key, iv)
|| !EVP_EncryptUpdate(ctx, out, &outl, in, inlen)
|| !EVP_EncryptFinal_ex(ctx, out + outl, &tmplen)) {
EVP_CIPHER_CTX_free(ctx);
return 0;
}
EVP_CIPHER_CTX_free(ctx);
if (outlen)
*outlen = outl + tmplen;
return 1;
}
int main()
{
unsigned char key[] = {
0x3f, 0x34, 0x2e, 0x9d, 0x67, 0xd6, 0xce, 0x7b,
0xe7, 0x01, 0x75, 0x6a, 0xf7, 0xba, 0xc8, 0xf2,};
unsigned char iv[] = {
0x1f, 0xb2, 0xd4, 0x2f, 0xb3, 0x6e, 0x2e, 0x88,
0xa2, 0x20, 0xb0, 0x4f, 0x2e, 0x49, 0xaa, 0x13,};
unsigned char in[] = "hello tongsuo";
unsigned char *out = NULL;
int outlen;
int ret;
out = malloc(sizeof(in) + EVP_MAX_BLOCK_LENGTH);
assert(out != NULL);
ret = sm4_enc(key, iv, in, strlen(in), out, &outlen);
assert(ret == 1);
for (size_t i = 0; i < outlen; i++)
printf("%x", out[i]);
printf("\n");
free(out);
return 0;
}
将内容保存为sm4_enc.c,并编译运行:
gcc sm4_enc.c -I/opt/tongsuo/include -L/opt/tongsuo/lib64 -lcrypto -Wl,-rpath=/opt/tongsuo/lib64
./a.out
输出明文消息的密文如下:
SM4解密:
#include <openssl/evp.h>
#include <openssl/err.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
static int sm4_dec(const unsigned char *key, const unsigned char *iv,
unsigned char *in, int inlen, unsigned char *out,
int *outlen)
{
EVP_CIPHER_CTX *ctx = NULL;
int outl, tmplen;
if ((ctx = EVP_CIPHER_CTX_new()) == NULL
|| !EVP_DecryptInit_ex(ctx, EVP_sm4_cbc(), NULL, key, iv)
|| !EVP_DecryptUpdate(ctx, out, &outl, in, inlen)
|| !EVP_DecryptFinal_ex(ctx, out + outl, &tmplen)) {
ERR_print_errors_fp(stderr);
EVP_CIPHER_CTX_free(ctx);
return 0;
}
EVP_CIPHER_CTX_free(ctx);
if (outlen)
*outlen = outl + tmplen;
return 1;
}
int main()
{
unsigned char key[] = {
0x3f, 0x34, 0x2e, 0x9d, 0x67, 0xd6, 0xce, 0x7b,
0xe7, 0x01, 0x75, 0x6a, 0xf7, 0xba, 0xc8, 0xf2,};
unsigned char iv[] = {
0x1f, 0xb2, 0xd4, 0x2f, 0xb3, 0x6e, 0x2e, 0x88,
0xa2, 0x20, 0xb0, 0x4f, 0x2e, 0x49, 0xaa, 0x13,};
unsigned char in[] = {
0xe2, 0x44, 0xdb, 0xeb, 0x97, 0x58, 0x83, 0x1e,
0xa8, 0x7b, 0x7c, 0xeb, 0x27, 0x8e, 0x6e, 0x5d,};
unsigned char *out = NULL;
int outlen;
int ret;
out = malloc(sizeof(in));
assert(out != NULL);
ret = sm4_dec(key, iv, in, sizeof(in), out, &outlen);
assert(ret == 1);
printf("%*s\n", outlen, out);
free(out);
return 0;
}
// gcc sm4_dec.c -I/opt/tongsuo/include -L/opt/tongsuo/lib64 -lcrypto -Wl,-rpath=/opt/tongsuo/lib64
保存内容为sm4_dec.c,编译并执行:
gcc sm4_dec.c -I/opt/tongsuo/include -L/opt/tongsuo/lib64 -lcrypto -Wl,-rpath=/opt/tongsuo/lib64
./a.out
输出如下: