👹
Carlos's Tech Blog
  • 🧔ECUs
    • ZYNQ_Documents
      • [ZYNQ] 构建ZYNQ的BSP工程
      • [ZYNQ] 启动流程
      • [ZYNQ] Secure Boot Flow
      • [ZYNQ] Provisioning Guideline
      • [ZYNQ] Decrypting Partition by the Decrypt Agent Using PUF key
      • [ZYNQ] enabling the cryptsetup on ramdisk
      • [ZYNQ] Encrypt external files based on file system using PUF key
      • [ZYNQ] Loading an Encrypted Linux kernel at U-Boot with a KUP Key
      • [ZYNQ] cross-compile the cryptsetup on Xilinx ZYNQ aarch64 platform
      • [ZYNQ] Linux Linaro系统镜像制作SD卡启动
    • S32G_Documents
      • [S32G] Going through the s32g hard/soft platform
      • [S32G] S32g247's Secure Boot using HSE firmware
        • S32g2 HSE key config
        • How S32g verify secure boot image
        • S32g secure boot signature generation
        • How to download and build S32g Secure boot image
        • [S32G] OTA with Secure Boot
    • RT117x_Documents
      • [RT-117x]IMX RT1170 Provisioning Guideline
      • [RT-117x] Going through the MX-RT1170 hard/soft platform
      • [RT-117x] i.MX-RT1170's Secure Boot
        • [RT-117x]Signing image with the HSM (SignServer)
    • LS104x_Documents
      • [LS104x] bsp project
      • [LS104x] boot flow
      • [LS104x] secure boot
      • [LS104x] Application Note, Using the PKCS#11 in TCU platform
      • [LS104x] 使用ostree更新rootfs
      • [LS104x] ostree的移植
      • [LS104x] Starting with Yocto
      • [LS104x] 使用FIT的kernel格式和initramfs
    • IMX6/8_Documents
      • [IMX6] Defining A U-Boot Command
      • NXP IMX6 嵌入式板子一些笔记
      • NXP-imx6 initialization
    • Vehicle_Apps
      • [SecOC] Tree
        • [SecOC] SecOC Freshness and MAC Truncation
  • 😾TECH
    • Rust Arm OS
      • ARMv7m_Using_The_RUST_Cross_Compiler
    • ARM
      • ARM-v7-M
        • 01_ARMv7-M_处理器架构技术综述
        • 02_ARMv7-M_编程模型与模式
        • 03_ARMv7-M_存储系统结构
        • 04_ARMv7-M_异常处理及中断处理
      • ARM-v8-A
        • 02_ARMv8_基本概念
        • 03_ARMv8_指令集介绍_加载指令集和存储指令集
        • 04_ARMv8_指令集_运算指令集
        • 05_ARMv8_指令集_跳转_比较与返回指令
        • 06_ARMv8_指令集_一些重要的指令
        • 0X_ARMv8_指令集_基于汇编的UART驱动
        • 07_ARMv8_汇编器Using as
        • 08_ARMv8_链接器和链接脚本
        • 09_ARMv8_内嵌汇编(内联汇编)Inline assembly
        • 10_ARMv8_异常处理(一) - 入口与返回、栈选择、异常向量表
        • 11_ARMv8_异常处理(二)- Legacy 中断处理
        • 12_ARMv8_异常处理(三)- GICv1/v2中断处理
        • 13_ARMv8_内存管理(一)-内存管理要素
        • 14_ARMv8_内存管理(二)-ARM的MMU设计
        • 15_ARMv8_内存管理(三)-MMU恒等映射及Linux实现
        • 16_ARMv8_高速缓存(一)cache要素
        • 17_ARMv8_高速缓存(二)ARM cache设计
        • 18_ARMv8_高速缓存(三)多核与一致性要素
        • 19_ARMv8_TLB管理(Translation Lookaside buffer)
        • 20_ARMv8_barrier(一)流水线和一致性模型
        • 21_ARMv8_barrier(二)内存屏障案例
      • ARM Boot Flow
        • 01_Embedded_ARMv7/v8 non-secure Boot Flow
        • 02_Embedded_ARMv8 ATF Secure Boot Flow (BL1/BL2/BL31)
        • 03_Embedded_ARMv8 BL33 Uboot Booting Flow
      • ARM Compiler
        • Compiler optimization and the volatile keyword
      • ARM Development
        • 在MACBOOK上搭建ARMv8架构的ARM开发环境
        • Starting with JLink debugger or QEMU
    • Linux
      • Kernel
        • 0x01_LinuxKernel_内核的启动(一)之启动前准备
        • 0x02_LinuxKernel_内核的启动(二)SMP多核处理器启动过程分析
        • 0x21_LinuxKernel_内核活动(一)之系统调用
        • 0x22_LinuxKernel_内核活动(二)中断体系结构(中断上文)
        • 0x23_LinuxKernel_内核活动(三)中断体系结构(中断下文)
        • 0x24_LinuxKernel_进程(一)进程的管理(生命周期、进程表示)
        • 0x25_LinuxKernel_进程(二)进程的调度器的实现
        • 0x26_LinuxKernel_设备驱动(一)综述与文件系统关联
        • 0x27_LinuxKernel_设备驱动(二)字符设备操作
        • 0x28_LinuxKernel_设备驱动(三)块设备操作
        • 0x29_LinuxKernel_设备驱动(四)资源与总线系统
        • 0x30_LinuxKernel_设备驱动(五)模块
        • 0x31_LinuxKernel_内存管理(一)物理页面、伙伴系统和slab分配器
        • 0x32_LinuxKernel_内存管理(二)虚拟内存管理、缺页与调试工具
        • 0x33_LinuxKernel_同步管理_原子操作_内存屏障_锁机制等
        • 01_LinuxDebug_调试理论和基础综述
      • Userspace
        • Linux-用户空间-多线程与同步
        • Linux进程之间的通信-管道(上)
        • Linux进程之间的通信-管道(下)
        • Linux进程之间的通信-信号量(System V)
        • Linux进程之间的通信-内存共享(System V)
        • Linux进程之间的通信-消息队列(System V)
        • Linux应用调试(一)方法、技巧和工具 - 综述
        • Linux应用调试(二)工具之coredump
        • Linux应用调试(三)工具之Valgrind
        • Linux机制之内存池
        • Linux机制之对象管理和引用计数(kobject/ktype/kset)
        • Linux机制copy_{to, from}_user
        • Linux设备树 - DTS语法、节点、设备树解析等
        • Linux System : Managing Linux Services - inittab & init.d
        • Linux System : Managing Linux Services - initramfs
      • Kernel Examples
        • Linux Driver - GPIO键盘驱动开发记录_OMAPL138
        • 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(一)之miscdevice和ioctl
        • 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(二)之cdev与read、write
        • 基于OMAPL138的字符驱动_GPIO驱动AD9833(三)之中断申请IRQ
        • Linux内核调用SPI驱动_实现OLED显示功能
        • Linux内核调用I2C驱动_驱动嵌套驱动方法MPU6050
    • OPTEE
      • 01_OPTEE-OS_基础之(一)功能综述、简要介绍
      • 02_OPTEE-OS_基础之(二)TrustZone和ATF功能综述、简要介绍
      • 03_OPTEE-OS_系统集成之(一)编译、实例、在QEMU上执行
      • 05_OPTEE-OS_系统集成之(三)ATF启动过程
      • 06_OPTEE-OS_系统集成之(四)OPTEE镜像启动过程
      • 07_OPTEE-OS_系统集成之(五)REE侧上层软件
      • 08_OPTEE-OS_系统集成之(六)TEE的驱动
      • 09_OPTEE-OS_内核之(一)ARM核安全态和非安全态的切换
      • 10_OPTEE-OS_内核之(二)对安全监控模式的调用的处理
      • 11_OPTEE-OS_内核之(三)中断与异常的处理
      • 12_OPTEE-OS_内核之(四)对TA请求的处理
      • 13_OPTEE-OS_内核之(五)内存和cache管理
      • 14_OPTEE-OS_内核之(六)线程管理与并发
      • 15_OPTEE-OS_内核之(七)系统调用及IPC机制
      • 16_OPTEE-OS_应用之(一)TA镜像的签名和加载
      • 17_OPTEE-OS_应用之(二)密码学算法和安全存储
      • 18_OPTEE-OS_应用之(三)可信应用的开发
      • 19_OPTEE-OS_应用之(四)安全驱动开发
      • 20_OPTEE-OS_应用之(五)终端密钥在线下发系统
    • Binary
      • 01_ELF文件_目标文件格式
      • 02_ELF文件结构_浅析内部文件结构
      • 03_ELF文件_静态链接
      • 04_ELF文件_加载进程虚拟地址空间
      • 05_ELF文件_动态链接
      • 06_Linux的动态共享库
      • 07_ELF文件_堆和栈调用惯例以ARMv8为例
      • 08_ELF文件_运行库(入口、库、多线程)
      • 09_ELF文件_基于ARMv7的Linux系统调用原理
      • 10_ELF文件_ARM的镜像文件(.bin/.hex/.s19)
    • Build
      • 01_Script_makefile_summary
    • Rust
      • 02_SYS_RUST_文件IO
    • Security
      • Crypto
        • 1.0_Security_计算机安全概述及安全需求
        • 2.0_Security_随机数(伪随机数)
        • 3.0_Security_对称密钥算法加解密
        • 3.1_Security_对称密钥算法之AES
        • 3.2_Security_对称密钥算法之MAC(CMAC/HMAC)
        • 3.3_Security_对称密钥算法之AEAD
        • 8.0_Security_pkcs7(CMS)_embedded
        • 9.0_Security_pkcs11(HSM)_embedded
      • Tools
        • Openssl EVP to implement RSA and SM2 en/dec sign/verify
        • 基于Mac Silicon M1 的OpenSSL 编译
        • How to compile mbedtls library on Linux/Mac/Windows
    • Embedded
      • eMMC启动介质
  • 😃Design
    • Secure Boot
      • JY Secure Boot Desgin
    • FOTA
      • [FOTA] Module of ECUs' FOTA unit design
        • [FOTA] Tech key point: OSTree Deployment
        • [FOTA] Tech key point: repositories role for onboard
        • [FOTA] Tech key point: metadata management
        • [FOTA] Tech key point: ECU verifying and Decrpting
        • [FOTA] Tech key point: time server
      • [FOTA] Local-OTA for Embedded Linux System
    • Provisioning
      • [X-Shield] Module of the Embedded Boards initialization
    • Report
