SM4.0

SM4.0

SM4.0(原名SMS4.0)是中華人民共和國政府採用的一種分組密碼標準,由國家密碼管理局於2012年3月21日發布。相關標準為“GM/T 0002-2012《SM4分組密碼算法》(原SMS4分組密碼算法)”。

基本介紹

  • 中文名:SM 4.0
  • 發布者國家密碼管理局
  • 發布時間:2012年3月21日
  • 相關標準:GM/T0002-2012
  • 學科:密碼學
  • 原名:SMS4
介紹,相關概念,原始碼,C/C++,Python,Java,

介紹

SM4.0(原名SMS4.0)是中華人民共和國政府採用的一種分組密碼標準,由國家密碼管理局於2012年3月21日發布。相關標準為“GM/T 0002-2012《SM4分組密碼算法》(原SMS4分組密碼算法)”。
商用密碼體系中,SM4主要用於數據加密,其算法公開,分組長度與密鑰長度均為128bit,加密算法與密鑰擴展算法都採用32輪非線性疊代結構,S盒為固定的8比特輸入8比特輸出。
SM4.0中的指令長度被提升到大於64K(即64×1024)的水平,這是SM 3.0規格(渲染指令長度允許大於512)的128倍。

相關概念

密碼學中,分組加密(英語:Block cipher),又稱分塊加密塊密碼,是一種對稱密鑰算法。它將明文分成多個等長的模組(block),使用確定的算法和對稱密鑰對每組分別加密解密。分組加密是極其重要的加密協定組成,其中典型的如DESAES作為美國政府核定的標準加密算法,套用領域從電子郵件加密到銀行交易轉帳,非常廣泛。
國密即國家密碼局認定的國產密碼算法。主要有SM1,SM2,SM3,SM4。密鑰長度和分組長度均為128位。
SM1為對稱加密。其加密強度與AES相當。該算法不公開,調用該算法時,需要通過加密晶片的接口進行調用。
SM2為非對稱加密,基於ECC。該算法已公開。由於該算法基於ECC,故其簽名速度與秘鑰生成速度都快於RSA。ECC 256位(SM2採用的就是ECC 256位的一種)安全強度比RSA 2048位高,但運算速度快於RSA。
SM3訊息摘要。可以用MD5作為對比理解。該算法已公開。校驗結果為256位。
SM4無線區域網路標準的分組數據算法。對稱加密,密鑰長度和分組長度均為128位。

原始碼

C/C++

