RFC4493——AES-CMAC

文章目录

  • Abstract
  • 1 Introduction
  • 2 Specification of AES-CMAC
    • 2.1 Basic Definitions
    • 2.2 Overview
    • 2.3 Subkey Generation Algorithm
    • 2.4 MAC Generation Algorithm
    • 2.5 MAC Verification Algorithm
  • 3 Security Considerations
  • 4 Test Vectors
  • 5 测试代码
    • 5.1 C语言版本
    • 5.2 Python语言版本
  • 6 SM4-CMAC
    • 6.1 SM4算法库
    • 6.2 SM4算法测试向量
    • 6.3 SM4-CMAC算法测试向量
  • 参考资料

Abstract

This memo specifies an authentication algorithm based on CMAC with the 128-bit Advanced Encryption Standard (AES). This new authentication algorithm is named AES-CMAC.

1 Introduction

AES-CMAC可以检测有意图的,未鉴权的数据修改,也包括意外修改。
AES比hash函数更容易使用。

2 Specification of AES-CMAC

2.1 Basic Definitions

见原文。

2.2 Overview

Illustration of the two cases of AES-CMAC
如果Message的size是128bit的整数倍,最后一个block在AES_K运算之前要和K1进行XOR运算;否则,最后一个block会使用10^i填充到128bit,并且在AES_K运算之前和K2进行XOR运算。
AES_K:使用秘钥K的AES-128。
M:message,被切分成了M_1,M_2,……, M_n, M_i就表示第i个block。M_1到M_n-1的长度都是128bits。M_n 的长度是≤128bits。
K1和K2是子密钥生成算法生成的两个子密钥。

2.3 Subkey Generation Algorithm

子密钥生成算法的输入输出表示:(K1,K2) := Generate_Subkey(K),K就是AES-128的秘钥,K1和K2就是算法输出结果,两个子密钥。
Algorithm Generate_Subkey

2.4 MAC Generation Algorithm

MAC生成算法被表示为:T := AES-CMAC(K,M,len),K表示秘钥,M就是要保护的message,len是消息长度(单位为octets)。校验MAC可以确定消息的完整性(integrity)和鉴权(authenticity)。
Algorithm AES-CMAC
n就是block个数, flag就表示是否被整除了,true表示正好是128的整数倍,false表示反之。

2.5 MAC Verification Algorithm

Algorithm Verify_MAC

3 Security Considerations

由AES算法提供安全性保证。 AES或者其他加密算法的优势部分在于秘钥K和实现的正确性。密钥的生成方式应满足 RFC 4086的伪随机性要求,并应安全保存。 当且仅当正确使用 AES-CMAC 时,它才能提供满足当前消息身份验证最佳实践的身份验证和完整性。

4 Test Vectors

见原文:https://datatracker.ietf.org/doc/html/rfc4493

5 测试代码

5.1 C语言版本

见原文。

5.2 Python语言版本

from .abscipheralgo import AbsCipherAlgo