由 GitBook 提供支持
在本页
  • 3.2_Security_对称密钥算法之MAC(CMAC + HMAC)
  • 1. 概念
  • 1.1 消息认证码的实现
  • 1.2 认证加密
  • 1.3 对MAC的攻击
  • 2. HMAC原理
  • 2.1 HMAC过程
  • 2.2 mbedtls示例
  • 3. CBC-MAC和CMAC
  • 3.1 CBC-MAC
  • 3.2 OMAC
  • Ref
  1. TECH
  2. Security
  3. Crypto

3.2_Security_对称密钥算法之MAC(CMAC/HMAC)

https://github.com/carloscn/blog/issues/144

上一页3.1_Security_对称密钥算法之AES下一页3.3_Security_对称密钥算法之AEAD

最后更新于1年前

3.2_Security_对称密钥算法之MAC(CMAC + HMAC)

Digest仅仅能够验证信息的完整性(Integrity),而没有办法确认信息的身份认证(Authetication)。例如,Alice收到一则需要Bob汇款1000元的消息,同时收到汇款消息的hash值,Alice可以计算hash确认1000元这个消息没有被篡改,但问题是,这则消息不是由Bob发的呢?因此就需要更高明的方法来帮助确认这个消息没有被篡改,还要确认这个消息是Bob发的。

