因為某些不可抗原因,友商加密平臺系統(tǒng)無法提供接口進行加密驗簽,以至于需要自己實現(xiàn)監(jiān)管要求的加密驗簽。
接口要求,報文先經(jīng)過sm2生成簽名,之后進行sm4加密。收到報文后,先進行sm4解密,解密后將報文進行驗簽。驗證成功之后既結(jié)束全部流程。
所以整體上分為兩大部分,一為sm4加密,二為sm2簽名。
首先先說簡單的sm4加密,調(diào)用代碼參考了開源項目openssl。
1.準(zhǔn)備密鑰和需要加密的報文
2.將報文進行分組,每16個字也就是128bit為一組,這里采用最簡單的ECB分組方式,對不足16位的最后一組進行補位,采用pkcs7方式進行補位,就是差幾位就補幾位的幾,比如8位差八位,就補八個八,對于16整數(shù)倍補16位的16(方便解碼)
3.生成輪密鑰,將32位的密鑰分成八位一組的四組,編號為k0k1k2k3,通過互相運算及s盒,得到k4,再選取k1k2k3k4,運算得到k5,。循環(huán)32次,得到k0-k35,選取k4-k35為生成的輪密鑰結(jié)果
4.進行加密,同樣將一組16個字也是32位分成八位一組的四組,輪加密Bi⊕F(B(i-1)⊕B(i-2)⊕B(i-3)⊕k(i-4))得到下一組,最終得到B31-B35,拼成一個串返回這一組的加密結(jié)果,單組加密完畢。
最終把所有組拼在一起就是加密結(jié)果。
解密正好相反,因為必然是16的整數(shù)倍,所以直接分組。將生成的輪密鑰與加密后的報文進行逆運算,最終得到補碼后的原報文,取報文最后一位,截取最后一位對應(yīng)的數(shù)字得到原始信息文章來源:http://www.zghlxwxcb.cn/news/detail-519148.html
參考代碼:文章來源地址http://www.zghlxwxcb.cn/news/detail-519148.html
#include "e_os2.h"
#include "sm4.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void sm4_decrypt_ecb(unsigned char* key,
int length,
unsigned char* input,
unsigned char* output)
{
unsigned char* tmp=NULL ;
unsigned char* tmp1 = NULL;
int length1 = length;
int bodylength; /*解密后報文體長度 */
int pkcs = 0; /*補位值 */
SM4_KEY ks; /*輪密鑰結(jié)構(gòu)體 */
tmp = (unsigned char*)malloc(sizeof(char) * length+1);
memset(tmp, 0x00, length + 1);
tmp1 = tmp;
ossl_sm4_set_key(key, &ks); /*通過密鑰生成32輪密鑰*/
while (length1 > 0)
{
ossl_sm4_decrypt(input, tmp, &ks); /* 進行單組解密,暫存至tmp*/
input += 16;
tmp += 16;
length1 -= 16;
}
bodylength = strlen(tmp1);
pkcs = (int)tmp1[bodylength - 1]; /*取最后一位pkcs補位字符,轉(zhuǎn)換成數(shù)字*/
strncpy(output, tmp1, (bodylength - pkcs)); /*去除補位字符,拷貝至輸出*/
tmp = NULL;
tmp1 = NULL;
}
void sm4_encrypt_ecb(unsigned char* key,
int length,
unsigned char* input,
unsigned char* output) {
int bodylength; /*補位后報文體長度 */
SM4_KEY ks; /*輪密鑰結(jié)構(gòu)體 */
unsigned char pkcs; /*補位值 */
unsigned char* tmp= output;
pkcs = 16 - (length % 16); /*獲取補位值*/
memset(input + strlen(input), pkcs, pkcs); /*報文補位*/
ossl_sm4_set_key(key, &ks); /*通過密鑰生成32輪密鑰*/
bodylength = strlen(input);
while (bodylength > 0)
{
ossl_sm4_encrypt(input, tmp, &ks); /* 進行單組加密*/
input += 16;
tmp += 16;
bodylength -= 16;
}
}
void main() {
char key[16+1] ;
char input[100];
char input1[100];
char output1[100];
char output[100];
memset(key,0x00, sizeof(key));
memset(input, 0x00, sizeof(input));
memset(input1, 0x00, sizeof(input1));
memset(output1, 0x00, sizeof(output1));
memset(output, 0x00, sizeof(output));
strcpy(key, "1234567890abcdef");
strcpy(input, "1234567890abcdeghhjuuu5555678900uuuuuuu");
sm4_encrypt_ecb(key, strlen(input), input, output);
strcpy(input1, output);
sm4_decrypt_ecb(key, strlen(input1), input1, output1);
printf("input=[%s],\noutput=[%s]", input, output1);
}
到了這里,關(guān)于sm2簽名與sm4加密(一)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!