#define HEADER_SM4_H#define HEADER_SM4_H#ifdef __cplusplusextern "C" {#endiftypedef unsigned char muint8;typedef unsigned long muint32;#define LITTLE_ENDIAN   //定義小端位元組序//#define BIG_ENDIAN   //定義大端位元組序#define SM4_ENCRYPT 1   //定義加密標誌#define SM4_DECRYPT 0   //定義解密標誌#define SM4_BLOCK_LEN    16#define SM4_KEY_LEN    16#define SM4_IV_LEN    SM4_BLOCK_LEN// SM4的密鑰擴展算法// 參數說明:Key為加密密鑰,rk為子密鑰,CryptFlag為加解密標誌int SM4KeyExt(const muint8 *Key, muint32 *rk, muint32 CryptFlag);// SM4的加解密函式// 參數說明:Input為輸入信息分組,Output為輸出分組,rk為輪密鑰int SM4Crypt(const muint8 *Input, muint8 *Output, const muint32 *rk);//For EVPvoid sm4_set_key(muint32 *rk, const unsigned char *data, int enc);void sm4_ecb_encrypt(char *in, char *out, const muint32 *rk,int enc);void sm4_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,const muint32 *rk, unsigned char *iv, int enc);void sm4_cfb64_encrypt(const unsigned char *in, unsigned char *out,long length, const muint32 *rk, unsigned char *ivec,int *num, int enc);void sm4_ofb64_encrypt(const unsigned char *in, unsigned char *out,long length, const muint32 *rk, unsigned char *ivec,int *num);#ifdef __cplusplus}#endif#endif#include "sm4.h"#include//muint32 rk[32];//作為加解密上下文const muint8 Sbox[256] = {0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05,0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99,0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62,0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6,0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8,0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35,0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87,0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e,0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1,0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3,0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f,0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51,0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8,0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0,0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84,0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48};const muint32 CK[32] = {0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 };#define Rotl(_x, _y) (((_x) << (_y)) | ((_x) >> (32 - (_y))))#define ByteSub(_A) (Sbox[(_A) >> 24 & 0xFF] << 24 ^ \Sbox[(_A) >> 16 & 0xFF] << 16 ^ \Sbox[(_A) >> 8 & 0xFF] << 8 ^ \Sbox[(_A) & 0xFF])#define L1(_B) ((_B) ^ Rotl(_B, 2) ^ Rotl(_B, 10) ^ Rotl(_B, 18) ^ Rotl(_B, 24))#define L2(_B) ((_B) ^ Rotl(_B, 13) ^ Rotl(_B, 23))// SM4的加解密函式// 參數說明:Input為輸入信息分組,Output為輸出分組,rk為輪密鑰int SM4Crypt(const muint8 *Input, muint8 *Output, const muint32 *rk){muint32 r, mid, x0, x1, x2, x3, *p;p = (muint32 *)Input;x0 = p[0];x1 = p[1];x2 = p[2];x3 = p[3];#ifdef LITTLE_ENDIANx0 = Rotl(x0, 16); x0 = ((x0 & 0x00FF00FF) << 8) ^ ((x0 & 0xFF00FF00) >> 8);x1 = Rotl(x1, 16); x1 = ((x1 & 0x00FF00FF) << 8) ^ ((x1 & 0xFF00FF00) >> 8);x2 = Rotl(x2, 16); x2 = ((x2 & 0x00FF00FF) << 8) ^ ((x2 & 0xFF00FF00) >> 8);x3 = Rotl(x3, 16); x3 = ((x3 & 0x00FF00FF) << 8) ^ ((x3 & 0xFF00FF00) >> 8);#endiffor (r = 0; r < 32; r += 4){mid = x1 ^ x2 ^ x3 ^ rk[r + 0];mid = ByteSub(mid);x0 ^= L1(mid);mid = x2 ^ x3 ^ x0 ^ rk[r + 1];mid = ByteSub(mid);x1 ^= L1(mid);mid = x3 ^ x0 ^ x1 ^ rk[r + 2];mid = ByteSub(mid);x2 ^= L1(mid);mid = x0 ^ x1 ^ x2 ^ rk[r + 3];mid = ByteSub(mid);x3 ^= L1(mid);}#ifdef LITTLE_ENDIANx0 = Rotl(x0, 16); x0 = ((x0 & 0x00FF00FF) << 8) ^ ((x0 & 0xFF00FF00) >> 8);x1 = Rotl(x1, 16); x1 = ((x1 & 0x00FF00FF) << 8) ^ ((x1 & 0xFF00FF00) >> 8);x2 = Rotl(x2, 16); x2 = ((x2 & 0x00FF00FF) << 8) ^ ((x2 & 0xFF00FF00) >> 8);x3 = Rotl(x3, 16); x3 = ((x3 & 0x00FF00FF) << 8) ^ ((x3 & 0xFF00FF00) >> 8);#endifp = (muint32 *)Output;p[0] = x3;p[1] = x2;p[2] = x1;p[3] = x0;return 1;}

Python