消息认证有着广泛的应用,例如:

  • SWIFT:环球银行金融电信协会。银行和银行之间通过SWIFT来传递交易消息,而消息的完整性及对消息的验证都是通过消息验证码。

  • IPSec:互联网基本通信息协议,对通信内容认证和校验都是采用消息验证码。

  • SSL/TLS:通信内容的认证和完整性校验都是通过消息验证码。

常用的MAC有:

1. 概念

这里是一个消息认证码的实例,发送消息的人把明文消息和密钥送入MAC模块中会得到MAC,接收的人使用相同的密钥和明文消息进行计算,然后对MAC值进行对比,就可以确定这个消息是不是发送方发的。需要注意,两方确认身份的凭证和对称加密算法一样,都是通过共享密钥来确认身份的,所以在MAC里面也存在和SYM加解密一样的问题——密钥配送的问题(例如,公钥密码、Diffie-Hellman密钥交换、密钥分配中心等)

1.1 消息认证码的实现

SHA-2之类的单向散列函数可以实现消息认证码,其中一种实现方法称为HMAC。使用AES之类的分组密码也可以实现消息认证码,将密钥作为消息认证码的共享密钥,使用固定的IV值,并用CBC模式将消息全部加密。

Alice认为既然同样持有密钥,对称加密兼顾了消息验证码的功能,只要解密出明文,就可以作为消息验证码使用,Alice想的对吗?

  1. 对称加密明文和密文长度是一致的,如果是一个加解密来确认,对于传输是有负担的,而消息认证码只有几个字节,方便传输;

  2. 如果使用ECB模式,明文块和块之间没有依赖,中间攻击者很可能删除一个完整块或做其他手脚,导致收到信息残缺,此时完整性已经被破坏,这是无法容忍的。

  3. 对于一些随机数或者密钥作为明文(人不可读的信息)的加密,当另一方解密的时候我们很难通过主观断言这就是我们想要的明文,因为对称解密解密错误也是输出一些人类无法识别的数据信息。

