CCM
CCM是加密认证模式,CCM = CTR加密 + CBC-MAC认证。CCM模式看起来比较繁琐,尤其在参数的哦选择上,限制不断。很可能在将来某天被别的方法替代。
参考文献
NIST SP 800-38C.加密与MAC生成流程
准备:
加密算法CIPHER密钥K; counter generation函数 formatting函数 MAC的比特长度Tlen
输入
随机数N消息P,长度为Plen比特 关联数据(associated data)A
输出
密文 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生成流程示意图
解密与验证流程
准备:
加密算法CIPHER密钥K; counter generation函数 formatting函数 MAC的比特长度Tlen
输入
随机数N密文C,长度为Clen比特 关联数据(associated data)A
输出
明文 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.
formatting_function
formatting_function(N, A, P)
B = B0 || B1 || … || Bm = Encode(N) || Encode(A)|| Encode(P)
输出参数N、A、P的含义
N为Nonce,长度为n字节A为associated data ,长度为a字节P为Message,长度为p字节Q为p的定长表示,Q长度为q
这些长度的取值参见 NIST SP 800-38C A.1
生成值Bi的含义
B0 = Encode(N),记录了Nounce N 和flag等信息的编码数据。B1~Bu = Encode(A) = Encode(a) || A || 0...0,记录associated data A的编码数据Bu+1~Bm = Encode(P) = P || 0...0,记录消息P的编码数据
第一个128比特块B0的进一步说明
B0 = Encode(N)记录了Nounce N 和flag等信息的编码数据。B0(16字节)的结构以及B0的第一个字节Flag2(1字节)的结构如下图
B1~Bu的进一步说明
B1~Bu = Encode(A)记录associated data A的编码数据
Encode(A) = Encode(a) || A || 0...0 ,
其中0...0表示末尾添加很多零,使得Encode(A)为16字节的倍数
[a]16表示把a写成16bit长,其余类似。
Bu+1~Bm的进一步说明
Bu+1~Bm = Encode(P)记录消息P的编码数据
Encode(P) = P || 0...0 ,
其中0...0表示末尾添加很多零,使得Encode(P)为16字节的倍数
counter_generation_function
生成counter block Ctr(i) (16字节),结构与formatting_function(N, A, P) 中的B0非常类似
这些长度的取值参见 NIST SP 800-38C A.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值
cipher // [输入] 密码算法key // [输入] 密钥keylen // [输入] 密钥长度uskey // [输入] 扩展密钥(可选)nonce // [输入] 随机数noncelen // [输入] 随机数长度header // [输入] Associated Dataheaderlen // [输入] Associated Data长度pt // [输入] 明文ptlen // [输入] 明文长度ct // [输出] 密文tag // [输出] mac值taglen // [输出] mac值长度direction // [输入] 加密(0)还是解密(1)
//[备注] 适合消息不太长的场合。Ptlen决定了消息长度不能超过4G
──────────────────────────────────────
如果消息太长,或许需要考虑象omac等工作模式一样,在实际执行中按以下方式操作:
ccm_init(***);//Init需事先设置消息的总长度
while( want_send_message )
{
ccm_process (***);//除最后一次外,每次送入的消息长度必需为分组长度
}
ccm_done (***);//返回MAC值
//以上相应代码需另行完成
另外需要注意的是,代码中对各变量的长度设定可能与标准有微小的差异。