class CmacAlgo:
    byte_limit = 16
    bit_limit = 128

    const_rb = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x87')
    const_zero = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

    def xor_bit_limit(self, a:bytearray, b:bytearray) -> bytearray:
        assert len(a) == self.byte_limit
        assert len(b) == self.byte_limit

        out = bytearray(self.byte_limit)
        for i in range(self.byte_limit):
            out[i] = a[i] ^ b[i]
        return out

    def left_shift_one_bit(self, input:bytearray) -> bytearray:
        assert len(input) == self.byte_limit

        overflow = bytearray(1)
        output = bytearray(self.byte_limit)

        for i in reversed(range(self.byte_limit)):
            # make sure is a byte
            output[i] = (input[i] << 1) & 0xFF
            output[i] |= overflow[0]
            overflow[0] = 1 if (input[i] & 0x80) else 0

        return output

    def generate_subkey(self, key: bytearray, cipher_algo:AbsCipherAlgo):
        L = bytearray(self.byte_limit)
        Z = bytearray(self.byte_limit)
        tmp = bytearray(self.byte_limit)

        for i in range(self.byte_limit):
            Z[i] = 0

        L = cipher_algo.encrypt(key, Z)

        # If MSB(L) = 0, then K1 = L << 1
        if (L[0] & 0x80) == 0:
            K1 = self.left_shift_one_bit(L)
        else:
            tmp = self.left_shift_one_bit(L)
            K1 = self.xor_bit_limit(tmp, self.const_rb)

        if K1[0] & 0x80 == 0:
            K2 = self.left_shift_one_bit(K1)
        else:
            tmp = self.left_shift_one_bit(K1)
            K2 = self.xor_bit_limit(tmp, self.const_rb)

        return K1,K2

    """
        将最后一个block以10^i的方式补齐
    """
    def padding(self, last_block: bytearray):
        assert last_block is not None

        pad = bytearray(self.byte_limit)

        for j in range(self.byte_limit):
            if j < len(last_block):
                pad[j] = last_block[j]
            elif j == len(last_block):
                pad[j] = 0x80
            else:
                pad[j] = 0x00
        return pad

    def cmac(self, key: bytearray, input:bytearray, cipher_algo:AbsCipherAlgo) -> bytes:
        K1, K2 = self.generate_subkey(key, cipher_algo)
        # n is number of rounds
        # c语言直接除,因为int截断
        n = (len(input) + self.byte_limit - 1) // self.byte_limit

        if n == 0:
            n = 1
            # last block is not a complete block
            flag = 0
        else:
            # last block is a complete block
            if len(input) % self.byte_limit == 0:
                flag = 1
            else:
                flag = 0

        # 计算M_last
        # last block is complete
        if flag:
            M_last = self.xor_bit_limit(input[(n - 1) * self.byte_limit : ], K1)
        else:
            padded = self.padding(input[(n - 1) * self.byte_limit : ])
            M_last = self.xor_bit_limit(padded, K2)

        X = bytearray(self.byte_limit)
        for i in range(self.byte_limit):
            X[i] = 0
        for i in range(n-1):
            Y = self.xor_bit_limit(X, input[self.byte_limit * i : self.byte_limit * (i + 1)])
            X = cipher_algo.encrypt(key, Y)

        Y = self.xor_bit_limit(X, M_last)
        X = cipher_algo.encrypt(key, Y)

        mac = bytearray(self.byte_limit)
        for i in range(self.byte_limit):
            mac[i] = X[i]

        return mac
from .cmacalgo import CmacAlgo

class Cmac128Algo(CmacAlgo):
    const_rb = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x87')
    const_zero = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

    def __init__(self):
        self.byte_limit = 16
        self.bit_limit = 128

        self.const_rb = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x87')
        self.const_zero = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

from .cmacalgo import CmacAlgo