因此, Alice考虑的不完全正确。

1.2 认证加密

信息鉴别码不能提供对信息的保密,若要同时实现保密认证,同时需要对信息进行加密。2000年后,关于认证加密逐渐展开(AE或者AEAD)。认证加密是一种将对称密码、消息认证码结合的的技术,因此,同时满足了机密性、完整性和认证三大功能。

1.3 对MAC的攻击

利用MAC的一些特性,可以衍生出一些攻击,还需要一些其他手段来抵御这些攻击,提高可靠性和安全性。

1.3.1 重放攻击

Bob在接受多个重放攻击之后,导致Bob把自己的钱全部转给了Alice,而Alice就会很迷惑了。

对于抵抗重放攻击,我们通常有以下手段,本质上都是让每次的MAC值发生变化,即便是Mallory拿到了某一次的MAC值,也无法进行重放攻击。

  • 使用序号。约定每次发送消息赋予一个递增的序号,在计算MAC的时候将序号值也包含在内。这样Mallory无法计算序号变换的MAC,就没有办法进行攻击了。但这样会增加两人的通信成本,需要共同协商和维护序号。

  • 使用时间戳。约定在发送消息的时候包含当前的时间,如果接到以前的消息,即便是MAC正确也将其作为错误的消息处理,这样就能抵御重放攻击。但这样需要进行时间同步,而且需要考虑到通信的延迟,必须有一定的窗口期,而在窗口期内也是有被重放攻击的风险的。

  • 加扰nonce。约定在通信之前Alice向Bob发送一个随机数,之后Alice会加入这个随机数的MAC计算,Bob也同样做这样的计算。代价就是,增加了通信开销。