SM4的Python實現
#!/usr/bin/env python# -*- coding: utf-8 -*-# @Author  : 河北雪域網路科技有限公司 A.Star# @contact: [email protected]# @site: www.snowland.ltd# @file: SM4.py# @time: 2018/9/21 15:25# @Software: PyCharmimport copyimport timefrom functools import reduce# Expanded SM4 S-boxes    Sbox table: 8bits input convert to 8 bits outputSboxTable = [    0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,    0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,    0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,    0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,    0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,    0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,    0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,    0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,    0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,    0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,    0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,    0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,    0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,    0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,    0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,    0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,]# System parameterFK = [0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc]# fixed parameterCK = [    0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,    0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,    0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,    0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,    0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,    0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,    0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,    0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279]ENCRYPT = 0DECRYPT = 1def GET_UINT32_BE(key_data):    return int((key_data[0] << 24) | (key_data[1] << 16) | (key_data[2] << 8) | (key_data[3]))def PUT_UINT32_BE(n):    return [int((n >> 24) & 0xff), int((n >> 16) & 0xff), int((n >> 8) & 0xff), int((n) & 0xff)]# rotate shift left marco definitiondef SHL(x, n):    return int(int(x << n) & 0xffffffff)def ROTL(x, n):    return SHL(x, n) | int((x >> (32 - n)) & 0xffffffff)def XOR(a, b):    return list(map(lambda x, y: x ^ y, a, b))# look up in SboxTable and get the related value.# args:    [in] inch: 0x00~0xFF (8 bits unsigned value).def sm4Sbox(idx):    return SboxTable[idx]# Calculating round encryption key.# args:    [in] a: a is a 32 bits unsigned value;# return: sk[i]: i{0,1,2,3,...31}.def sm4CalciRK(ka):    a = PUT_UINT32_BE(ka)    b = [sm4Sbox(i) for i in a]    bb = GET_UINT32_BE(b)    rk = bb ^ (ROTL(bb, 13)) ^ (ROTL(bb, 23))    return rk# private F(Lt) function:# "T algorithm" == "L algorithm" + "t algorithm".# args:    [in] a: a is a 32 bits unsigned value;# return: c: c is calculated with line algorithm "L" and nonline algorithm "t"def sm4Lt(ka):    a = PUT_UINT32_BE(ka)    b = [sm4Sbox(i) for i in a]    bb = GET_UINT32_BE(b)    return bb ^ (ROTL(bb, 2)) ^ (ROTL(bb, 10)) ^ (ROTL(bb, 18)) ^ (ROTL(bb, 24))# private F function:# Calculating and getting encryption/decryption contents.# args:    [in] x0: original contents;# args:    [in] x1: original contents;# args:    [in] x2: original contents;# args:    [in] x3: original contents;# args:    [in] rk: encryption/decryption key;# return the contents of encryption/decryption contents.def sm4F(x0, x1, x2, x3, rk):    return (x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk))class Sm4(object):    def __init__(self):        self.sk = [0] * 32        self.mode = ENCRYPT    def sm4_set_key(self, key_data, mode):        self.sm4_setkey(key_data, mode)    def sm4_setkey(self, key, mode):        MK = [0, 0, 0, 0]        k = [0] * 36        MK[0] = GET_UINT32_BE(key[0:4])        MK[1] = GET_UINT32_BE(key[4:8])        MK[2] = GET_UINT32_BE(key[8:12])        MK[3] = GET_UINT32_BE(key[12:16])        k[0:4] = XOR(MK, FK)        for i in range(32):            k[i + 4] = k[i] ^ (sm4CalciRK(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ CK[i]))        self.sk = k[4:]        self.mode = mode        if mode == DECRYPT:            self.sk.reverse()    def sm4_one_round(self, sk, in_put):        item = [GET_UINT32_BE(in_put[0:4]), GET_UINT32_BE(in_put[4:8]), GET_UINT32_BE(in_put[8:12]),                GET_UINT32_BE(in_put[12:16])]        res = reduce(lambda x, y: [x[1], x[2], x[3], sm4F(x[0], x[1], x[2], x[3], y)], sk, item)        res.reverse()        rev = map(PUT_UINT32_BE, res)        out_put = []        [out_put.extend(_) for _ in rev]        return out_put    def sm4_crypt_ecb(self, input_data):        # SM4-ECB block encryption/decryption        output_data = []        tmp = [input_data[i:i + 16] for i in range(0, len(input_data), 16)]        [output_data.extend(each) for each in map(lambda x: self.sm4_one_round(self.sk, x), tmp)]        return output_data    def sm4_crypt_cbc(self, iv, input_data):        # SM4-CBC buffer encryption/decryption        length = len(input_data)        i = 0        output_data = []        tmp_input = [0] * 16        if self.mode == ENCRYPT:            while length > 0:                tmp_input[0:16] = XOR(input_data[i:i + 16], iv[0:16])                output_data += self.sm4_one_round(self.sk, tmp_input[0:16])                iv = copy.deepcopy(output_data[i:i + 16])                i += 16                length -= 16        else:            while length > 0:                output_data += self.sm4_one_round(self.sk, input_data[i:i + 16])                output_data[i:i + 16] = XOR(output_data[i:i + 16], iv[0:16])                iv = copy.deepcopy(input_data[i:i + 16])                i += 16                length -= 16        return output_datadef sm4_crypt_ecb(mode, key, data):    sm4_d = Sm4()    sm4_d.sm4_set_key(key, mode)    en_data = sm4_d.sm4_crypt_ecb(data)    return en_datadef sm4_crypt_cbc(mode, key, iv, data):    sm4_d = Sm4()    sm4_d.sm4_set_key(key, mode)    en_data = sm4_d.sm4_crypt_cbc(iv, data)    return en_dataif __name__ == "__main__":    # log_init()    key_data = [0x5a] * 16    input_data = [0x6b] * 128    iv_data = [0] * 16    sm4_d = Sm4()    sm4_d.sm4_set_key(key_data, ENCRYPT)    en_data = sm4_d.sm4_crypt_ecb(input_data)    print(en_data, "en_data:")    sm4_d.sm4_set_key(key_data, DECRYPT)    de_data = sm4_d.sm4_crypt_ecb(en_data)    print(de_data, "de_data:")    if de_data == input_data:        print("ecb check pass")    else:        print("ecb check fail")        raise BaseException("error")    sm4_d.sm4_set_key(key_data, ENCRYPT)    en_data = sm4_d.sm4_crypt_cbc(iv_data, input_data)    print(en_data, "en_data:")    sm4_d.sm4_set_key(key_data, DECRYPT)    de_data = sm4_d.sm4_crypt_cbc(iv_data, en_data)    print(de_data, "de_data:")    if de_data == input_data:        print("cbc check pass")    else:        print("cbc check fail")        raise BaseException("error")    # file test    file_path = r"test2.txt"    ecb_path_en = r"test2k_ecb_en.txt"    ecb_path_de = r"test2k_ecb_de.txt"    cbc_path_en = r"test2k_cbc_en.txt"    cbc_path_de = r"test2k_cbc_de.txt"    key_data = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]    iv_data = [0x5a] * 16    with open(file_path, 'rb') as f:        file_data = f.read()    # file_data_list = [ord(x) for x in file_data]    file_data_list = list(file_data)    # 1. ECB    sm4_d = Sm4()    sm4_d.sm4_set_key(key_data, ENCRYPT)    en_data = sm4_d.sm4_crypt_ecb(file_data_list)    with open(ecb_path_en, 'w+b') as f:        f.write(bytes(en_data))    sm4_d.sm4_set_key(key_data, DECRYPT)    de_data = sm4_d.sm4_crypt_ecb(en_data)    with open(ecb_path_de, 'w+b') as f:        f.write(bytes(de_data))    if de_data == file_data_list:        print("file decode pass")    else:        print("file decode fail")        raise BaseException('error')    # 2. CBC    sm4_d.sm4_set_key(key_data, ENCRYPT)    en_data = sm4_d.sm4_crypt_cbc(iv_data, file_data_list)    with open(cbc_path_en, 'w+b') as f:        f.write(bytes(en_data))    sm4_d.sm4_set_key(key_data, DECRYPT)    de_data = sm4_d.sm4_crypt_cbc(iv_data, en_data)    with open(cbc_path_de, 'w+b') as f:        f.write(bytes(de_data))    if de_data == file_data_list:        print("file decode pass")    else:        print("file decode fail")        raise BaseException("error")    # log_end()