class Cmac256Algo(CmacAlgo):
    const_rb = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x87')
    const_zero = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

    def __init__(self):
        self.byte_limit = 32
        self.bit_limit = 256

        const_rb = bytearray(
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x87')
        const_zero = bytearray(
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

6 SM4-CMAC

6.1 SM4算法库

Cryptography:https://blog.51cto.com/u_16175518/6765321
CryptSM4:https://cloud.tencent.com/developer/article/1751336?areaId=106001
https://github.com/yang3yen/pysm4

算法padding模式:PKCS7,None

6.2 SM4算法测试向量

明文:
0x40, 0x10, 0xFF, 0xEF, 0x00, 0x45, 0x93, 0x00, 0xAB, 0xCD, 0xEE, 0x00, 0xF0, 0xF4, 0x00, 0x88,
0xA2, 0x19, 0x09, 0x67, 0x87, 0x0C, 0xFF, 0x54, 0xF3, 0x12, 0x50, 0x33, 0xC7, 0xF9, 0x1F, 0xDF,
0x13, 0x73, 0x4F, 0x67, 0xD7, 0xEB, 0xCC, 0x44, 0xF1, 0x12, 0x90, 0x18, 0xA7, 0xA9, 0x1F, 0x03,
0x13, 0x88, 0x4F, 0x67, 0xD7, 0xEB, 0xCC, 0x44, 0xF1, 0x12, 0x46, 0x18, 0x64, 0xA9, 0x1F, 0xEE,

密钥:
0x23, 0x33, 0x41, 0x67, 0x87, 0xEB, 0xFF, 0x54, 0xF1, 0x12, 0x90, 0x11, 0xC7, 0xF9, 0x1F, 0x23

ECB密文:
0x92, 0x31, 0xc8, 0x55, 0xcb, 0x47, 0x0b, 0x07, 0x93, 0x1d, 0xff, 0xb8, 0x14, 0x23, 0x4c, 0x63,
0x06, 0xc9, 0x57, 0x3f, 0x37, 0x12, 0x3b, 0x54, 0xef, 0x61, 0xb6, 0x82, 0x18, 0x83, 0x1f, 0xa2,
0x8a, 0xb6, 0xa9, 0xcc, 0x02, 0xa7, 0xd3, 0x26, 0xeb, 0xeb, 0xe4, 0x5a, 0x48, 0xab, 0xb2, 0xe1,
0x5b, 0x38, 0x67, 0xe9, 0xb4, 0x16, 0x47, 0x6a, 0x0a, 0xf3, 0x9b, 0xef, 0x12, 0xb0, 0x28, 0xb5,

CBC密文:
0x0f, 0xa7, 0x44, 0xda, 0xba, 0x7c, 0x9d, 0xe3, 0xc3, 0xde, 0xab, 0xe7, 0x42, 0x4f, 0x29, 0x68,
0xa2, 0xdd, 0x8e, 0x21, 0x60, 0xd5, 0xbd, 0x5f, 0xf1, 0x63, 0x7e, 0xa7, 0xb2, 0xdf, 0x3f, 0x89,
0x73, 0xc9, 0x72, 0xe6, 0x69, 0x2d, 0xee, 0x23, 0xe5, 0x10, 0xd7, 0x57, 0x7d, 0xc2, 0x1f, 0x0b,
0x6f, 0x12, 0x51, 0x6d, 0xc3, 0x28, 0x2b, 0x07, 0xee, 0xd2, 0x56, 0x05, 0x22, 0x1e, 0x3d, 0xad,

6.3 SM4-CMAC算法测试向量

明文:
0x40, 0x10, 0xFF, 0xEF, 0x00, 0x45, 0x93, 0x00, 0xAB, 0xCD, 0xEE, 0x00, 0xF0, 0xF4, 0x00, 0x88,
0xA2, 0x19, 0x09, 0x67, 0x87, 0x0C, 0xFF, 0x54, 0xF3, 0x12, 0x50, 0x33, 0xC7, 0xF9, 0x1F, 0xDF,
0x13, 0x73, 0x4F, 0x67, 0xD7, 0xEB, 0xCC, 0x44, 0xF1, 0x12, 0x90, 0x18, 0xA7, 0xA9, 0x1F, 0x03,
0x13, 0x88, 0x4F, 0x67, 0xD7, 0xEB, 0xCC, 0x44, 0xF1, 0x12, 0x46, 0x18, 0x64, 0xA9, 0x1F, 0xEE,

密钥:
0x23, 0x33, 0x41, 0x67, 0x87, 0xEB, 0xFF, 0x54, 0xF1, 0x12, 0x90, 0x11, 0xC7, 0xF9, 0x1F, 0x23

CMAC密文:
0xb0, 0xeb, 0x38, 0x61, 0xe6, 0xc5, 0xc1, 0x09, 0x89, 0x61, 0x30, 0x7d, 0x49, 0xb1, 0x7a, 0x7d

参考资料

[1] https://datatracker.ietf.org/doc/html/rfc4493
[2]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/199563.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

逻辑漏洞 暴力破解(DVWA靶场)与验证码安全 (pikachu靶场) 全网最详解包含代码审计

逻辑漏洞 暴力破解(DVWA靶场)与验证码安全 (pikachu靶场) 全网最详解包含代码审计 0x01 前言 在当今互联网的广袤世界中&#xff0c;各式交互平台层出不穷。每一个交互平台几乎都要求用户注册账号&#xff0c;而这些账号则成为我们在数字世界中的身份象征。账号的安全性变得至…

Unity中Shader的BRDF解析(四)

文章目录 前言一、BRDF 中的 IBL二、解析一下其中的参数1、光照衰减系数 &#xff1a;surfaceReduction2、GI镜面反射在不同角度下的强弱 &#xff1a;gi.specular * FresnelLerp (specColor, grazingTerm, nv);在BRDF中&#xff0c;IBL&#xff08;Image Based Light&#xff…

webpack如何设置兼容浏览器的范围​browserslist

Browserslist 是前端工程化不可或缺的工具&#xff0c;无论是处理 js 的 babel 还是处理 css 的 postcss&#xff0c;他们背后都有Browserslist 的身影。 一、如何查看查看所有浏览器和它的市场占有率 我们如何知道现在的浏览器那些被废弃、那些市场占有率高&#xff0c;可以…

vue使用echarts中国地图

需求&#xff1a;Vue3 vite TS 项目内使用 Echarts 5 绘制中国地图。鼠标悬浮省份上面显示指定的数据&#xff0c;地图支持缩放和拖拽的功能&#xff0c;页面放大缩小支持自适应&#xff0c;window.addEventListener(‘resize’, resize); 添加防抖动函数debounce。 一、安装…

Linux MTR(My TraceRoute)command

Internet上有许多小型网络测试工具:Ping、Traceroute、Dig、Host等。 但是&#xff0c;这些工具的功能都比较单一。今天会给大家分享一个包含ping和traceroute功能的工具&#xff1a;MTR 文章目录 什么是MTR&#xff1f;MTR可以提供哪些功能Linux MTR可用选项Linux MTR用法推荐…

如何通过Portal实现消息集成

在数字化时代浪潮下&#xff0c;信息的流通与交互已变得至关重要&#xff0c;不论是在企业内部日常协作&#xff0c;还是与外部客户的紧密沟通&#xff0c;信息的快速、准确、实时传递都成为了确保业务顺畅进行的关键因素、决策精准的核心要素。 为了满足这种日益增长的需求&a…

同旺科技 USB 转 RS-485 适配器

内附链接 1、USB 转 RS-485 适配器 基础版主要特性有&#xff1a;&#xff08;非隔离&#xff09; ● 支持USB 2.0/3.0接口&#xff0c;并兼容USB 1.1接口&#xff1b; ● 支持USB总线供电&#xff1b; ● 支持Windows系统驱动&#xff0c;包含WIN10 / WIN11系统32 / 64位…

Spring Security 6.x 系列(5)—— Servlet 认证体系结构介绍

一、前言 本章主要学习Spring Security中基于Servlet 的认证体系结构&#xff0c;为后续认证执行流程源码分析打好基础。 二、身份认证机制 Spring Security提供个多种认证方式登录系统&#xff0c;包括&#xff1a; Username and Password&#xff1a;使用用户名/密码 方式…

JSP forEach 标签遍历map集合

之前我们说了 普通list 单纯按数量循环 bean类型list的遍历方式 那么 我们forEach标签 也能循环map语法非常简单&#xff0c;和循环list基本是一样的 我们直接上jsp代码 <% page import"java.util.Map" %> <% page import"java.util.HashMap" %…

万人拼团团购小程序源码系统+拼团设置+拼团管理 附带完整的搭建教程

随着互联网的快速发展&#xff0c;电子商务和社交电商的兴起&#xff0c;团购作为一种高效的营销策略和消费方式&#xff0c;受到了广大消费者的热烈欢迎。在此背景下&#xff0c;我们开发了一款基于微信小程序的万人拼团团购系统&#xff0c;旨在为用户提供一种更加便捷、高效…

AI旅游:旅游行业的人工智能成熟艺术适应从实践到表现报告

今天分享的是AI系列深度研究报告&#xff1a;《AI旅游&#xff1a;旅游行业的人工智能成熟艺术适应从实践到表现报告》。 &#xff08;报告出品方&#xff1a;accenture&#xff09; 报告共计&#xff1a;25页 旅行还没有充分利用AI所能做的一 而旅游业比两年前强多了。公司…

winform 程序多语言

新建一个winform程序添加资源文件 在多语言的资源文件中设置key以及value设置button根据环境选择语言文件 namespace WindowsFormsMulLang {public partial class Form1 : Form{public Form1(){InitializeComponent();}public static ResourceManager rm new ResourceManager(…

全新仿某度文库网站源码/在线文库源码/文档分享平台网站源码/仿某度文库PHP源码

源码简介&#xff1a; 全新仿某度文库网站源码/在线文库源码&#xff0c;是以phpMySQL开发的&#xff0c;它是仿某度文库PHP源码。有功能免费文库网站 文档分享平台 实现文档上传下载及在线预览。 仿百度文库是一个以phpMySQL进行开发的免费文库网站源码。仿某度文库实现文档…

20-多线程

20.1线程简介 世间有很多工作都是可以同时完成的。例如&#xff0c;人体可以同时进行呼吸、血液循环、思考问题等活用户既可以使用计算机听歌&#xff0c;也可以使用它打印文件。同样&#xff0c;计算机完全可以将多种活动同时进这种思想放在 Java 中被称为并发&#xff0c;而…

redis基本数据结构

Redis入门&#xff1a;五大数据类型 文章目录 Redis入门&#xff1a;五大数据类型一.概述二.Redis的基本了解三.Redis五大数据类型1.String (字符串)2.List(列表)3.Set集合(元素唯一不重复)4.Hash集合5.zSet(有序集合) 一.概述 什么是Redis Redis&#xff08;Remote Dictiona…

数学建模-基于LightGBM和BP神经网络的互联网招聘需求分析与预测

基于LightGBM和BP神经网络的互联网招聘需求分析与预测 整体求解过程概述(摘要) 就业是民生之本&#xff0c;是发展之基&#xff0c;也是安国之策。2020 年新冠肺炎疫情的爆发&#xff0c;稳就业成为应对疫情、稳定社会的重要保障之一。随着数据新动能的发展&#xff0c;互联网…

什么是Geo Trust OV证书

一、GeoTrust OV证书的介绍 GeoTrust OV证书是由GeoTrust公司提供的SSL证书&#xff0c;它是一种支持OpenSSL的数字证书&#xff0c;具有更高的安全性和可信度。GeoTrust是全球领先的网络安全解决方案提供商&#xff0c;为各类用户提供SSL证书和信任管理服务。GeoTrust OV证书…

数据结构-交换排序(冒泡、快速)

冒泡排序 基本思想 先将第一个记录与第二个记录比较&#xff0c;将较大的记录放到第二个位置上&#xff0c;之后再将第二个记录与第三 个记录比较&#xff0c;将较大的记录放到第三个位置上&#xff0c;如此类推&#xff0c;知道比较完最后一个位置&#xff0c;此时注意到 …

在Rust中处理命令行参数和环境变量

1.摘要 Rust的命令行和环境变量处理在标准库中提供了一整套实现方法, 在本文中除了探索标准库的使用方法之外, 也在不断适应Rust独有的语法特点。在本文中, 我们通过标准库函数的返回值熟悉了迭代器的使用方法, 操作迭代器精确控制保存的内容, 包括字符串和键值对的使用方法。…

GUI加分游戏

需求目标 这个简单的游戏窗口包含一个得分标签和一个按钮。每次点击按钮时&#xff0c;得分增加1&#xff0c;并更新得分标签的显示。 效果 源码 /*** author lwh* date 2023/11/28* description 这个简单的游戏窗口包含一个得分标签和一个按钮。每次点击按钮时&#xff0c;…