密码库LibTomCrypt学习记录——(2.13)分组密码算法的工作模式——CCM加密认证模式

  1. CCM

CCM是加密认证模式,CCM = CTR加密 + CBC-MAC认证。CCM模式看起来比较繁琐,尤其在参数的哦选择上,限制不断。很可能在将来某天被别的方法替代。

参考文献

  1. NIST SP 800-38C.
  1. 加密与MAC生成流程

准备:

  1. 加密算法CIPHER
  2. 密钥K;
  3. counter generation函数
  4. formatting函数
  5. MAC的比特长度Tlen

输入

  1. 随机数N
  2. 消息P,长度为Plen比特
  3. 关联数据(associated data)A

输出

  1. 密文 C(C包含了P对应的密文和MAC信息)

步骤

Step 1.    用formatting函数formatting_function (N, A, P) 生成B0, …,Br

Step 2.    Y0= CIPHK(B0).

Step 3.    For i = 1 to r, do Yi = CIPHK(Bi ⊕ Yi-1).

Step 4.    T=MSBTlen(Yr).

Step 5.    用counter generation函数生成Ctr0, Ctr1, …, Ctrm, 其中m=向上取整(Plen/128).

Step 6.    For j=0 to m, do Sj= CIPHK(Ctrj).

Step 7.    S= S1 || S2 || …|| Sm.

Step 8.    Return C=(P ⊕ MSBPlen(S)) || (T ⊕ MSBTlen(S0)).

其中:

counter generation函数和formatting函数后面介绍;

MSBPlen()表示取最高的Plenbit,其余类似。

加密与MAC生成流程示意图如下:

CCM的加密与MAC生成流程示意图

  1. 解密与验证流程

准备:

  1. 加密算法CIPHER
  2. 密钥K;
  3. counter generation函数
  4. formatting函数
  5. MAC的比特长度Tlen

输入

  1. 随机数N
  2. 密文C,长度为Clen比特
  3. 关联数据(associated data)A

输出

  1. 明文 P(或者INVALID)

步骤

//////////////

Step 1.    If Clen≤Tlen, then return INVALID.

Step 2.    用counter generation函数生成Ctr0, Ctr1, …, Ctrm, 其中m=向上取整(Plen/128).

Step 3.    For j=0 to m, do S j= CIPHK(Ctrj).

Step 4.    S= S1 || S2 || …|| Sm.

Step 5.    P=MSBClen-Tlen(C) ⊕ MSBClen-Tlen(S).

Step 6.    T=LSBTlen(C) ⊕ MSBTlen(S0).

Step 7.    如果 N, A, P无效, then return INVALID,

否则,用formatting函数 formatting_function (N, A, P)生成B0, B1, …, Br.

Step 8.    Set Y0= CIPHK(B0).

Step 9.    For i = 1 to r, do Yj = CIPHK(Bi ⊕ Yi-1).

Step 10.  If T≠MSBTlen(Yr), then return INVALID, else return P.

  1. formatting_function

formatting_function(N, A, P)

B = B0 || B1 || … || Bm = Encode(N) || Encode(A)|| Encode(P)

 

输出参数NAP的含义

  1. N为Nonce,长度为n字节
  2. A为associated data ,长度为a字节
  3. P为Message,长度为p字节
  4. Q为p的定长表示,Q长度为q

这些长度的取值参见 NIST SP 800-38C A.1

 

生成值Bi的含义

  1. B0 = Encode(N),记录了Nounce N 和flag等信息的编码数据。
  2. B1~Bu = Encode(A) = Encode(a) || A || 0...0,记录associated data A的编码数据
  3. Bu+1~Bm = Encode(P) = P || 0...0,记录消息P的编码数据

 

第一个128比特块B0的进一步说明

    1. B0 = Encode(N)记录了Nounce N 和flag等信息的编码数据。
    2. B0(16字节)的结构以及B0的第一个字节Flag2(1字节)的结构如下图

 

B0

字节序号

0

1 …15-q

16-q … 15

 

字节长度

1

15-q

q

 

内容

Flags

N

Q

 

Flags

比特序号

7

6

5

4

3

2

1

0

 

比特长度

Reserved

Adata

(t-2)/2

q-1

 

含义与值

0

有无A

 

 

 

B1Bu的进一步说明

B1Bu = Encode(A)记录associated data A的编码数据

Encode(A) = Encode(a) || A || 0...0 ,

其中0...0表示末尾添加很多零,使得Encode(A)为16字节的倍数

 

 

[a]16

2字节

if 0 < a < 2^16 - 2^8

Encode(a) =

0xff || 0xfe || [a]32

6字节

if 2^16 – 2^8 ≤ a < 2^32

 

0xff || 0xff || [a]64

10字节

If 2^32 ≤ a < 2^64

[a]16表示把a写成16bit长,其余类似。

 

Bu+1Bm的进一步说明

Bu+1Bm = Encode(P)记录消息P的编码数据

Encode(P) =  P || 0...0 ,

其中0...0表示末尾添加很多零,使得Encode(P)为16字节的倍数

  1. counter_generation_function

生成counter block Ctr(i) (16字节),结构与formatting_function(N, A, P) 中的B0非常类似

 

Ctr(i)

字节序号

0

1 …15-q

16-q … 15

 

字节长度

1

15-q

q

 

内容

Flags

N

i

 

Flags

比特序号

7

6

5

4

3

2

1

0

 

比特长度

Reserved

Reserved

000

q-1

 

含义与值

0

0

000

 

 

这些长度的取值参见 NIST SP 800-38C A.1。

 

  1. LibTomCrypt与CCM

 LibTomCrypt中与CCM相关的信息如下:

首先,CCM没有类似别的算法实现中的ccm_state,因为CCM的实现只有一个函数。

在LibTomCrypt中CCM只有一个函数。

int ccm_memory(int cipher, const unsigned char *key, unsigned long keylen, symmetric_key *uskey, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen, unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen, int direction)

 

──────────────────────────────────────

int ccm_memory(int cipher, const unsigned char *key, unsigned long keylen, symmetric_key *uskey, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen, unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen, int direction)

// [功能]   对一段数据进行CCM处理,得到密文和mac值

  1. cipher           // [输入] 密码算法
  2. key                   // [输入] 密钥
  3. keylen          // [输入] 密钥长度
  4. uskey           // [输入] 扩展密钥(可选)
  5. nonce           // [输入] 随机数
  6. noncelen           // [输入] 随机数长度
  7. header              // [输入] Associated Data
  8. headerlen     // [输入] Associated Data长度
  9. pt                // [输入] 明文
  10. ptlen            // [输入] 明文长度
  11. ct                // [输出] 密文
  12. tag               // [输出] mac值
  13. taglen          // [输出] mac值长度
  14. direction            // [输入] 加密(0)还是解密(1)

//[备注]    适合消息不太长的场合。Ptlen决定了消息长度不能超过4G

──────────────────────────────────────

 

如果消息太长,或许需要考虑象omac等工作模式一样,在实际执行中按以下方式操作:

ccm_init(***);//Init需事先设置消息的总长度

while( want_send_message )

{

ccm_process (***);//除最后一次外,每次送入的消息长度必需为分组长度

}

ccm_done (***);//返回MAC值

//以上相应代码需另行完成

 

另外需要注意的是,代码中对各变量的长度设定可能与标准有微小的差异。

 

猜你喜欢

转载自blog.csdn.net/samsho2/article/details/85261325