了解国密CCM模式示例

举报
码乐 发表于 2026/01/12 09:46:49 2026/01/12
【摘要】 1 简介CCM(Counter with CBC-MAC) 是一种认证加密模式(AEAD),同时提供: 机密性(Encryption) 完整性(Integrity) 身份认证(Authentication)在国密体系中,CCM 通常与 SM4 分组密码结合使用,称为: SM4-CCM它在国标中主要用于需要同时加密和认证的通信与存储场景。 2 CCM 的设计核心将两种成熟...

1 简介

CCM(Counter with CBC-MAC) 是一种认证加密模式(AEAD),同时提供:

    机密性(Encryption)

    完整性(Integrity)

    身份认证(Authentication)

在国密体系中,CCM 通常与 SM4 分组密码结合使用,称为:

		SM4-CCM

它在国标中主要用于需要同时加密和认证的通信与存储场景。

2 CCM 的设计核心

将两种成熟模式组合在一起:

CTR(计数器模式) → 用于加密

CBC-MAC → 用于认证

1️⃣ 整体结构
明文 ──CTR加密──► 密文

└──CBC-MAC────► 认证标签(Tag)

最终输出:

		{ Nonce, Ciphertext, Authentication Tag }

设计理念:

关键设计特性
✅ 1. AEAD 一体化

同时完成:

加密

消息完整性校验

消息来源认证

避免 Encrypt-then-MAC 错误实现

✅ 2. 支持 AAD(附加认证数据)

例如:

协议头

设备 ID

版本号

不加密,但受认证保护

✅ 3. Nonce 驱动安全性

Nonce 不可重复

相同密钥 + 重复 Nonce ⇒ 灾难性安全问题

✅ 4. 可变 Tag 长度

在性能和安全性之间灵活取舍

常见:

64 bit(嵌入式)

128 bit(高安全)

3 适用场景

  • 安全通信协议

国密 TLS(GM/T 0024)

VPN / 专网通信

工控协议安全封装

  • 嵌入式与物联网(IoT)

MCU / 智能卡 / 安全芯片

资源受限环境

无高速乘法单元

📌 相比 GCM:

CCM 代码更小

硬件实现更简单

  • 数据存储保护

安全日志

设备配置文件

传感器数据

  • 国密合规系统

政务系统

金融行业

等保、密评要求系统

4 实现示例

  1. 服务端实现

       import (
           "encoding/base64"
           "encoding/json"
           "fmt"
           "log"
           "net/http"
           "sm4-ccm-api/internal/sm4ccm"
       )
    

全局SM4-CCM实例

			var sm4Cipher *sm4ccm.SM4CCM

API请求结构

      type EncryptRequest struct {
          Data string `json:"data"`
      }

      type EncryptResponse struct {
          EncryptedData string `json:"encrypted_data"`
      }

      type DecryptRequest struct {
          EncryptedData string `json:"encrypted_data"`
      }

      type DecryptResponse struct {
          DecryptedData string `json:"decrypted_data"`
      }

初始化SM4密钥

    func init() {
        // 使用固定密钥或从配置文件读取
        // 实际应用中应该从安全的地方获取密钥
        key := []byte("1234567890abcdef") // 16字节密钥

        var err error
        sm4Cipher, err = sm4ccm.NewSM4CCM(key)
        if err != nil {
            log.Fatalf("Failed to init SM4-CCM: %v", err)
        }
    }

加密处理器

    func encryptHandler(w http.ResponseWriter, r *http.Request) {
        if r.Method != http.MethodPost {
            http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
            return
        }

        var req EncryptRequest
        if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
            http.Error(w, "Invalid request body", http.StatusBadRequest)
            return
        }

        // 加密数据
        ciphertext, err := sm4Cipher.Encrypt([]byte(req.Data))
        if err != nil {
            http.Error(w, fmt.Sprintf("Encryption failed: %v", err), http.StatusInternalServerError)
            return
        }

        // 返回Base64编码的密文
        resp := EncryptResponse{
            EncryptedData: base64.StdEncoding.EncodeToString(ciphertext),
        }

        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(resp)
    }

