• ## 国密算法

千次阅读 2017-12-07 09:42:45
国密算法
//
//
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/gmapi.h>
#include "utils.h"
int compress_public_key(const unsigned char* puk, int puk_len, char* compressed_puk, int* compressed_puk_len)
{
EC_GROUP *curve_group = NULL;
EC_POINT *point=NULL;
BIGNUM *xy = NULL;
BIGNUM *x;
BIGNUM *y;
unsigned char buff[128] = { 0x0 };
int result = 0;
curve_group = EC_GROUP_new_by_curve_name(NID_sm2p256v1);
if(curve_group == NULL)
{
result = -2;
return  result;
}
xy = BN_new();
x = BN_new();
y = BN_new();
// create a big number from the unsigned char array
BN_bin2bn(puk, puk_len, xy);
BN_bin2bn(puk, 32, x);
BN_bin2bn(puk+32, 32, y);
point = EC_POINT_new(curve_group);
if(point==NULL)
{
result = -3;
return  result;
}
if (!EC_POINT_set_affine_coordinates_GFp(curve_group, point, x, y, NULL)) {
return -5;
}
if (!EC_POINT_is_on_curve(curve_group, point, NULL)) {
return -4;
}
if ((result = EC_POINT_point2oct(curve_group, point,
POINT_CONVERSION_COMPRESSED,
buff, sizeof(buff), NULL)) != 33) {
return -6;
}
memcpy(compressed_puk, buff, result);
*compressed_puk_len = result;
return 0;
}
int uncompress_public_key(unsigned char *in, int in_len, unsigned char *out, int *out_len)
{
EC_GROUP *curve_group = NULL;//
EC_POINT *point=NULL;
BIGNUM *x_compressed = NULL;
int y_chooser_bit = 0;
int results = 0;
size_t returnsize = 0;
unsigned char xy[200]={0};
unsigned char x_compressed_byte_array[33]={0};
do{
if(in[0] == 0x03)
{
y_chooser_bit = 1;
}else{
y_chooser_bit = 0;
}
memcpy(x_compressed_byte_array, in, 33);
x_compressed=BN_new();
if(x_compressed==NULL)
{
results = -1;
break;
}
curve_group=EC_GROUP_new_by_curve_name(NID_sm2p256v1);
if(curve_group==NULL)
{
results = -2;
break;
}
// create a big number from the unsigned char array
BN_bin2bn(&x_compressed_byte_array[1],sizeof(x_compressed_byte_array)-1,x_compressed);
point = EC_POINT_new(curve_group);
if(point==NULL)
{
results = -3;
break;
}
//说明：素数域椭圆曲线，给定压缩坐标x和y_bit参数，设置point的几何坐标；用于将Octet-String转化为椭圆曲线上的点；
EC_POINT_set_compressed_coordinates_GFp(curve_group, point,
x_compressed,
y_chooser_bit, NULL);
//printf("results=%d\r\n",results);
if (!EC_POINT_is_on_curve(curve_group,point,NULL))
{
results = -4;
break;
}
returnsize = EC_POINT_point2oct(curve_group, point,
POINT_CONVERSION_UNCOMPRESSED,
&xy[0], sizeof(xy), NULL); // 49
if(returnsize!=65)
{
results = -5;
break;
}
//printf("returnsize=%d\r\n",returnsize);
}while(0);
// clean up allocated memory
if(x_compressed)
BN_free(x_compressed);
if(point)
EC_POINT_free(point);
if(curve_group)
EC_GROUP_free(curve_group);
if(0==results)
{
memcpy(out, xy, 65);
*out_len = 65;
}
return results;
}
int hexToBin(const char* src, int src_len, char* dst, int* dst_len)
{
char tmpbuff[4] = { 0x0};
int i = 0;
int t;
if (src_len < 2 && (src_len % 2) != 0) {
return -1;
}
*dst_len = src_len / 2;
for(i=0; i< *dst_len; i++) {
memcpy(tmpbuff, src + i*2, 2);
t = strtol(tmpbuff, NULL, 16);
*(dst + i) = t & 0xff;
memset(tmpbuff, 0x0, sizeof(tmpbuff));
}
return 0;
}
int binToHex(const char* src, int src_len, char* dst, int* dst_len)
{
int i = 0;
for(i= 0; i < src_len; i++) {
sprintf(dst + i*2, "%02X", *(src + i) & 0xff);
}
*dst_len = src_len *2;
return 0;
}
int sm2_sign(const unsigned char* pvk, int pvk_len, const char* data, int data_len, char* signature, int* signature_len)
{
EVP_PKEY *pkey = NULL;
EC_KEY *ec_key = NULL;
const EVP_MD *id_md = EVP_sm3();
const EVP_MD *msg_md = EVP_sm3();
int type = NID_sm2p256v1;
unsigned char dgst[EVP_MAX_MD_SIZE];
size_t dgstlen = 32;
char *id = "1234567812345678";
ECDSA_SIG *sm2sig = NULL;
unsigned char sig[256] = { 0x0 };
unsigned int siglen = 0;
const BIGNUM *sig_r;
const BIGNUM *sig_s;
const unsigned char * p;
int i;
unsigned char* tp;
pkey = d2i_AutoPrivateKey(NULL, &pvk, pvk_len);
ec_key = EVP_PKEY_get0_EC_KEY(pkey);
SM2_compute_message_digest(id_md, msg_md,
(const unsigned char *)data, data_len, id, strlen(id),
dgst, &dgstlen, ec_key);
#ifdef DEBUG
printf("dgst1 = ");
for(i = 0; i< dgstlen; i++) {
printf("%02X", dgst[i]);
}
printf("\n");
#endif
siglen = sizeof(sig);
if (!SM2_sign(type, dgst, dgstlen, sig, &siglen, ec_key)) {
fprintf(stderr, "error: %s %d\n", __FUNCTION__, __LINE__);
return -1;
}
p = sig;
sm2sig  = d2i_ECDSA_SIG(NULL, &p, siglen);
ECDSA_SIG_get0(sm2sig, &sig_r, &sig_s);
siglen = BN_bn2bin(sig_r, signature);
*signature_len = siglen;
siglen = BN_bn2bin(sig_s, signature + siglen);
*signature_len += siglen;
return 0;
}
int sm2_sign_verify(const unsigned char* puk, int puk_len, const unsigned char* data, int data_len, const unsigned char* signature, int sig_len)
{
EC_KEY *ec_key = NULL;
BIGNUM *x = NULL;
BIGNUM *y = NULL;
EC_GROUP* group;
int ret = -1;
const EVP_MD *id_md = EVP_sm3();
const EVP_MD *msg_md = EVP_sm3();
int type = NID_sm2p256v1;
unsigned char dgst[EVP_MAX_MD_SIZE];
size_t dgstlen = 32;
char *id = "1234567812345678";
int i = 0;
ECDSA_SIG *sig = NULL;
BIGNUM *r = NULL;
BIGNUM *s = NULL;
unsigned char *pp = NULL;
unsigned char *pp_sig = NULL;
int pp_len = 0;
unsigned char* tp = NULL;
#ifdef DEBUG
printf("puk[%d] = ", puk_len);
for(i = 0; i< puk_len; i++) {
printf("%02X", puk[i]&0xff);
}
printf("\n");
printf("data[%d] = ", data_len);
for(i = 0; i< data_len; i++) {
printf("%02X", data[i]&0xff);
}
printf("\n");
printf("sign[%d] = ", sig_len);
for(i = 0; i< sig_len; i++) {
printf("%02X", signature[i]&0xff);
}
printf("\n");
#endif
group = EC_GROUP_new_by_curve_name(NID_sm2p256v1);
if (!(ec_key = EC_KEY_new())) {
ret = -2;
goto end;
}
if (!EC_KEY_set_group(ec_key, group)) {
ret = -3;
goto end;
}
if ((x = BN_bin2bn(puk, 32, NULL)) == NULL) {
ret = -4;
goto end;
}
if ((y = BN_bin2bn(puk+32, 32, NULL)) == NULL) {
ret = -5;
goto end;
}
if (!EC_KEY_set_public_key_affine_coordinates(ec_key, x, y)) {
ret = -6;
goto end;
}
ret = SM2_compute_message_digest(id_md, msg_md,
data, data_len, id, strlen(id),
dgst, &dgstlen, ec_key);
#ifdef DEBUG
printf("ret = [%d] = ", ret);
ret = EVP_MD_size(msg_md);
printf("EVP_MD_size = [%d] = ", ret);
printf("dgst[%d] = ", dgstlen);
for(i = 0; i< dgstlen; i++) {
printf("%02X", dgst[i]&0xff);
}
printf("\n");
printf("id_md [%d] = ", 64);
for(i = 0; i< 64; i++) {
printf("%02X", ((unsigned char*)id_md)[i]&0xff);
}
printf("\n");
printf("msg_md[%d] = ", 64);
for(i = 0; i< 64; i++) {
printf("%02X", ((unsigned char*)msg_md)[i]&0xff);
}
printf("\n");
printf("ec_key[%d] = ", 64);
for(i = 0; i< 64; i++) {
printf("%02X", ((unsigned char*)ec_key)[i]&0xff);
}
printf("\n");
#endif
if ((r = BN_bin2bn(signature, 32, NULL)) == NULL) {
ret = -4;
goto end;
}
if ((s = BN_bin2bn(signature+32, 32, NULL)) == NULL) {
ret = -5;
goto end;
}
pp_len = ECDSA_size(ec_key);
if ((pp_sig = OPENSSL_malloc(pp_len)) == NULL) {
fprintf(stderr, "error : %s %d\n", __FUNCTION__, __LINE__);
goto end;
}
sig = ECDSA_SIG_new();
if (!ECDSA_SIG_set0(sig, r, s)) {
fprintf(stderr, "error : %s %d\n", __FUNCTION__, __LINE__);
goto end;
}
pp = pp_sig;
pp_len = i2d_ECDSA_SIG(sig, &pp);
#ifdef DEBUG
printf("sig = ");
for(i = 0; i< pp_len; i++) {
printf("%02X", pp_sig[i]);
}
printf("\n");
#endif
ret = SM2_verify(type, dgst, dgstlen, pp_sig, pp_len, ec_key);
if (1 != ret) {
fprintf(stderr, "error %d : %s %d\n", ret, __FUNCTION__, __LINE__);
ret = -7;
goto end;
}
ret = 0;
end:
return ret;
}
void dump_cert_request(CERT_REQUEST_T *cert_req)
{
int i = 0;
unsigned char* p;
printf("Cert request file, length = %d bytes\n", sizeof(CERT_REQUEST_T));
p = (unsigned char*)cert_req;
for(i = 0; i< sizeof(CERT_REQUEST_T); i++) {
printf("%02X", *(p+i));
}
printf("\n");
printf("Service id: ");
for(i = 0; i< sizeof(cert_req->service_id); i++) {
printf("%02X", cert_req->service_id[i]);
}
printf("\n");
printf("Cert format: %02X\n", cert_req->format);
printf("Expire date: ");
for(i = 0; i< sizeof(cert_req->expire_date); i++) {
printf("%02X", cert_req->expire_date[i]);
}
printf("\n");
printf("Record number: ");
for(i = 0; i< sizeof(cert_req->record_number); i++) {
printf("%02X", cert_req->record_number[i]);
}
printf("\n");
printf("Sign algo: %02X\n", cert_req->sign_id);
printf("Encrypt algo: %02X\n", cert_req->encrypt_id);
printf("SM2 public key param: %02X\n", cert_req->puk_param_id);
printf("SM2 public key length: %02X\n", cert_req->puk_len);
printf("SM2 public key: ");
for(i = 0; i< sizeof(cert_req->puk); i++) {
printf("%02X", cert_req->puk[i]);
}
printf("\n");
printf("SM2 signature: ");
for(i = 0; i< sizeof(cert_req->signature); i++) {
printf("%02X", cert_req->signature[i]);
}
printf("\n");
return;
}
void dump_cert_response(CERT_RESPONSE_T* cert_resp)
{
int i = 0;
unsigned char* p;
printf("Cert response file, length = %d bytes\n", sizeof(CERT_RESPONSE_T));
p = (unsigned char*)cert_resp;
for(i = 0; i< sizeof(CERT_RESPONSE_T); i++) {
printf("%02X", *(p+i));
}
printf("\n");
printf("Service id: ");
for(i = 0; i< sizeof(cert_resp->service_id); i++) {
printf("%02X", cert_resp->service_id[i]);
}
printf("\n");
printf("Root CA public key index: %02X\n", cert_resp->ca_puk_idx);
printf("Cert format: %02X\n", cert_resp->format);
printf("Issuer id: ");
for(i = 0; i< sizeof(cert_resp->issuer_id); i++) {
printf("%02X", cert_resp->issuer_id[i]);
}
printf("\n");
printf("Expire date: ");
for(i = 0; i< sizeof(cert_resp->expire_date); i++) {
printf("%02X", cert_resp->expire_date[i]);
}
printf("\n");
printf("Serial number: ");
for(i = 0; i< sizeof(cert_resp->record_number); i++) {
printf("%02X", cert_resp->record_number[i]);
}
printf("\n");
printf("Sign algo: %02X\n", cert_resp->sign_id);
printf("Encrypt algo: %02X\n", cert_resp->encrypt_id);
printf("SM2 public key param: %02X\n", cert_resp->puk_param_id);
printf("SM2 public key length: %02X\n", cert_resp->puk_len);
printf("SM2 public key: ");
for(i = 0; i< sizeof(cert_resp->puk); i++) {
printf("%02X", cert_resp->puk[i]);
}
printf("\n");
printf("SM2 signature: ");
for(i = 0; i< sizeof(cert_resp->signature); i++) {
printf("%02X", cert_resp->signature[i]);
}
printf("\n");
return;
}
int dump_cert_response_to_file(int fd, CERT_RESPONSE_T* cert_resp)
{
unsigned char *p;
int len;
int ret;
p = (unsigned char*)cert_resp;
len = sizeof(CERT_RESPONSE_T);
ret = write(fd, p, len);
if (len != ret) {
printf("Failed to write file.\n");
return -1;
}
return 0;
}
int read_private_key_from_pem(const char* pemfile, unsigned char* private_key, int* private_key_len)
{
BIO *fp;
char *name = 0;
unsigned char *buff = 0x0 ;
long buff_len;
int ret = -1;
if (access(pemfile, R_OK) != 0 ) {
return -1;
}
fp = BIO_new_file(pemfile, "r");
if (fp == NULL) {
printf("Failed to open file: %s", pemfile);
ret = -2;
goto  err;
}
#ifdef DEBUG
printf("1buff ret = %d len = %d name = %s data = \n", ret, buff_len, name);
for(int i = 0; i<buff_len; i++) {
printf("%02X", buff[i]);
}
printf("\n");
#endif
if (strncmp(name, "EC PARAMETERS", 13) == 0 ) {
#ifdef DEBUG
printf("2buff len = %d data = \n", buff_len);
for(int i = 0; i<buff_len; i++) {
printf("%02X", buff[i]);
}
printf("\n");
#endif
memcpy(private_key, buff, buff_len);
*private_key_len = buff_len;
ret = 0;
} else {
printf("WARNING: This is not a EC key file.\n");
ret = -3;
goto  err;
}
err:
BIO_free(fp);
return ret;
}
展开全文
• js国密算法sm2以及国密算法sm3 js的实现以及例子 js国密算法sm2以及国密算法sm3 js的实现以及例子
• 国密算法--Openssl 实现国密算法（加密和解密），内涵对称算法，非对称算法加解密流程，图文直观，并附有C语言代码
• 国密算法概述1 SM1对称密码2 SM2椭圆曲线公钥密码算法3 SM3杂凑算法4 SM4对称算法5 SM7对称密码6 SM9标识密码算法7 ZUC祖冲之算法总结 算法名称 算法类别 应用领域 特点 SM1 对称密码算法 芯片 分组长度、...
国密算法概述1 SM1对称密码2 SM2椭圆曲线公钥密码算法3 SM3杂凑算法4 SM4对称算法5 SM7对称密码6 SM9标识密码算法7 ZUC祖冲之算法总结