1.3.2 推测密钥

此外,密钥务必是由真随机数生成的,否则会被推测出来。

1.3.3 MAC的局限性

因为双方共同持有相同的密钥,所以第三方证明无法确认谁是发送,谁是接受。也同样没有办法防止否认。

第三方证明

Bob再接收到Alice的请求汇款的消息的时候,Bob想向第三方Victor证明这条消息是由Alice发的,Bob是做不到的。因此Victor认为,因为密钥Bob和Alice同样持有,Bob可以自己编写一个假消息,然后做MAC计算。Victor可能会怀疑Bob说谎,而Bob也没有办法来证明。

否认

那同样的Alice真的发了消息,但是不承认自己发了,Alice说谎说是Bob自己编的消息然后算的MAC值,同样Bob也没办法来指出Alice在说谎。

因此,消息验证码没有办法证明出两个持有密钥的人之间的消息传递。而这就要靠数字签名来完成。

2. HMAC原理

2.1 HMAC过程

HMAC有个比较大条的思路就是上面的图片,对消息做MD5或者HASH,求得单向散列,接着对单向散列的数据进行加密。思路是这样的,但是实际上比这个情况要复杂的多。

根據RFC 2104,HMAC的數學公式為:

其中:

  • H为密码杂凑函数(如SHA家族)

  • K为密钥(secret key)

  • m是要认证的消息

  • K'是从原始密钥K导出的另一个秘密密钥(如果K短于散列函数的输入块大小,则向右填充(Padding)零;如果比该块大小更长,则对K进行散列)

  • || 代表串接

  • ⊕ 代表异或(XOR)

  • opad 是外部填充(0x5c5c5c…5c5c,一段十六进制常量)

  • ipad 是内部填充(0x363636…3636,一段十六进制常量)

进行处理的过程,我们可以从:

KEY和IPAD和OPAD与message之间是有信息冗余的,然后经过两轮HASH算法之后得到的MAC,我们可以更清晰的从这个角度来看,message和key和i_pad和o_pad之间的信息冗余:

2.2 mbedtls示例

我们以HMAC384为例,使用mbedtls来完成这个例子:

https://github.com/carloscn/cryptography/blob/master/modules/digest/src/mbedtls_hmac.c

int mbedtls_hmac_sha384(const unsigned char *key,
                        size_t key_byte_size,
                        const unsigned char *input,
                        size_t input_byte_size,
                        unsigned char output[48])
{

    int ret = 0, mret = 0;
    mbedtls_md_info_t *info = NULL;
    mbedtls_md_context_t ctx;

    if (key == NULL ||
        input == NULL ||
        output == NULL) {
        ret = ERROR_COMMON_INPUT_PARAMETERS;
        mbedtls_printf(" * input parameters error, returned %d, line: %d\n",
                       ret, __LINE__);
        goto finish;
    }

    if (key_byte_size == 0 ||
        input_byte_size == 0) {
        ret = ERROR_NONE;
        mbedtls_printf(" * key size or input size == 0, returned %d, line: %d\n",
                       ret, __LINE__);
        goto finish;
    }

    mbedtls_md_init(&ctx);

    info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
    if (NULL == info) {
        ret = ERROR_CRYPTO_INIT_FAILED;
        mbedtls_printf(" * init failed, returned %d, line: %d\n",
                       ret, __LINE__);
        goto ctx_inited;
    }

    mret = mbedtls_md_setup(&ctx, info, 1);
    if (0 != mret) {
        ret = ERROR_CRYPTO_INIT_FAILED;
        mbedtls_printf(" * init failed, returned %d, line: %d\n",
                       ret, __LINE__);
        goto ctx_inited;
    }

    mret = mbedtls_md_hmac_starts(&ctx, key, key_byte_size);
    if (0 != mret) {
        ret = ERROR_CRYPTO_INIT_FAILED;
        mbedtls_printf(" * start failed, returned %d, line: %d\n",
                       ret, __LINE__);
        goto ctx_inited;
    }

    mret = mbedtls_md_hmac_update(&ctx, input, input_byte_size);
    if (0 != mret) {
        ret = ERROR_CRYPTO_ENCRYPT_FAILED;
        mbedtls_printf(" * update failed, returned %d, line: %d\n",
                       ret, __LINE__);
        goto ctx_inited;
    }

    mret = mbedtls_md_hmac_finish(&ctx, output);
    if (0 != mret) {
        ret = ERROR_CRYPTO_ENCRYPT_FAILED;
        mbedtls_printf(" * finish failed, returned %d, line: %d\n",
                       ret, __LINE__);
    }

ctx_inited:
    mbedtls_md_free(&ctx);
finish:
    return ret;
}

