EAX是一种加密认证模式,它可以对消息明文进行加密,同时对消息明文和关联信息(Associated Data)进行认证,当然此关联信息也可以为空。EAX由Mihir Bellare等人在2003年提交给NIST,其目的是希望取代现在的CCM标准。因为相较之下,EAX有更好的表现,而CCM显得较为复杂。但到目前为止,EAX还没有取代CCM。
EAX参考文献
- Mihir Bellare, Phillip Rogaway, and David Wagner, The EAX Mode of Operation, FSE 2004, LNCS 3017, pp. 389–407, 2004.
- Mihir Bellare, Phillip Rogaway, and David Wagner, The EAX Mode of Operation(A Two-Pass Authenticated-Encryption Scheme Optimized for Simplicity and Efficiency), A preliminary full version appears in Fast Software Encryption ’04, Lecture Notes in Computer Science.
- EAX算法
EAX加密流程
输入:
- K:密钥
- M:明文
- N:随机数
- H:不需加密仅需认证的关联信息
输出:
- C:密文
- CT:认证MAC值(t bit)
EAX的加密流程图如下:
图 EAX加密流程图
- LibTomCrypt与EAX
记录EAX信息的结构体是eax_state,其结构如下
typedef struct {
unsigned char N[MAXBLOCKSIZE];
symmetric_CTR ctr;
omac_state headeromac, ctomac;
} eax_state;//ctomac记录了OMAC_K( [2]_128 || c)的信息。
参数说明
- N = LTC_OMAC_0K(nonce) = OMAC_K( [0]_128 || nonce),在eax_init()中被计算出来,在eax_done()中使用此N值。
- ctr记录了CTR加密模式的工作状态。
- headeromac记录了OMAC_K( [1]_128 || header)的信息。为方便继续添加header,故而采用 omac_state,这样以后可以调用eax_addheader()添加header。
- ctomac记录密文的omac信息状态。
eax涉及函数如下。
int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen);
int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length);
int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length);
int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length);
int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen);
int eax_encrypt_authenticate_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen, const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen);
int eax_decrypt_verify_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen, const unsigned char *ct, unsigned long ctlen, unsigned char *pt, unsigned char *tag, unsigned long taglen, int *stat);
int eax_test(void);
──────────────────────────────────────
int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen)
// [功能] 初始化EAX
- cipher // [输入] 密码算法
- key // [输入] 密钥
- keylen // [输入] 密钥长度
- nonce // [输入] 随机数
- noncelen // [输入] 随机数长度
- header // [输入] 关联信息
- headerlen // [输入] 关联信息长度
- eax // [输入/输出] EAX状态
//备注: 处理过程如下
//1. 计算 N = LTC_OMAC_0K(nonce) = OMAC_K( [0]_128 || nonce)
//2. 计算 H = LTC_OMAC_0K(header) = OMAC_K( [1]_128 || header)
// 为方便继续添加header,此处计算出来的H还没有封口,所以采用 omac_state
//3. 初始化 CTR 模式
//4. 计算 C` = LTC_OMAC_2K(C) = OMAC_K( [2]_128 || C)的第一个分组[2]_128
// 这里的OMAC^t_K(M) = OMAC_K( [t]n || M)
// [t]n是t的n bit表示形式,这里就是将t表示为一个分组长度──────────────────────────────────────
──────────────────────────────────────
int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length);
// [功能] 加密与认证
- pt // [输入] 明文
- ct // [输出] 密文
- length // [输入] 明文长度
- eax // [输入/输出] EAX状态
//备注:处理过程为
//1. 先用CRT加密得到密文
//2. 再用OMAC处理加密得到的密文
──────────────────────────────────────
──────────────────────────────────────
int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length)
// [功能] 解密与验证
- out // [输出] MAC
- outlen // [输入/输出] MAC长度
- eax // [输入/输出] eax的状态
//备注:-
──────────────────────────────────────
──────────────────────────────────────
int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length)
// [功能] 继续添加 head信息
- header // [输入] 关联信息
- length // [输入/输出] 关联信息长度
- eax // [输入/输出] eax的状态
//备注:主要应对head信息也是流式数据需不断添加的情况
──────────────────────────────────────
──────────────────────────────────────
int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen)
// [功能] 结束EAX,得到最终mac值 tag
- tag // [输出] MAC
- tag len // [输出] MAC长度
- eax // [输入/输出] eax的状态
//备注: 主要做以下三件事情
//Step1. 结束ct的omac工作,得到ctmac
//Step2. 结束header的omac工作,得到headermac
//step3. 三项异或得到MAC值
──────────────────────────────────────
──────────────────────────────────────
int eax_encrypt_authenticate_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen, const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen)
// [功能] 处理消息并输出MAC(即加密认证一段数据)
- cipher // [输入] 密码算法
- key // [输入] 密钥
- keylen // [输入] 密钥长度
- nonce // [输入] 随机数
- noncelen // [输入] 随机数长度
- header // [输入] 关联信息
- headerlen // [输入] 关联信息长度
- pt // [输入] 明文
- ptlen // [输入] 明文长度
- ct // [输出] 密文
- tag // [输出] MAC
- tag len // [输出] MAC长度
//备注: 实际是对整个EAX过程的一个简单封装。
// 这要求所有消息和附加的认证信息都不能太长,且不能再次添加
// 工作流程为:
// 1. eax_init( )
// 2. eax_encrypt( )
// 3. eax_done( )
──────────────────────────────────────
──────────────────────────────────────
int eax_decrypt_verify_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen, const unsigned char *ct, unsigned long ctlen, unsigned char *pt, unsigned char *tag, unsigned long taglen, int *stat)
// [功能] 验证并解密一段数据
- cipher // [输入] 密码算法
- key // [输入] 密钥
- keylen // [输入] 密钥长度
- nonce // [输入] 随机数
- noncelen // [输入] 随机数长度
- header // [输入] 关联信息
- headerlen // [输入] 关联信息长度
- ct // [输入] 密文
- ctlen // [输入] 密文长度
- pt // [输出] 明文
- tag // [输出] MAC
- tag len // [输出] MAC长度
//备注:实际是对整个EAX解密验证过程的一个简单封装。
// 这要求所有消息和附加的认证信息都不能太长,且不能再次添加
// 工作流程为:
// 1. eax_init( )
// 2. eax_decrypt( )
// 3. eax_done( )
──────────────────────────────────────
──────────────────────────────────────
int eax_test(void)
// [功能] 测试函数
──────────────────────────────────────