算法名称
算法类别
应用领域
特点

SM1
对称密码算法
芯片
分组长度、密钥长度均为 128 比特

SM2
公钥密码算法
加密
ECC椭圆曲线密码机制256位 相比RSA，处理速度快，消耗更少

SM3
Hash函数算法
完整性
安全性及效率与SHA-256相当 压缩函数更复杂

SM4
对称密码算法
无线局域网产品
分组长度、密钥长度均为 128 比特 计算轮数多

SM7
对称密码算法
非接触式IC卡
分组长度、密钥长度均为 128 比特

SM9
标识密码算法（IBE）
端对端离线安全通讯
加密强度等同于3072位密钥的RSA加密算法

ZUC
序列密码算法
移动通信4G网络
流密码

概述
众所周知，为了保障商用密码的安全性，国家商用密码管理办公室制定了一系列密码标准，包括SM1（SCB2）、SM2、SM3、SM4、SM7、SM9、祖冲之密码算法（ZUC)那等等。
在金融领域目前主要使用公开的SM2、SM3、SM4三种商用密码算法，分别为非对称加密算法、哈希算法和对称加密算法。
其中SM1、SM4、SM7、祖冲之密码（ZUC）是对称算法；SM2、SM9是非对称算法；SM3是哈希算法。目前，这些算法已广泛应用于各个领域中，期待有一天会有采用国密算法的区块链应用出现。
SM2，3，9已被纳入国际标准
其中SM1、SM7算法不公开，调用该算法时，需要通过加密芯片的接口进行调用；比较少人了解这些算法，在这里对这些国密算法做简单的科普
1 SM1对称密码
SM1 算法是分组密码算法，分组长度为128位，密钥长度都为 128 比特，算法安全保密强度及相关软硬件实现性能与 AES 相当，算法不公开，仅以IP核的形式存在于芯片中。
采用该算法已经研制了系列芯片、智能IC卡、智能密码钥匙、加密卡、加密机等安全产品，广泛应用于电子政务、电子商务及国民经济的各个应用领域（包括国家政务通、警务通等重要领域）。
2 SM2椭圆曲线公钥密码算法
SM2算法就是ECC椭圆曲线密码机制，但在签名、密钥交换方面不同于ECDSA、ECDH等国际标准，而是采取了更为安全的机制。另外，SM2推荐了一条256位的曲线作为标准曲线。
SM2标准包括总则，数字签名算法，密钥交换协议，公钥加密算法四个部分，并在每个部分的附录详细说明了实现的相关细节及示例。
SM2性能更优更安全：密码复杂度高、处理速度快、机器性能消耗更小

