【IC卡 国密SM4算法 密钥分散,加解密,MAC计算】

这篇具有很好参考价值的文章主要介绍了【IC卡 国密SM4算法 密钥分散,加解密,MAC计算】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


在这里记录一下工作中调查国密算法SM4过程中掌握的心得体会。

密钥分散

对基于 SM4 的分散算法的描述。
密钥分散算法简称 Diversify,是指将一个双长度的密钥 MK,对分散数据进行处理,推导出双长度的密钥 DK。
将分散数据的 8 个字节,作为输入数据的左半部分:
将分散数据的 8 个字节求反,作为输入数据的右半部分;
用 MK 对输入数据进行 SM4 运算。

        /// <summary>
        /// 基于SM4的分散算法。
        /// 将分散数据的 8 个字节,作为输入数据的左半部分;将分散数据的 8 个字节求反,作为输入数据的右半部分; 用CKKey 对输入数据进行 SM4 运算。
        /// </summary>
        /// <param name="SourceData"></param>
        /// <param name="srcIndex"></param>
        /// <param name="CKKey"></param>
        /// <param name="subKey"></param>
        public static void GetSubKey_SM4(byte[] SourceData, int srcIndex, byte[] CKKey, ref byte[] subKey)
        {
            int num;
            byte[] pvInOutputBlock = new byte[0x10];
            for (num = 0; num < 8; num++)
            {
                pvInOutputBlock[num] = SourceData[num + srcIndex];
            }

            for (num = 0; num < 8; num++)
            {
                pvInOutputBlock[8 + num] = (byte)~SourceData[num + srcIndex];
            }

            CombinedSM4Operation(ref pvInOutputBlock, null, CKKey, DES.ZERO_CBC_IV | DES.TRIPLE_DES_ENCRYPTION_EDE2, 1);
            Array.Copy(pvInOutputBlock, 0, subKey, 0, 16);
        }

加解密

SM4属于对称算法,加密和解密密钥相同。
SM4算法:
SM4算法是指使用长度为16字节的密钥K将16字节明文数据块加密成密文数据块,如下所
示:
Y = SM4 (K) [X]
解密的方式如下:
X = SM4-1 (K)[X]
计算过程:
数据的加密解密计算采用ECB 作为块操作模式按照如下步骤对数据进行加密:
第一步: 用Ld(1 字节)表示明文数据的长度,在明文数据前加上Ld 产生新的数据块。
第二步:将该数据块分成以分组长度 128 位为单位的数据块,表示为块 1、块 2、…、块 n。
第三步:如果最后(或唯一) 的数据块的长度是分组长度,转到第四步:如果不足分组长度,则在其后加入16进制数’80’,如果达到分组长度,则转到第四步:否则在其后加入16进制数’00’直到长度达到分组长度。
第四步:使用加密密钥对每一个数据块进行加密。
第五步: 计算结束后,所有加密后的数据块依照原顺序连接在一起。

按照如下步骤对数据进行解密:
第一步: 将该数据块分成以分组长度128位为单位的数据块,,表示为块1、块2、…、块n。
第二步: 使用解密密钥对每个数据块进行解密。
第三步: 计算结束后,所有解密后的数据块依照原顺序连接在一起。
第四步: 第一个字节为 Ld,从第二字节起,取前 Ld 字节数据作为明文输出。

使用了BouncyCastle.Crypto开源库,NuGet安装即可。
代码中的一些变量自己定义。

        /// <summary>
        /// SM4加解密算法
        /// 数据的加密解密计算采用ECB作为块操作模式。
        /// </summary>
        /// <param name="pvInOutputBlock">数据块</param>
        /// <param name="pvCbcBlock">保留</param>
        /// <param name="pbKeyString">密钥</param>
        /// <param name="eSm4Mode">加解密模式</param>
        /// <param name="cnt">轮数</param>
        public static void CombinedSM4Operation(ref byte[] pvInOutputBlock, byte[] pvCbcBlock, byte[] pbKeyString, uint eSm4Mode, uint cnt)
        {
            // 补0到最小位数
            string data = CommonFunc.Instance.ConvertByteToString(pvInOutputBlock);
            if ((data.Length % 0x20) != 0)
            {
                if ((data.Length % 0x20) != 0)
                {
                    data = data.PadRight(0x20 * ((data.Length / 0x20) + (((data.Length % 0x20) == 0) ? 0 : 1)), '0');
                }
            }
            pvInOutputBlock = CommonFunc.Instance.ConvertStringToByte(data);

            bool forEncryption = (eSm4Mode == (DES.ZERO_CBC_IV | DES.TRIPLE_DES_ENCRYPTION_EDE2)); // true 表示加密, false表示解密

            SM4Engine sm4 = new SM4Engine(); // 创建 SM4 算法实例
            
            sm4.Init(forEncryption, new KeyParameter(pbKeyString)); // 设置加密模式和密钥 默认ECB模式

            byte[] encryptedData = new byte[pvInOutputBlock.Length]; // 存储加密后的数据

            if (cnt == 0)
            {
                cnt = 1;
            }
            // 按照 ECB 算法使用加密密钥对每一个数据块进行加密
            for (int i = 0; i < cnt; i ++)
            {
                if (pvInOutputBlock.Length < (i + 1) * sm4.GetBlockSize())
                { break; }
                sm4.ProcessBlock(pvInOutputBlock, i* sm4.GetBlockSize(), encryptedData, i* sm4.GetBlockSize());
            }

            Array.Copy(encryptedData, pvInOutputBlock, encryptedData.Length);
        }