解密处理器

      func decryptHandler(w http.ResponseWriter, r *http.Request) {
          if r.Method != http.MethodPost {
              http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
              return
          }

          var req DecryptRequest
          if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
              http.Error(w, "Invalid request body", http.StatusBadRequest)
              return
          }

          // 解码Base64密文
          ciphertext, err := base64.StdEncoding.DecodeString(req.EncryptedData)
          if err != nil {
              http.Error(w, "Invalid base64 data", http.StatusBadRequest)
              return
          }

          // 解密数据
          plaintext, err := sm4Cipher.Decrypt(ciphertext)
          if err != nil {
              http.Error(w, fmt.Sprintf("Decryption failed: %v", err), http.StatusBadRequest)
              return
          }

          resp := DecryptResponse{
              DecryptedData: string(plaintext),
          }

          w.Header().Set("Content-Type", "application/json")
          json.NewEncoder(w).Encode(resp)
      }

      func main() {
          // 设置路由
          http.HandleFunc("/api/encrypt", encryptHandler)
          http.HandleFunc("/api/decrypt", decryptHandler)

          // 健康检查
          http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
              w.WriteHeader(http.StatusOK)
              w.Write([]byte("SM4-CCM API Server is running"))
          })

          port := ":8080"
          log.Printf("SM4-CCM API Server starting on %s", port)
          log.Printf("Endpoints:")
          log.Printf("  POST /api/encrypt - Encrypt data")
          log.Printf("  POST /api/decrypt - Decrypt data")
          log.Printf("  GET  /health      - Health check")

          if err := http.ListenAndServe(port, nil); err != nil {
              log.Fatal(err)
          }
      }
  • 客户端实现

      import (
          "bytes"
          "encoding/base64"
          "encoding/json"
          "fmt"
          "io"
          "log"
          "net/http"
          "sm4-ccm-api/internal/sm4ccm"
          "time"
      )
    
      // API客户端
      type SM4CCMClient struct {
          BaseURL string
          Key     []byte
          Client  *http.Client
      }
    
      // 请求响应结构
      type EncryptRequest struct {
          Data string `json:"data"`
      }
    
      type EncryptResponse struct {
          EncryptedData string `json:"encrypted_data"`
      }
    
      type DecryptRequest struct {
          EncryptedData string `json:"encrypted_data"`
      }
    
      type DecryptResponse struct {
          DecryptedData string `json:"decrypted_data"`
      }
    

NewSM4CCMClient 创建客户端

    func NewSM4CCMClient(baseURL string, key []byte) *SM4CCMClient {
        return &SM4CCMClient{
            BaseURL: baseURL,
            Key:     key,
            Client: &http.Client{
                Timeout: 30 * time.Second,
            },
        }
    }

Encrypt 调用远程加密API

    func (c *SM4CCMClient) Encrypt(data string) (string, error) {
        reqBody := EncryptRequest{Data: data}
        jsonData, err := json.Marshal(reqBody)
        if err != nil {
            return "", fmt.Errorf("marshal request failed: %v", err)
        }

        resp, err := c.Client.Post(c.BaseURL+"/api/encrypt", "application/json", bytes.NewBuffer(jsonData))
        if err != nil {
            return "", fmt.Errorf("request failed: %v", err)
        }
        defer resp.Body.Close()

        if resp.StatusCode != http.StatusOK {
            body, _ := io.ReadAll(resp.Body)
            return "", fmt.Errorf("API error: %s - %s", resp.Status, string(body))
        }

        var result EncryptResponse
        if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
            return "", fmt.Errorf("parse response failed: %v", err)
        }

        return result.EncryptedData, nil
    }

Decrypt 调用远程解密API

    func (c *SM4CCMClient) Decrypt(encryptedData string) (string, error) {
        reqBody := DecryptRequest{EncryptedData: encryptedData}
        jsonData, err := json.Marshal(reqBody)
        if err != nil {
            return "", fmt.Errorf("marshal request failed: %v", err)
        }

        resp, err := c.Client.Post(c.BaseURL+"/api/decrypt", "application/json", bytes.NewBuffer(jsonData))
        if err != nil {
            return "", fmt.Errorf("request failed: %v", err)
        }
        defer resp.Body.Close()

        if resp.StatusCode != http.StatusOK {
            body, _ := io.ReadAll(resp.Body)
            return "", fmt.Errorf("API error: %s - %s", resp.Status, string(body))
        }

        var result DecryptResponse
        if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
            return "", fmt.Errorf("parse response failed: %v", err)
        }

        return result.DecryptedData, nil
    }