SM2算法主要考虑素域Fp和F2m上的椭圆曲线，分别介绍了这两类域的表示，运算，以及域上的椭圆曲线的点的表示，运算和多倍点计算算法。然后介绍了编程语言中的数据转换，包括整数和字节串，字节串和比特串，域元素和比特串，域元素和整数，点和字节串之间的数据转换规则。
详细说明了有限域上椭圆曲线的参数生成以及验证，椭圆曲线的参数包括有限域的选取，椭圆曲线方程参数，椭圆曲线群基点的选取等，并给出了选取的标准以便于验证。最后给椭圆曲线上密钥对的生成以及公钥的验证，用户的密钥对为（s，sP），其中s为用户的私钥，sP为用户的公钥，由于离散对数问题从sP难以得到s，并针对素域和二元扩域给出了密钥对生成细节和验证方式。总则中的知识也适用于SM9算法。
在总则的基础上给出了数字签名算法（包括数字签名生成算法和验证算法），密钥交换协议以及公钥加密算法（包括加密算法和解密算法），并在每个部分给出了算法描述，算法流程和相关示例。
数字签名算法，密钥交换协议以及公钥加密算法都使用了国家密管理局批准的SM3密码杂凑算法和随机数发生器。数字签名算法，密钥交换协议以及公钥加密算法根据总则来选取有限域和椭圆曲线，并生成密钥对。
SM2算法在很多方面都优于RSA算法（RSA发展得早应用普遍，SM2领先也很自然），与RSA安全性对比如下图
3 SM3杂凑算法
SM3安全性高：压缩函数更复杂
Hash函数的性质

