CCM加密模式及客户端示例

举报
码乐 发表于 2025/12/23 10:36:12 2025/12/23
【摘要】 1 简介CCM (Counter with CBC-MAC) - 计数器与 CBC-MAC 模式定义:CCM 是 CTR 与 CBC-MAC 的组合,提供 AEAD 功能。工作原理:先用 CBC-MAC 计算认证标签(基于明文、AAD 和 nonce)。然后用 CTR 加密明文。加密:MAC = CBC-MAC(K, B),其中 B 是格式化的块(nonce、长度、AAD、明文);然后 C...

1 简介

CCM (Counter with CBC-MAC) - 计数器与 CBC-MAC 模式

定义:CCM 是 CTR 与 CBC-MAC 的组合,提供 AEAD 功能。
工作原理:
先用 CBC-MAC 计算认证标签(基于明文、AAD 和 nonce)。
然后用 CTR 加密明文。
加密:MAC = CBC-MAC(K, B),其中 B 是格式化的块(nonce、长度、AAD、明文);然后 C = P \oplus CTR_stream,Tag = MAC \oplus CTR_0。

解密:验证 Tag 后解密。

优缺点:
优点:单密钥、提供认证、适合资源受限设备。
缺点:两次遍历数据(MAC + 加密),不如 GCM 高效;nonce 必须唯一。

安全考虑:IND-CCA2 安全,但对 nonce 长度有要求(7-13 字节)。SM4-CCM 在无线传感器网络标准中常见。
SM4 应用:IoT 设备加密、Zigbee 协议。

2 CCM模式 vs SCM标准模式分析

  • 基本概念对比

1.1 SM4标准模式

SM4标准定义了几种基础分组密码模式:

      ECB (Electronic Codebook):电子密码本模式

      CBC (Cipher Block Chaining):密码分组链接模式

      CFB (Cipher Feedback):密码反馈模式

      OFB (Output Feedback):输出反馈模式

      CTR (Counter):计数器模式

这些是基础的分组密码模式,主要提供机密性。

  • CCM模式

CCM (Counter with CBC-MAC):计数器模式与CBC-MAC结合

属于认证加密模式 (Authenticated Encryption)

同时提供机密性 + 完整性认证 + 消息认

CCM vs GCM:

  • CCM: 软件实现较好,抗侧信道攻击
  • GCM: 硬件加速更好,支持流处理
  • CCM: 专利问题(已过期)
  • GCM: NIST推荐,更常用

3 客户端实现示例

  1. 创建SM4-CCM加解密模块

     require github.com/tjfoc/gmsm v1.4.1
     internal/sm4ccm/sm4ccm.go:
    
    
     import (
         "crypto/cipher"
         "crypto/rand"
         "errors"
         "fmt"
         "io"
    
         "github.com/tjfoc/gmsm/sm4"
     )
    

SM4CCM 结构体

    type SM4CCM struct {
        key []byte
    }

NewSM4CCM 创建SM4-CCM实例

      func NewSM4CCM(key []byte) (*SM4CCM, error) {
          if len(key) != 16 {
              return nil, errors.New("SM4 key must be 16 bytes")
          }
          return &SM4CCM{key: key}, nil
      }

Encrypt 加密数据 (CCM模式)

    func (s *SM4CCM) Encrypt(plaintext []byte) ([]byte, error) {
        // 创建SM4块
        block, err := sm4.NewCipher(s.key)
        if err != nil {
            return nil, fmt.Errorf("create cipher failed: %v", err)
        }

生成随机nonce (13字节推荐用于CCM)

        nonce := make([]byte, 13)
        if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
            return nil, fmt.Errorf("generate nonce failed: %v", err)
        }

创建CCM模式的AEAD

        aead, err := cipher.NewCCM(block, 7, 13) // tag长度7字节,nonce长度13字节
        if err != nil {
            return nil, fmt.Errorf("create CCM failed: %v", err)
        }

附加数据(可以为空)

			additionalData := []byte("CCM Mode")

加密

				ciphertext := aead.Seal(nil, nonce, plaintext, additionalData)

返回 nonce + ciphertex

          result := make([]byte, len(nonce)+len(ciphertext))
          copy(result[:13], nonce)
          copy(result[13:], ciphertext)

            return result, nil
        }

Decrypt 解密数据

      func (s *SM4CCM) Decrypt(ciphertext []byte) ([]byte, error) {
          if len(ciphertext) < 13 {
              return nil, errors.New("ciphertext too short")
          }

            block, err := sm4.NewCipher(s.key)
            if err != nil {
                return nil, fmt.Errorf("create cipher failed: %v", err)
            }

创建CCM模式的AEAD

          aead, err := cipher.NewCCM(block, 7, 13)
          if err != nil {
              return nil, fmt.Errorf("create CCM failed: %v", err)
          }

分离nonce和密文

          nonce := ciphertext[:13]
          actualCiphertext := ciphertext[13:]

附加数据(必须与加密时一致)

				additionalData := []byte("CCM Mode")

解密

          plaintext, err := aead.Open(nil, nonce, actualCiphertext, additionalData)
          if err != nil {
              return nil, fmt.Errorf("decrypt failed: %v", err)
          }

          return plaintext, nil
      }

GenerateKey 生成随机SM4密钥

    func GenerateKey() ([]byte, error) {
        key := make([]byte, 16)
        if _, err := io.ReadFull(rand.Reader, key); err != nil {
            return nil, err
        }
        return key, nil
    }
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。