1. 程式人生 > >密碼庫LibTomCrypt學習記錄——(2.12)分組密碼演算法的工作模式——OMAC認證模式

密碼庫LibTomCrypt學習記錄——(2.12)分組密碼演算法的工作模式——OMAC認證模式

  1. 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上。

參考文獻

  1. NIST SP 800-38B.
  2. 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/.
  3. 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.
  4. T. Iwata, K. Kurosawa, OMAC: One-Key CBC MAC, Natl. Inst. Stand. Technol. [Web page], http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/.
  5. 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.
  6. T. Iwata, K. Kurosawa, OMAC: One-Key CBC MAC—Addendum, Natl. Inst. Stand. Technol. [Web page], http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/.
  7. 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/.
  8. A. Menezes, P. van Oorschot, S. Vanstone, Handbook of Applied Cryptography, CRC Press, Inc., Boca Raton (1996).
  1. 子金鑰生成

記加密演算法為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 = 012010000111R64 = 05911011

012010000111就是前面120bit0再在低位接10000111,其餘類似。

其實,對步驟2和步驟3更準確的理解是,這是在做有限域GF(2b)上的乘以2的乘法,Rb是生成多項式的尾項,即生成多項式為f(x)=x128+Rb此有限域上的b = a2的運算過程就是:。這樣一來,兩個子金鑰的來歷就是:

子金鑰生成的流程圖(生成子金鑰K1和K2)

  1. 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)

 

  1. 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;

其中

  1. 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);

// [功能]   初始化

  1. omac            // [輸入/輸出] OMAC狀態
  2. cipher           // [輸入] 初始化向量
  3. key                   // [輸入] 金鑰
  4. keylen          // [輸入] 金鑰長度

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

 

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

int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen);

// [功能]   處理輸入資訊

  1. omac            // [輸入/輸出] OMAC狀態
  2. in                 // [輸入] 訊息
  3. inlen            // [輸入] 訊息長度

//[備註]    訊息長度可以不是分組長度的倍數。可多次呼叫此函式輸入訊息

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

 

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

int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen);

// [功能]   結束並輸出mac值

  1. omac            // [輸入/輸出] OMAC狀態
  2. out               // [輸出] mac值
  3. 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值

  1. cipher           // [輸入] 密碼演算法
  2. key                   // [輸入] 金鑰
  3. keylen          // [輸入] 金鑰長度
  4. in                 // [輸入] 訊息
  5. inlen            // [輸入] 訊息長度
  6. out               // [輸出] mac值
  7. 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值

  1. cipher           // [輸入] 密碼演算法
  2. key                   // [輸入] 金鑰
  3. keylen          // [輸入] 金鑰長度
  4. out               // [輸出] mac值
  5. outlen          // [輸出] mac值長度
  6. in                 // [輸入] 訊息
  7. inlen            // [輸入] 訊息長度
  8. …                 // [輸入] 可選引數,先跟訊息地址,再跟訊息長度,如此反覆

//[備註]    類似omac_memory,只不過處理的是多段資料

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

 

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

int omac_file(int cipher, const unsigned char *key, unsigned long keylen, const char *filename, unsigned char *out, unsigned long *outlen);

// [功能]   計算檔案的mac值

  1. cipher           // [輸入] 密碼演算法
  2. key                   // [輸入] 金鑰
  3. keylen          // [輸入] 金鑰長度
  4. filename            // [輸入] 檔名
  5. out               // [輸出] mac值
  6. outlen          // [輸出] mac值長度

//[備註]    適合訊息不太長的場合。實際處理過程為

omac_init(***);

while ( file_not end )

{

fread(***);

omac_ process (***);

}

omac_ done (***);

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

 

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

int omac_test(void);

// [功能]   測試函式

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