MAC计算

报文认证码的计算采用分组长度为 128 位分组计算,采用 CBC 分组操作模式按照如下步骤计算报文认证码 MAC:
第一步: 终端 GET CHALLENGE 命令从 IC 获得一个 4/8/16 字节随机数,后补 12/8/0字节‘00’作为初始数据。
第二步:将所有输入数据按指定顺序连接成一个数据块。
第三步:将该数据块分成以分组长度 128 位为单位的数据块,表示为块 1、块 2、···、块n。
第四步:在最后的数据块后加入 16 进制数’80’,如果此时达到分组长度,则转到第五否则在其后加入 16 进制数‘00’直到长度达到分组长度。
第五步:按下图所述的算法对这些数据块使用指定密钥进行加密来产生 MAC。
第六步: 返回MAC计算数据,具体怎么取还要看需求。一般取计算结果前4字节长度的MAC。

这是第五步中的算法代码

        /// <summary>
        ///  SM4 MAC计算方法
        /// </summary>
        /// <param name="pvSubKeys">密钥</param>
        /// <param name="pvCbcBlock">IV</param>
        /// <param name="pbInputData">数据块</param>
        /// <param name="eNBytes">保留</param>
        /// <param name="pbMac32Out">返回值mac</param>
        public static void CalcPBOCMac_SM4(byte[] pvSubKeys, byte[] pvCbcBlock, byte[] pbInputData, uint eNBytes, ref byte[] pbMac32Out)
        {
            // 补0到最小位数
            string data = CommonFunc.Instance.ConvertByteToString(pvCbcBlock);
            if ((data.Length % 0x20) != 0)
            {
                if ((data.Length % 0x20) != 0)
                {
                    data = data.PadRight(0x20 * ((data.Length / 0x20) + (((data.Length % 0x20) == 0) ? 0 : 1)), '0');
                }
            }

            pvCbcBlock = CommonFunc.Instance.ConvertStringToByte(data);

            byte[] szTempArray = new byte[16];
            byte[] szBlockArray = new byte[16];
            Array.Clear(szBlockArray, 0, szBlockArray.Length);
            Array.Clear(szTempArray, 0, szTempArray.Length);
            if (pvCbcBlock == null)
            {
                pvCbcBlock = szBlockArray;
            }
            uint num = eNBytes / 16u;
            if (num * 16 < eNBytes)
            {
                num++;
                pbInputData[eNBytes] = 128;
            }

            // 创建SM4引擎
            SM4Engine sm4Engine = new SM4Engine();

            // 设置为加密模式,并设置密钥
            sm4Engine.Init(true, new KeyParameter(pvSubKeys));
  
            byte[] encryptedData = new byte[16]; // 存储加密后的数据
            for (uint num2 = 0u; num2 < num; num2++)
            {
                DataXOR16(ref szTempArray, pbInputData, (int)(num2 * 16), pvCbcBlock, 0);
                sm4Engine.ProcessBlock(szTempArray, 0, encryptedData, 0);
                Array.Copy(encryptedData, pvCbcBlock, 16);
            }

            Array.Copy(encryptedData, pbMac32Out, 4);
        }
		// 异或方法 
        private static void DataXOR16(ref byte[] xoData, byte[] des, int desIndex, byte[] source, int sourceIndex)
        {
            for (byte i = 0; i < 16; i = (byte)(i + 1))
            {
                xoData[i] = (byte)(des[i + desIndex] ^ source[i + sourceIndex]);
            }
        }

实例测试

TODO 之后更新文章来源地址https://www.toymoban.com/news/detail-733809.html