测试函数为:

https://github.com/carloscn/cryptography/blob/master/testsuite/src/unit_test_mbedtls.c#L599

static void test_mbedtls_hmac_384(void)
{
    int ret = 0, i = 0;
    unsigned char key[] = {1,5,8,8,9,5,6,204,5,4,8,0,0,0,0};
    unsigned char input[] = {1,5,8,8,9,5,6,204,5,4,8,0,0,0,0};
    unsigned char output[48] = {0};

    ret = mbedtls_hmac_sha384(key,
                              sizeof(key)/sizeof(key[0]),
                              input,
                              sizeof(input)/sizeof(input[0]),
                              output);
    for (i = 0; i < 48; i ++) {
        mbedtls_printf("%x", output[i]);
    }
    mbedtls_printf("\n");
    CU_ASSERT_EQUAL(ret, 0);
}

3. CBC-MAC和CMAC

消息认证码还有另一大类就是CMAC(Cipher-Based Message Authentication Code,CMAC)。提到CMAC就不得不提一下CBC-MAC,CMAC是CBC-MAC的变体,CBC-MAC因为只能对固定长度的消息进行运算,因此存在安全问题,CMAC可以补足这个问题。CMAC最后的输出叫做tag。

3.1 CBC-MAC

CBC-MAC是在实践中应用非常广泛的standard message MAC。当message的长度固定时,CBC-MAC是安全的。CBC-MAC是最为广泛使用的消息认证算法之一,同时它也是一个ANSI标准(X9.17)。CBC-MAC实际上就是对消息使用CBC模式进行加密,取密文的最后一块作为认证码tag。

CBC的构造方法如下:

CBC-MAC和CBC操作模式是相似的但还是存在一些重要的区别:

  1. CBC操作模式使用的初始化向量I V IVIV,这是其安全性的主要保证;但是CBC-MAC却没有用到IV(使用随机向量IV会变得不安全)。

  2. 在CBC操作模式中所有的中间值都被输出作为密文的一部分;而CBC-MAC则只输出最终的tag 。如果CBC-MAC输出每一个则就不再安全。

由于有更好的MAC可以供选择,比如HMAC和OMAC,因此,CBC-MAC很难在一些密码库中看到身影。(至少mbedtls没有这个函数)

3.2 OMAC

One-key MAC (OMAC)是一种消息认证码。在定义上,OMAC分为OMAC1和OMAC2,其中OMAC1就是我们说的CMAC,这个定义是2005年NIST进行推荐的。

业界发现了CBC-MAC存在的一些安全问题(在消息不是等长的时候,破坏fixed -length),进而创建了密码型消息身份验证代码(Cipher-Based Message Authentication Code,CMAC)。CMAC提供与CBC-MAC相同类型的数据源身份验证和完整性,但在数学上更为安全。CMAC 是CBC-MAC 的一种变体,它被批准与AES和三重DES一起使用。

CMAC的核心也是借助CBC-MAC:

算法一共有三个密钥,K, K1, K2, 其中K1和K2可以由K导出。对于CMAC来说,有两种情况,第一种是数据长度恰好就是分组长度的整数倍,对于这种情况,使用K1和最后一个分组异或之后加密得出结果,另一种情况是数据长度不是分组的整数倍,这就要先padding到分组的整数倍,Padding方法是先添加1bit的1, 其余bit填充0, 直到数据满足分组的整数倍。

OMAC和AES的关系是:

mbedtls提供了CMAC的接口,可以使用CMAC接口来计算消息的tag。注,mbedtls需要在编译的时候使能CMAC。CONFIG_MBEDTLS_MAC_CMAC_ENABLED。

int mbedtls_cmac_aes_128_ecb(const unsigned char *key, 
							 size_t key_byte_size,
                             const unsigned char *input, 
                             size_t input_byte_size,
                             unsigned char *output, 
                             size_t *output_byte_size)
{
    int rc = 0;     /* mbedtls layer error code */
    int ret = 0;    /* current layer error code */
    mbedtls_cipher_context_t ctx, *p_ctx = NULL;
    mbedtls_cipher_info_t *info = NULL;

    mbedtls_cipher_init(&ctx);
    p_ctx = &ctx;
    info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
    rc = mbedtls_cipher_setup(p_ctx, info);

    rc = mbedtls_cipher_cmac_starts(p_ctx, key, 
								    BYTE_CONV_BITS_NUM(key_byte_size));

    rc = mbedtls_cipher_cmac_update(p_ctx, input, input_byte_size);

    rc = mbedtls_cipher_cmac_finish(p_ctx, output);

    *output_byte_size = mbedtls_cipher_get_key_bitlen(p_ctx)/8;

    if (NULL != p_ctx) {
        mbedtls_cipher_free(p_ctx);
    }
    return ret;
}

使用示例: https://github.com/carloscn/cryptography/blob/master/modules/digest/src/mbedtls_cmac_exa.c

Ref

在密码学中,消息认证码(英语:Message authentication code,缩写为MAC),又译为消息鉴别码、文件消息认证码、讯息鉴别码、信息认证码,是经过特定算法后产生的一小段信息,检查某段消息的,以及作。它可以用来检查在消息传递过程中,其内容是否被更改过,不管更改的原因是来自意外或是蓄意攻击。同时可以作为消息来源的,确认消息的来源。

消息认证码的算法中,通常会使用(HMAC),或者

消息认证码我们将在 来详细说明,主要包含GCM/GMAC之类的。

重放攻击(英语:replay attack,或称为回放攻击)是一种恶意或欺诈的重复或延迟有效数据的攻击形式。 这可以由发起者或由拦截数据并重新传输数据的来执行。这是“”的一个较低级别版本。

和单向散列函数攻击一样,对消息认证码也可以进行暴力破解以及。对于MAC来说,应保证不能根据MAC值推测出通信双方所使用的密钥。HMAC就是利用sha函数的单向性和抗碰撞性来保证无法根据MAC推测出密钥。

HMAC (有时扩展为 英语:keyed-hash message authentication code, 金钥杂凑讯息鉴别码, 或 英语:hash-based message authentication code,杂凑讯息鉴别码),是一种通过特别计算方式之后产生的(MAC),使用,同时结合一个加密金钥。它可以用来保证资料的完整性,同时可以用来作某个讯息的。

😾
CBC-MAC
DAA
GMAC
HMAC
NMAC
OMAC/CMAC
PMAC
Poly1305
SipHash
UMAC
VMAC
完整性
身份验证
身份验证
带密钥的散列函数
块密码
3.3_Security_对称密钥算法之AEAD
网络
对手
中间人攻击
生日攻击
讯息鉴别码
密码杂凑函数
身份验证
CONFIG_MBEDTLS_MAC_CMAC_ENABLED