抗第一原像（单向性）：对于给定的hash值h，要找到M使得H（M）=h在计算上是不可行的
抗第二原像（抗弱碰撞性）：对于给定的消息M1，要发现另一个消息M2，满足H（M1）=H（M2）在计算上是不可行的
抗强碰撞性：找任意一对不同消息M1、M2，使H（M1）=H（M2）在计算上是不可行的

SM3****密码杂凑（哈希、散列）算法给出了杂凑函数算法的计算方法和计算步骤，并给出了运算示例。此算法适用于商用密码应用中的数字签名和验证，消息认证码的生成与验证以及随机数的生成，可满足多种密码应用的安全需求。在SM2，SM9标准中使用。
此算法对输入长度小于2的64次方的比特消息，经过填充和迭代压缩，生成长度为256比特的杂凑值， 安全性及效率与SHA-256相当。其中使用了异或，模，模加，移位，与，或，非运算，由填充，迭代过程，消息扩展和压缩函数所构成。具体算法及运算示例见SM3标准。

4 SM4对称算法
SM4更安全：计算轮数多、增加非线性变化

此算法是一个分组算法，用于无线局域网产品。该算法的分组长度为128比特，密钥长度为128比特。加密算法与密钥扩展算法都采用32轮非线性迭代结构。解密算法与加密算法的结构相同，只是轮密钥的使用顺序相反，解密轮密钥是加密轮密钥的逆序。
此算法采用非线性迭代结构，每次迭代由一个轮函数给出，其中轮函数由一个非线性变换和线性变换复合而成，非线性变换由S盒所给出。其中rki为轮密钥，合成置换T组成轮函数。轮密钥的产生与上图流程类似，由加密密钥作为输入生成，轮函数中的线性变换不同，还有些参数的区别。SM4算法的具体描述和示例见SM4标准。
5 SM7对称密码
SM7算法，是一种分组密码算法，分组长度为128比特，密钥长度为128比特。SM7适用于非接触式IC卡，应用包括身份识别类应用(门禁卡、工作证、参赛证)，票务类应用(大型赛事门票、展会门票)，支付与通卡类应用（积分消费卡、校园一卡通、企业一卡通等）。
6 SM9标识密码算法
SM9算法不需要申请数字证书，适用于互联网应用的各种新兴应用的安全保障。如基于云技术的密码服务、电子邮件安全、智能终端保护、物联网安全、云存储安全等等。这些安全应用可采用手机号码或邮件地址作为公钥，实现数据加密、身份认证、通话加密、通道加密等安全应用，并具有使用方便，易于部署的特点，从而开启了普及密码算法的大门。
7 ZUC祖冲之算法
祖冲之序列密码算法是中国自主研究的**流密码算法,**是运用于移动通信4G网络中的国际标准密码算法,该算法包括祖冲之算法(ZUC)、加密算法(128-EEA3)和完整性算法(128-EIA3)三个部分。目前已有对ZUC算法的优化实现，有专门针对128-EEA3和128-EIA3的硬件实现与优化。
总结
密码算法作为国家战略资源，比历史上任何时候都显得更为关键。在大数据和云计算的时代，关键信息往往通过数据挖掘技术在海量数据中获得，所以每一个人的信息保护都非常重要。
转载链接：https://m.qukuaiwang.com.cn/news/2271.html
参考链接：https://zhuanlan.zhihu.com/p/34618269