Java

SM4的Java實現
package ltd.snowland.security.utils;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;public class SM4Base {    public static final int SM4_ENCRYPT = 1;    public static final int SM4_DECRYPT = 0;    private long GET_ULONG_BE(byte[] b, int i) {   long n = (long) (b[i] & 0xff) << 24 | (long) ((b[i + 1] & 0xff) << 16) | (long) ((b[i + 2] & 0xff) << 8) | (long) (b[i + 3] & 0xff) & 0xffffffffL;   return n;    }    private void PUT_ULONG_BE(long n, byte[] b, int i) {   b[i] = (byte) (int) (0xFF & n >> 24);   b[i + 1] = (byte) (int) (0xFF & n >> 16);   b[i + 2] = (byte) (int) (0xFF & n >> 8);   b[i + 3] = (byte) (int) (0xFF & n);    }    private long SHL(long x, int n) {   return (x & 0xFFFFFFFF) << n;    }    private long ROTL(long x, int n) {   return SHL(x, n) | x >> (32 - n);    }    private void SWAP(long[] sk, int i) {   long t = sk[i];   sk[i] = sk[(31 - i)];   sk[(31 - i)] = t;    }    public static final byte[] SboxTable = { (byte) 0xd6, (byte) 0x90, (byte) 0xe9, (byte) 0xfe, (byte) 0xcc,  (byte) 0xe1, 0x3d, (byte) 0xb7, 0x16, (byte) 0xb6, 0x14, (byte) 0xc2, 0x28, (byte) 0xfb, 0x2c, 0x05, 0x2b,  0x67, (byte) 0x9a, 0x76, 0x2a, (byte) 0xbe, 0x04, (byte) 0xc3, (byte) 0xaa, 0x44, 0x13, 0x26, 0x49,  (byte) 0x86, 0x06, (byte) 0x99, (byte) 0x9c, 0x42, 0x50, (byte) 0xf4, (byte) 0x91, (byte) 0xef, (byte) 0x98,  0x7a, 0x33, 0x54, 0x0b, 0x43, (byte) 0xed, (byte) 0xcf, (byte) 0xac, 0x62, (byte) 0xe4, (byte) 0xb3, 0x1c,  (byte) 0xa9, (byte) 0xc9, 0x08, (byte) 0xe8, (byte) 0x95, (byte) 0x80, (byte) 0xdf, (byte) 0x94,  (byte) 0xfa, 0x75, (byte) 0x8f, 0x3f, (byte) 0xa6, 0x47, 0x07, (byte) 0xa7, (byte) 0xfc, (byte) 0xf3, 0x73,  0x17, (byte) 0xba, (byte) 0x83, 0x59, 0x3c, 0x19, (byte) 0xe6, (byte) 0x85, 0x4f, (byte) 0xa8, 0x68, 0x6b,  (byte) 0x81, (byte) 0xb2, 0x71, 0x64, (byte) 0xda, (byte) 0x8b, (byte) 0xf8, (byte) 0xeb, 0x0f, 0x4b, 0x70,  0x56, (byte) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (byte) 0xd1, (byte) 0xa2, 0x25, 0x22, 0x7c,  0x3b, 0x01, 0x21, 0x78, (byte) 0x87, (byte) 0xd4, 0x00, 0x46, 0x57, (byte) 0x9f, (byte) 0xd3, 0x27, 0x52,  0x4c, 0x36, 0x02, (byte) 0xe7, (byte) 0xa0, (byte) 0xc4, (byte) 0xc8, (byte) 0x9e, (byte) 0xea, (byte) 0xbf,  (byte) 0x8a, (byte) 0xd2, 0x40, (byte) 0xc7, 0x38, (byte) 0xb5, (byte) 0xa3, (byte) 0xf7, (byte) 0xf2,  (byte) 0xce, (byte) 0xf9, 0x61, 0x15, (byte) 0xa1, (byte) 0xe0, (byte) 0xae, 0x5d, (byte) 0xa4, (byte) 0x9b,  0x34, 0x1a, 0x55, (byte) 0xad, (byte) 0x93, 0x32, 0x30, (byte) 0xf5, (byte) 0x8c, (byte) 0xb1, (byte) 0xe3,  0x1d, (byte) 0xf6, (byte) 0xe2, 0x2e, (byte) 0x82, 0x66, (byte) 0xca, 0x60, (byte) 0xc0, 0x29, 0x23,  (byte) 0xab, 0x0d, 0x53, 0x4e, 0x6f, (byte) 0xd5, (byte) 0xdb, 0x37, 0x45, (byte) 0xde, (byte) 0xfd,  (byte) 0x8e, 0x2f, 0x03, (byte) 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, (byte) 0x8d, 0x1b, (byte) 0xaf,  (byte) 0x92, (byte) 0xbb, (byte) 0xdd, (byte) 0xbc, 0x7f, 0x11, (byte) 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a,  (byte) 0xd8, 0x0a, (byte) 0xc1, 0x31, (byte) 0x88, (byte) 0xa5, (byte) 0xcd, 0x7b, (byte) 0xbd, 0x2d, 0x74,  (byte) 0xd0, 0x12, (byte) 0xb8, (byte) 0xe5, (byte) 0xb4, (byte) 0xb0, (byte) 0x89, 0x69, (byte) 0x97, 0x4a,  0x0c, (byte) 0x96, 0x77, 0x7e, 0x65, (byte) 0xb9, (byte) 0xf1, 0x09, (byte) 0xc5, 0x6e, (byte) 0xc6,  (byte) 0x84, 0x18, (byte) 0xf0, 0x7d, (byte) 0xec, 0x3a, (byte) 0xdc, 0x4d, 0x20, 0x79, (byte) 0xee, 0x5f,  0x3e, (byte) 0xd7, (byte) 0xcb, 0x39, 0x48 };    public static final int[] FK = { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc };    public static final int[] CK = { 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd,  0xc4cbd2d9, 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,  0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, 0xa0a7aeb5,  0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 };    private byte sm4Sbox(byte inch) {   int i = inch & 0xFF;   byte retVal = SboxTable[i];   return retVal;    }    private long sm4Lt(long ka) {   long bb = 0L;   long c = 0L;   byte[] a = new byte[4];   byte[] b = new byte[4];   PUT_ULONG_BE(ka, a, 0);   b[0] = sm4Sbox(a[0]);   b[1] = sm4Sbox(a[1]);   b[2] = sm4Sbox(a[2]);   b[3] = sm4Sbox(a[3]);   bb = GET_ULONG_BE(b, 0);   c = bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24);   return c;    }    private long sm4F(long x0, long x1, long x2, long x3, long rk) {   return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk);    }    private long sm4CalciRK(long ka) {   long bb = 0L;   long rk = 0L;   byte[] a = new byte[4];   byte[] b = new byte[4];   PUT_ULONG_BE(ka, a, 0);   b[0] = sm4Sbox(a[0]);   b[1] = sm4Sbox(a[1]);   b[2] = sm4Sbox(a[2]);   b[3] = sm4Sbox(a[3]);   bb = GET_ULONG_BE(b, 0);   rk = bb ^ ROTL(bb, 13) ^ ROTL(bb, 23);   return rk;    }    private void sm4_setkey(long[] SK, byte[] key) {   long[] MK = new long[4];   long[] k = new long[36];   int i = 0;   MK[0] = GET_ULONG_BE(key, 0);   MK[1] = GET_ULONG_BE(key, 4);   MK[2] = GET_ULONG_BE(key, 8);   MK[3] = GET_ULONG_BE(key, 12);   k[0] = MK[0] ^ (long) FK[0];   k[1] = MK[1] ^ (long) FK[1];   k[2] = MK[2] ^ (long) FK[2];   k[3] = MK[3] ^ (long) FK[3];   for (; i < 32; i++) {  k[(i + 4)] = (k[i] ^ sm4CalciRK(k[(i + 1)] ^ k[(i + 2)] ^ k[(i + 3)] ^ (long) CK[i]));  SK[i] = k[(i + 4)];   }    }    private void sm4_one_round(long[] sk, byte[] input, byte[] output) {   int i = 0;   long[] ulbuf = new long[36];   ulbuf[0] = GET_ULONG_BE(input, 0);   ulbuf[1] = GET_ULONG_BE(input, 4);   ulbuf[2] = GET_ULONG_BE(input, 8);   ulbuf[3] = GET_ULONG_BE(input, 12);   while (i < 32) {  ulbuf[(i + 4)] = sm4F(ulbuf[i], ulbuf[(i + 1)], ulbuf[(i + 2)], ulbuf[(i + 3)], sk[i]);  i++;   }   PUT_ULONG_BE(ulbuf[35], output, 0);   PUT_ULONG_BE(ulbuf[34], output, 4);   PUT_ULONG_BE(ulbuf[33], output, 8);   PUT_ULONG_BE(ulbuf[32], output, 12);    }    private byte[] padding(byte[] input, int mode) {   if (input == null) {  return null;   }   byte[] ret = (byte[]) null;   if (mode == SM4_ENCRYPT) {  int p = 16 - input.length % 16;  ret = new byte[input.length + p];  System.arraycopy(input, 0, ret, 0, input.length);  for (int i = 0; i < p; i++) { ret[input.length + i] = (byte) p;  }   } else {  int p = input[input.length - 1];  ret = new byte[input.length - p];  System.arraycopy(input, 0, ret, 0, input.length - p);   }   return ret;    }    public void sm4_setkey_enc(SM4_Context ctx, byte[] key) throws Exception {   if (ctx == null) {  throw new Exception("ctx is null!");   }   if (key == null || key.length != 16) {  throw new Exception("key error!");   }   ctx.mode = SM4_ENCRYPT;   sm4_setkey(ctx.sk, key);    }    public void sm4_setkey_dec(SM4_Context ctx, byte[] key) throws Exception {   if (ctx == null) {  throw new Exception("ctx is null!");   }   if (key == null || key.length != 16) {  throw new Exception("key error!");   }   int i = 0;   ctx.mode = SM4_DECRYPT;   sm4_setkey(ctx.sk, key);   for (i = 0; i < 16; i++) {  SWAP(ctx.sk, i);   }    }    public byte[] sm4_crypt_ecb(SM4_Context ctx, byte[] input) throws Exception {   if (input == null) {  throw new Exception("input is null!");   }   if ((ctx.isPadding) && (ctx.mode == SM4_ENCRYPT)) {  input = padding(input, SM4_ENCRYPT);   }   int length = input.length;   ByteArrayInputStream bins = new ByteArrayInputStream(input);   ByteArrayOutputStream bous = new ByteArrayOutputStream();   for (; length > 0; length -= 16) {  byte[] in = new byte[16];  byte[] out = new byte[16];  bins.read(in);  sm4_one_round(ctx.sk, in, out);  bous.write(out);   }   byte[] output = bous.toByteArray();   if (ctx.isPadding && ctx.mode == SM4_DECRYPT) {  output = padding(output, SM4_DECRYPT);   }   bins.close();   bous.close();   return output;    }    public byte[] sm4_crypt_cbc(SM4_Context ctx, byte[] iv, byte[] input) throws Exception {   if (iv == null || iv.length != 16) {  throw new Exception("iv error!");   }   if (input == null) {  throw new Exception("input is null!");   }   if (ctx.isPadding && ctx.mode == SM4_ENCRYPT) {  input = padding(input, SM4_ENCRYPT);   }   int i = 0;   int length = input.length;   ByteArrayInputStream bins = new ByteArrayInputStream(input);   ByteArrayOutputStream bous = new ByteArrayOutputStream();   if (ctx.mode == SM4_ENCRYPT) {  for (; length > 0; length -= 16) { byte[] in = new byte[16]; byte[] out = new byte[16]; byte[] out1 = new byte[16]; bins.read(in); for (i = 0; i < 16; i++) {out[i] = ((byte) (in[i] ^ iv[i])); } sm4_one_round(ctx.sk, out, out1); System.arraycopy(out1, 0, iv, 0, 16); bous.write(out1);  }   } else {  byte[] temp = new byte[16];  for (; length > 0; length -= 16) { byte[] in = new byte[16]; byte[] out = new byte[16]; byte[] out1 = new byte[16]; bins.read(in); System.arraycopy(in, 0, temp, 0, 16); sm4_one_round(ctx.sk, in, out); for (i = 0; i < 16; i++) {out1[i] = ((byte) (out[i] ^ iv[i])); } System.arraycopy(temp, 0, iv, 0, 16); bous.write(out1);  }   }   byte[] output = bous.toByteArray();   if (ctx.isPadding && ctx.mode == SM4_DECRYPT) {  output = padding(output, SM4_DECRYPT);   }   bins.close();   bous.close();   return output;    }}
package ltd.snowland.security.utils;public class SM4_Context{    public int mode;         public long[] sk;         public boolean isPadding;     public SM4_Context()     {        this.mode = 1;        this.isPadding = true;        this.sk = new long[32];    }}

相關詞條

熱門詞條

聯絡我們