大家好,又见面了,我是你们的朋友全栈君。
OMAC是一种认证模式,LibTomCrypt中涉及的OMAC,而NIST中提到的是CMAC。它们之间的关系是这样的:
为避免基本的MAC算法CBC-MAC存在的安全缺陷,Black和Rogaway对其进行了改进,提出了避免CBC-MAC安全缺陷的XCBC算法。Iwata和Kurosawa对XCBC进一步改进,提出了One-Key CBC-MAC(OMAC),接着又精益求精地提出了OMAC1。而NIST SP 800-38B 中涉及的CMAC其实就是OMAC1。因此,OMAC采用的基本模式是用改进的CBC模式得到MAC值,主要调整是子密钥的生成和最后一个分组的padding上。
参考文献
- NIST SP 800-38B.
- Black, P. Rogaway, A Suggestion for Handling Arbitrary-Length Messages with the CBC MAC, Natl. Inst. Stand. Technol. [Web page], http://csrc.nist.gov/CryptoToolkit/modes/workshop1/.
- J. Black, P. Rogaway, CBC MACs for arbitrary-length messages: The three-key constructions, in Advances in Cryptology—Crypto 2000, Lecture Notes in Computer Science, Vol. 1880, Mihir Bellare, ed., Springer-Verlag (2000), pp. 197–215.
- T. Iwata, K. Kurosawa, OMAC: One-Key CBC MAC, Natl. Inst. Stand. Technol. [Web page], http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/.
- T. Iwata, K. Kurosawa, OMAC: One-Key CBC MAC, in Fast Software Encryption, 10th International Workshop, FSE 2003, Lecture Notes in Computer Science, Vol. 2887, Thomas Johansson, ed., Springer-Verlag (2003), p.p. 129–153.
- T. Iwata, K. Kurosawa, OMAC: One-Key CBC MAC—Addendum, Natl. Inst. Stand. Technol. [Web page], http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/.
- T. Iwata, K. Kurosawa, Stronger Security Bounds for OMAC, TMAC, and XCBC, Natl. Inst. Stand. Technol. [Web page], http://csrc.nist.gov/CryptoToolkit/modes/comments/.
- A. Menezes, P. van Oorschot, S. Vanstone, Handbook of Applied Cryptography, CRC Press, Inc., Boca Raton (1996).
记加密算法为CIPH,其分组大小为b比特;密钥记为K;输出子密钥为K1和K2。子密钥生成步骤如下:
step 1. L = CIPHK(0b).
step 2. If MSB1(L) = 0, then K1 = L << 1;
Else K1 = (L << 1) ⊕ Rb;
step 3. If MSB1(K1) = 0, then K2 = K1 << 1;
Else K2 = (K1 << 1) ⊕ Rb.
step 4. Return K1, K2.
其中:Rb在b为128bit和64bit时的值为
R128 = 012010000111,R64 = 05911011。
012010000111就是前面120bit的0再在低位接10000111,其余类似。
其实,对步骤2和步骤3更准确的理解是,这是在做有限域GF(2b)上的乘以2的乘法,Rb是生成多项式的尾项,即生成多项式为f(x)=x128+Rb。此有限域上的b = a2的运算过程就是:。这样一来,两个子密钥的来历就是:
子密钥生成的流程图(生成子密钥K1和K2)
- MAC生成
记加密算法为CIPH,其分组大小为b比特;密钥记为K;输入消息为Mlen比特长的M,输出MAC值为Tlen比特长的T。
MAC生成CMAC(K, M, Tlen)(也可以记为CMAC(K, M))步骤如下:
step 1. 使用子密钥生产算法生成子密钥K1和K2;
step 2. If Mlen = 0, n = 1; else, n = 向上取整(Mlen/b).
step 3. 将消息M按照分组大小b进行划分
M =M1 || M2 || … || Mn-1 || Mn*,
这里的M1, M2,…, Mn-1是完整分组,而最后一个分组Mn*可能完整也可能不完整。
step 4. 若Mn*是完整分组,Mn = K1 ⊕ Mn*; 否则,Mn = K2 ⊕ (Mn*||10j),j = nb-Mlen-1。
step 5. Let C0 = 0b.
step 6. For i = 1 to n, Ci = CIPHK(Ci-1 ⊕ Mi).
step 7. T = MSBTlen(Cn).
step 8. Return T.
MAC生成的流程图(MAC值为T)
- LibTomCrypt与OMAC
LibTomCrypt中与OMAC相关的信息如下:
typedef struct {
int cipher_idx, //密码算法索引值
buflen, // block中数据的长度
blklen; // 分块大小,即密码算法分组大小
unsigned char block[MAXBLOCKSIZE], //缓存尾巴上的数据
prev[MAXBLOCKSIZE], //上一块加密数据
Lu[2][MAXBLOCKSIZE];// Lu[0] is Subkey K1, Lu[1] is Subkey K2
symmetric_key key; // 扩展密钥
} omac_state;
其中
- block[MAXBLOCKSIZE]缓存尾巴上的数据,当数据长len为blklen的倍数时,block存储最后一个blklen的数据;否则,存储len mod blklen 个字节的末尾数据
在LibTomCrypt中omac主要有以下函数
int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen);
int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen);
int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen);
int omac_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen);
int omac_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, …);
int omac_file(int cipher, const unsigned char *key, unsigned long keylen, const char *filename, unsigned char *out, unsigned long *outlen);
int omac_test(void);
──────────────────────────────────────
int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen);
// [功能] 初始化
- omac // [输入/输出] OMAC状态
- cipher // [输入] 初始化向量
- key // [输入] 密钥
- keylen // [输入] 密钥长度
──────────────────────────────────────
──────────────────────────────────────
int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen);
// [功能] 处理输入信息
- omac // [输入/输出] OMAC状态
- in // [输入] 消息
- inlen // [输入] 消息长度
//[备注] 消息长度可以不是分组长度的倍数。可多次调用此函数输入消息
──────────────────────────────────────
──────────────────────────────────────
int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen);
// [功能] 结束并输出mac值
- omac // [输入/输出] OMAC状态
- out // [输出] mac值
- outlen // [输出] mac值长度
//[备注] 实际输出长度 = min ( 输入的outlen长度, 分组长度 )
OMAC通常的执行流程是:
omac_init(***);
while( want_send_message )
{
omac_ process (***);//每次送入的消息长度可以为任意值
}
omac_ done (***);
──────────────────────────────────────
──────────────────────────────────────
int omac_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen);
// [功能] 计算一段数据的mac值
- cipher // [输入] 密码算法
- key // [输入] 密钥
- keylen // [输入] 密钥长度
- in // [输入] 消息
- inlen // [输入] 消息长度
- out // [输出] mac值
- outlen // [输出] mac值长度
//[备注] 适合消息不太长的场合。实际处理过程为
omac_init(***);
omac_ process (***);
omac_ done (***);
──────────────────────────────────────
──────────────────────────────────────
int omac_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, …);
// [功能] 计算多段数据的mac值
- cipher // [输入] 密码算法
- key // [输入] 密钥
- keylen // [输入] 密钥长度
- out // [输出] mac值
- outlen // [输出] mac值长度
- in // [输入] 消息
- inlen // [输入] 消息长度
- … // [输入] 可选参数,先跟消息地址,再跟消息长度,如此反复
//[备注] 类似omac_memory,只不过处理的是多段数据
──────────────────────────────────────
──────────────────────────────────────
int omac_file(int cipher, const unsigned char *key, unsigned long keylen, const char *filename, unsigned char *out, unsigned long *outlen);
// [功能] 计算文件的mac值
- cipher // [输入] 密码算法
- key // [输入] 密钥
- keylen // [输入] 密钥长度
- filename // [输入] 文件名
- out // [输出] mac值
- outlen // [输出] mac值长度
//[备注] 适合消息不太长的场合。实际处理过程为
omac_init(***);
while ( file_not end )
{
fread(***);
omac_ process (***);
}
omac_ done (***);
──────────────────────────────────────
──────────────────────────────────────
int omac_test(void);
// [功能] 测试函数
──────────────────────────────────────
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/159192.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...