展开全文
• 国密算法，Fully摘要,Simple摘要,SM2-加验签，SM4-ECB加密解密
• sm4 国密算法 c语言 sm4 国密算法 c语言 sm4 国密算法 c语言
• 国密算法简介
• sm国密算法源码java版
• 国密算法那点事儿】解读DES和SM4、RSA和SM2及SM3安全是智能卡的核心，而算法是安全的基础。国密算法由国家密码局发布，包含SM1\ SM2\ SM3\ SM4\ SSF33算法;国际算法由美国的安全局发布，是现今最通用的商用算法。...
• 文档为国密算法介绍，主要介绍SM1、SM2、SM3、SM4、SM7、SM9算法以及ZUC算法
• 国密算法SM2 SM3 SM4 的技术规范文档，还有RSA文档，PDF文件。
• Java版国密算法SM2、SM3、SM4源代码，包含测试案例及算法相关文档。 100%可用。
• 初识国密算法 国密算法是国家商用密码算法的简称，由国家密码管理局管理和发布标准。国家密码管理局的官方网站是： http://www.oscca.gov.cn/sca/index.shtml 就如同其它政府网站一样，望着满屏的信息，就是找不到我...
初识国密算法
国密算法是国家商用密码算法的简称，由国家密码管理局管理和发布标准。国家密码管理局的官方网站是：
http://www.oscca.gov.cn/sca/index.shtml
就如同其它政府网站一样，望着满屏的信息，就是找不到我所想要的，比如国密算法标准和规范文档，网站上只有发布文档的公告，但找不到获取方法。后来在github上找到，网址为：
https://github.com/guanzhi/GM-Standards.git
这里面有全套的国密算法标准文档，不是由官方维护，不清楚里面是否包含了所有的最新标准文档。文档库中的文档非常多，比如GMT正式标准下就有69个标准文档：

