密碼庫LibTomCrypt學習記錄——(2.12)分組密碼演算法的工作模式——OMAC認證模式
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);
// [功能] 測試函式
──────────────────────────────────────