到了这里,关于【IC卡 国密SM4算法 密钥分散,加解密,MAC计算】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 国密算法SM2/3/4简单比较,以及基于Java的SM4(ECB模式,CBC模式)对称加解密实现

    常用的国密算法包含SM2,SM3,SM4。以下针对每个算法使用场景进行说明以比较其差异 SM2:非对称加密算法,可以替代RSA 数字签名,SM2为非对称加密,加解密使用一对私钥和公钥,只有签名发行者拥有私钥,可用于加密,其他需要验证解密或验签者使用公钥进行。如果使用公

    2024年04月13日
    浏览(41)
  • SpringBoot实现国密SM4加密、解密

    SM4.0(原名SMS4.0)是中华人民共和国政府采用的一种分组密码标准,由国家密码管理局于2012年3月21日发布。相关标准为“GM/T 0002-2012《SM4分组密码算法》(原SMS4分组密码算法)”。 在商用密码体系中,SM4主要用于数据加密,其算法公开,分组长度与密钥长度均为128bit,加密算

    2024年02月07日
    浏览(63)
  • 国密SM4对称加密Java加解密

    提示:国密SM4对称加密Java加解密 国家密码管理局 参考博文 SM4.0(原名SMS4.0)是中华人民共和国政府采用的一种分组密码标准,由国家密码管理局于2012年3月21日发布。相关标准为“GM/T 0002-2012《SM4分组密码算法》(原SMS4分组密码算法)”。 SM4 代码如下(示例): 在密码学中

    2024年02月11日
    浏览(54)
  • 前端使用国密SM4进行加密、解密

    前端/后端使用 国密SM4 进行加密/解密, 【注意】前后端配合加解密时,需要我们 自定义密钥 ,一般由后端提供 下载 sm4util 依赖 sm4util 依赖使用说明 使用 - ECB 模式加解密 后端代码参考:https://blog.csdn.net/qq_48922459/article/details/122130283 这种办法好像只能使用默认密钥 key,不能

    2023年04月23日
    浏览(56)
  • 前端使用国密sm2和sm4进行加解密

    国密SM:国密算法,即国家商用密码算法。是由国家密码管理局认定和公布的密码算法标准及其应用规范,其中部分密码算法已经成为国际标准。如SM系列密码,SM代表商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术。 安装SM加密依赖 SM2 封装 将sm2的加密解密

    2024年02月08日
    浏览(60)
  • 前端国密加解密使用方法SM2、SM3、SM4

       国密算法,即国家商用密码算法。是由国家密码管理局认定和公布的密码算法标准及其应用规范,其中部分密码算法已经成为国际标准。如SM系列密码,SM代表商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术。      不多废话直接上干货 项目中 可能存在

    2023年04月09日
    浏览(51)
  • java实现国密SM4的加密和解密方式(即时通讯的消息对话加密采用SM2还是SM4)

    1.对于即时通讯的消息对话加密采用SM2还是SM4更合适? 对于即时通讯的消息对话加密,建议采用SM4对称加密算法,而不是SM2非对称加密算法。 SM2主要用于数字签名和密钥交换,其加密速度比SM4慢,而且SM2不太适合对长消息进行加密,因为它只能对比较短的数据块进行加密,这

    2024年02月07日
    浏览(82)
  • 医保移动支付加密解密请求工具封装【国密SM2SM4】

    医保移动支付加密解密请求工具封装 定点医药机构向地方移动支付中心发起费用明细上传、支付下单、医保退费等交易时需要发送密文,由于各大医疗机构厂商的开发语各不相同,可能要有java的、c#的、python的、pb的、nodjs的、php的、还可能有Delphi的等。。。。很多开发语言

    2024年01月21日
    浏览(90)
  • C# 实现 国密SM4/ECB/PKCS7Padding对称加密解密

    C# 实现 国密SM4/ECB/PKCS7Padding对称加密解密,为了演示方便本问使用的是Visual Studio 2022 来构建代码的 1、新建项目,之后选择 项目 鼠标右键选择  管理NuGet程序包管理,输入  BouncyCastle 回车 添加BouncyCastle程序包 2、代码如下:CBC模式 代码如下:ECB模式 3、运行 4、SM4密码算法

    2024年02月11日
    浏览(66)
  • Delphi SM2/SM4国密算法

        最近忙个医保平台的项目,涉及SM2/SM4的签名,验签,加密,解密的业务操作过程。毕竟现在用Delpih的人不是很多,懂这方面的技术的人也更少,能涉及密码算法的少之更少,网上也能搜到一些开源的代码,也由于使用的人少,未加通过业务系统来验证,所以存在不少Bu

    2024年02月11日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包