里面包含了SM2/SM3/SM4等密码算法标准及其应用规范。“SM”代表“商密”，即用于商用的、不涉及国家秘密的密码技术。其中SM2为基于椭圆曲线密码的公钥密码算法标准，包含数字签名、密钥交换和公钥加密，用于替换RSA/Diffie-Hellman/ECDSA/ECDH等国际算法；SM3为密码哈希算法，用于替代MD5/SHA-1/SHA-256等国际算法；SM4为分组密码，用于替代DES/AES等国际算法；SM9为基于身份的密码算法，可以替代基于数字证书的PKI/CA体系。
看到这一堆的标准文档，是不是有点发怵。别慌，目前已经有国密算法的开源实现，这个项目就是GmSSL。该项目有一个官方网站：
http://gmssl.org/
里面有许多对于程序员而言非常有用的信息。从中我们可以了解到，GmSSL项目由北京大学关志副研究员的密码学研究组开发维护，项目源码托管于GitHub：
https://github.com/guanzhi/GmSSL.git
GmSSL是一个开源的密码库以及工具箱，支持SM2/SM3/SM4/SM9/ZUC等国密(国家商用密码)算法、SM2国密数字证书及基于SM2证书的SSL/TLS安全通信协议，支持国密硬件密码设备，提供符合国密规范的编程接口与命令行工具，可以用于构建PKI/CA、安全通信、数据加密等符合国密标准的安全应用。
GmSSL是从鼎鼎大名的开源安全库 OpenSSL fork而来，研究其源码可以看出它是基于OpenSSL 1.1.0d开发。GmSSL与OpenSSL保持接口兼容，理论上使用OpenSSL库的产品，可以直接使用GmSSL替换。GmSSL项目采用对商业应用友好的类BSD开源许可证，无论是在开源项目，还是闭源的商业应用中，都可以放心使用，不必担心授权问题。
研究安全算法，必须拥有深厚的数学功底（又是数学，不管是研究深度学习，还是安全算法，数学都是拦路虎图片），否则读那些算法如同天书。感谢有这些开源实现，否则真不知道如何继续下去。基于这些开源实现，我们可以在几个方面进行深挖：
算法移植，包括硬件和软件两个方面。硬件移植包括移植到更多的平台，比如ARM、MIPS等架构的芯片上，还有就是针对硬件平台进行优化，启用硬件加速。软件则包括将算法移植到其它的语言库，比如Java、JavaScript等等，甚至同样使用C语言，也存在移植的需求，比如firefox家族产品所使用的NSS库。
GmSSL库本身的完善。就拿《GM/T 0024-2014: SSL VPN技术规范》的新增密码套件来说，GmSSL并不是都支持。后续如果有新的算法标准公布，也需要加入新的实现。
集成国密算法到产品。国密算法只是一套算法标准，其作用还要体现在具体产品中。要推广国密算法，客户端（如浏览器、邮件客户端、加密卡等）和服务器端（如 Web 服务器、邮件服务器等）都需要推进。
国密算法标准，更多的像是自上而下的政治任务，而不是从产品的实际需求出发，不可避免的带有一些中国特色。就拿浏览器产品来说，虽然这个标准从2012年开始颁布，但我这个从业者之前从没有听说过这个标准，主流的浏览器chrome、firefox，甚至国内的浏览器都不支持该标准。网上搜索了一些号称支持国密的浏览器，除了360，都没达到商用水准。
这套标准中，SM1算法并没有公布，从现代密码学的角度看，这并不安全。就我们普通人看来，算法不公布，不是更难破解吗？所谓道高一尺，魔高一丈，看看Windows系统被攻击的多惨就知道了。而Linux系统采取开源策略，不停的有高手参与进来修复漏洞，反而更安全。当然这只是我的浅见，我对算法这么高深的领域没有发言权。
有句话是这样说的，一流的企业做标准，二流的企业做品牌，三流的企业做产品。要争夺话语权，制定标准无疑是最高级的打法。但从国密算法标准操作来看，似乎并没有想更多的企业参与进来，先不说国际推广吧，对国内参与者也不算友好，发布的标准文档还需要费力从个人维护的github找到，文档也是纸质扫描档，搜索、查找都不方便。参与的企业也是各自为战，并没有很好的交流渠道。
不过吐槽归吐槽，中国推出这套国密算法，也是期望在国际竞争中不受制于人。这套算法标准，目前没看出其先进性。但路总要一步步的走，期望一下子推出领先国际的技术，而忘了我们的基础还比较薄弱，那是自欺欺人。这样的标准推广，需要众多的程序员，做好基础工作，先做出和别人相当的水准，才可能后续慢慢超越。


展开全文
• 国密算法sm9pdf格式
• 国密算法： sm2和sm3 java+js实现， js国密算法sm2以及国密算法sm3 js的实现以及例子
• SM4国密算法，加密、解密。未经本人同意，不得随意转载。
• 本文设计并提出了基于国密算法的区块链架构—“国密链”, 以国密算法SM2、SM3替换国际通用密码算法的ECC、SHA-256, 实现了区块链架构的自主可控. 同时, 针对当前区块链架构面临的共识算法妥协的现状, 设计了“可插拔...
• 国家商用密码管理局公布的标准国密算法SM4的算法实现哦
• 使用JS实现国密算法SM4
• java 国密算法sm2、sm3 详细使用参考：https://blog.csdn.net/weixin_30512027/article/details/86013878

...