HealthCheck 检查服务状态

  func (c *SM4CCMClient) HealthCheck() error {
      resp, err := c.Client.Get(c.BaseURL + "/health")
      if err != nil {
          return err
      }
      defer resp.Body.Close()

      if resp.StatusCode != http.StatusOK {
          return fmt.Errorf("health check failed: %s", resp.Status)
      }

      return nil
  }

本地加解密(用于对比验证)

    func localEncryptDecrypt(key []byte) {
        cipher, err := sm4ccm.NewSM4CCM(key)
        if err != nil {
            log.Fatalf("Create cipher failed: %v", err)
        }

        // 测试数据
        testData := "Hello, SM4-CCM! This is a test message. 你好,国密!"

        // 本地加密
        ciphertext, err := cipher.Encrypt([]byte(testData))
        if err != nil {
            log.Fatalf("Local encryption failed: %v", err)
        }
        ciphertextB64 := base64.StdEncoding.EncodeToString(ciphertext)
        fmt.Printf("Local encrypted (base64): %s\n", ciphertextB64)

        // 本地解密
        plaintext, err := cipher.Decrypt(ciphertext)
        if err != nil {
            log.Fatalf("Local decryption failed: %v", err)
        }
        fmt.Printf("Local decrypted: %s\n", string(plaintext))
    }

    func main() {
        // 使用与服务端相同的密钥
        key := []byte("1234567890abcdef")

        // 创建客户端
        client := NewSM4CCMClient("http://localhost:8080", key)

        // 检查服务状态
        fmt.Println("Checking server health...")
        if err := client.HealthCheck(); err != nil {
            log.Fatalf("Health check failed: %v", err)
        }
        fmt.Println("Server is healthy!")

        // 测试数据
        testData := `{
            "user_id": "12345",
            "username": "张三",
            "email": "zhangsan@example.com",
            "sensitive_data": "This is confidential information 2024-01-15",
            "timestamp": "2024-01-15T10:30:00Z"
        }`

        // 调用远程加密API
        fmt.Println("\n=== Remote Encryption ===")
        encrypted, err := client.Encrypt(testData)
        if err != nil {
            log.Fatalf("Remote encryption failed: %v", err)
        }
        fmt.Printf("Encrypted (base64): %s\n", encrypted)

        // 调用远程解密API
        fmt.Println("\n=== Remote Decryption ===")
        decrypted, err := client.Decrypt(encrypted)
        if err != nil {
            log.Fatalf("Remote decryption failed: %v", err)
        }
        fmt.Printf("Decrypted: %s\n", decrypted)

        // 验证数据一致性
        if decrypted == testData {
            fmt.Println("\n✓ Encryption/Decryption successful! Data matches.")
        } else {
            fmt.Println("\n✗ Data mismatch!")
        }

        // 本地加解密对比
        fmt.Println("\n=== Local Encryption/Decryption ===")
        localEncryptDecrypt(key)
    }
  1. 运行说明
    启动服务端:

     cd sm4-ccm-api
     go run server/main.go
    

启动客户端:

在另一个终端

    cd sm4-ccm-api
    go run client/main.go
  1. 测试示例

使用curl测试:

加密请求:

    curl -X POST http://localhost:8080/api/encrypt \
      -H "Content-Type: application/json" \
      -d '{"data": "Hello, SM4-CCM!"}'

解密请求:

  curl -X POST http://localhost:8080/api/decrypt \
    -H "Content-Type: application/json" \
    -d '{"encrypted_data": "BASE64_ENCODED_CIPHERTEXT_HERE"}'

5 小结

  • 生产环境建议

密钥管理:

从环境变量或密钥管理服务获取密钥

定期轮换密钥

安全增强:

添加HTTPS支持

实现API认证(JWT、API Key等)

添加请求频率限制

性能优化:

使用连接池

添加缓存层

监控和日志:

添加详细日志

集成监控指标

这个实现提供了完整的SM4-CCM模式API服务,支持双向加解密操作,并且包含了本地和远程加解密的对比验证功能。

总体而言国密 CCM(SM4-CCM)是一种面向嵌入式和国密合规场景的高可靠 AEAD 模式,通过 CTR 加密 + CBC-MAC 认证,实现安全、可实现性和性能之间的平衡。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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