LibTomCrypt学习笔记——工作模式——OMAC

2023-10-28 18:58

本文主要是介绍LibTomCrypt学习笔记——工作模式——OMAC,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

介绍

OMAC是一种认证模式,CMAC is an essentially the One-Key CBC-MAC (OMAC)。NIST官网的介绍如下。

The CMAC authentication mode is specified inSpecial Publication 800-38B for use with any approved block cipher.CMAC stands for cipher-based message authentication code (MAC), analogous to HMAC, the hash-based MAC algorithm.

CMAC is an essentially the One-Key CBC-MAC (OMAC) algorithm submitted by Iwata and Kurosawa. OMAC is an improvement of the XCBC algorithm, submitted by Rogaway and Black, which itself is an improvement of the CBC-MAC algorithm. XCBC efficiently addresses the security deficiencies of CBC-MAC;OMAC efficiently reduces the key size of XCBC.

算法

OMAC采用的是CBC模式得到MAC值,当然在其中某些地方做了调整,主要调整在:子密钥的生成和最后一个分组的padding上。

子密钥生成

The following is a specification of the subkey generation process of CMAC:

Prerequisites:

block cipher CIPH with block size b;

key K.

Output:

subkeys K1, K2.

Suggested Notation:

SUBK(K).

Steps:

1. Let L = CIPHK(0b).

2. If MSB1(L) = 0, then K1 = L << 1;

Else K1 = (L << 1) ⊕ Rb; see Sec. 5.3 for the definition of Rb.

3. If MSB1(K1) = 0, then K2 = K1 << 1;

Else K2 = (K1 << 1) ⊕ Rb.

3.        Return K1, K2.

其中Rb的含义如下:

b表示分组大小(bit)R128= 012010000111, and R64= 05911011.

012010000111就是前面120bit0再在低位接10000111,其余类似

子密钥生成的流程图(生成子密钥K1和K2)

MAC生成

block cipher CIPH with block sizeb;

key K;

MAC length parameter Tlen.

Input:

message M of bit lengthMlen.

Output:

MAC T of bit lengthTlen.

Suggested Notation:

CMAC(K, M,Tlen) or, ifTlenis understood from the context, CMAC(K,M).

Steps:

1. Apply the subkey generation process in Sec. 6.1 toKto produceK1and K2.

2. If Mlen = 0, letn= 1; else, letn= 向上取整(Mlen/b).

3. Let M1, M2, ... , Mn-1, Mn* denote the unique sequence of bit strings such thatM=

M1 || M2 || ... ||Mn-1 ||Mn*, whereM1,M2,..., Mn-1 are complete blocks.2

4. If Mn* is a complete block, letMn=K1Mn*; else, letMn=K2 ⊕ (Mn*||10j),

where j = nb-Mlen-1.

5. Let C0 = 0b.

6. For i = 1 ton, letCi= CIPHK(Ci-1⊕Mi).

7. Let T = MSBTlen(Cn).

8. Return T.

 

MAC生成的流程图(MAC值为T)

 

代码

在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);

// [功能] 初始化

// [返回] 0 [正常] or other [出错]

// [出处] omac_init.c

l         omac                    // [输入/输出] OMAC状态

l         cipher                   // [输入] 初始化向量

l         key                       // [输入] 密钥

l         keylen                  // [输入] 密钥长度

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

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

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

// [功能] 处理输入信息

// [返回] 0 [正常] or other [出错]

// [出处] omac_process.c

l         omac                    // [输入/输出] OMAC状态

l         in                         // [输入] 消息

l         inlen                     // [输入] 消息长度

//[备注]  消息长度可以不是分组长度的倍数。可多次调用此函数输入消息

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

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

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

// [功能] 结束并输出mac值

// [返回] 0 [正常] or other [出错]

// [出处] omac_done.c

l         omac                    // [输入/输出] OMAC状态

l         out                       // [输出] mac值

l         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值

// [返回] 0 [正常] or other [出错]

// [出处] omac_memory.c

l         cipher                   // [输入] 密码算法

l         key                       // [输入] 密钥

l         keylen                  // [输入] 密钥长度

l         in                         // [输入] 消息

l         inlen                     // [输入] 消息长度

l         out                       // [输出] mac值

l         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值

// [返回] 0 [正常] or other [出错]

// [出处] omac_memory_multi.c

l         cipher                   // [输入] 密码算法

l         key                       // [输入] 密钥

l         keylen                  // [输入] 密钥长度

l         out                       // [输出] mac值

l         outlen                  // [输出] mac值长度

l         in                         // [输入] 消息

l         inlen                     // [输入] 消息长度

l         …                         // [输入] 可选参数,先跟消息地址,再跟消息长度,如此反复

//[备注]  类似omac_memory,只不过处理的是多段数据

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

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

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

// [功能] 计算文件的mac值

// [返回] 0 [正常] or other [出错]

// [出处] omac_file.c

l         cipher                   // [输入] 密码算法

l         key                       // [输入] 密钥

l         keylen                  // [输入] 密钥长度

l         filename               // [输入] 文件名

l         out                       // [输出] mac值

l         outlen                  // [输出] mac值长度

//[备注]  适合消息不太长的场合。实际处理过程为

omac_init(***);

while ( file_not end )

{

fread(***);

omac_ process (***);

}

omac_ done (***);

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

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

int omac_test(void);

// [功能] 测试函数

// [返回] 0 [正常] or other [出错]

// [出处] omac_ test.c

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

测试代码

使用NIST提供的测试向量

参见 Test_CMAC_AES.c

测试代码

//------------------------------------------------------------    代码分割线    ---------------------------------------------------------------------------------------


#include "tomcrypt.h"
#include "TestMode.h"

 
//lie test , use nist test vetor

int Test_CMAC_AES(void)
{
 // 数据来源
 // NIST SP 800-38B (Recommendation for Block Cipher Modes of Operation:The CMAC Mode for Authentication).pdf
 NistTestVector vect[] = {
  {//vect[0]
   /*name*/ "D.1 AES-128 Example  1: Mlen =   0",
   /*keylen*/ 16,
   /*msglen*/ 16*0,
   /*Key*/  "2b7e151628aed2a6abf7158809cf4f3c",
   /*IV */  "",
   {// pt  Message
    ""
   },
   {//ct T
    "bb1d6929e95937287fa37d129b756746"
   }
  },
  //
  {//vect[1]
   /*name*/ "D.1 AES-128 Example  2: Mlen = 128",
   /*keylen*/ 16,
   /*msglen*/ 16*1,
   /*Key*/  "2b7e151628aed2a6abf7158809cf4f3c",
   /*IV */  "",
   {// pt Message
    "6bc1bee22e409f96e93d7e117393172a"
   },
   {//ct T
    "070a16b46b4d4144f79bdd9dd04a287c"
   }
  },
  //
  {//vect[2]
   /*name*/ "D.1 AES-128 Example  3: Mlen = 320",
   /*keylen*/ 16,
   /*msglen*/ 16*5/2,
   /*Key*/  "2b7e151628aed2a6abf7158809cf4f3c",
   /*IV */  "",
   {// pt Message
    "6bc1bee22e409f96e93d7e117393172a",
    "ae2d8a571e03ac9c9eb76fac45af8e51",
    "30c81c46a35ce411"
   },
   {//ct T
    "dfa66747de9ae63030ca32611497c827"
   }
  },
  //
  {//vect[3]
   /*name*/ "D.1 AES-128 Example  4: Mlen = 512",
   /*keylen*/ 16,
   /*msglen*/ 16*4,
   /*Key*/  "2b7e151628aed2a6abf7158809cf4f3c",
   /*IV */  "",
   {// pt Message
    "6bc1bee22e409f96e93d7e117393172a",
    "ae2d8a571e03ac9c9eb76fac45af8e51",
    "30c81c46a35ce411e5fbc1191a0a52ef",
    "f69f2445df4f9b17ad2b417be66c3710"
   },
   {//ct T
    "51f0bebf7e3b9d92fc49741779363cfe"
   }
  },
  //
  {//vect[4]
   /*name*/ "D.2 AES-192 Example  5: Mlen =   0",
   /*keylen*/ 24,
   /*msglen*/ 16*0,
   /*Key*/  "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",  
   /*IV */  "",
   {// pt
    "",
   },
   {//ct
    "d17ddf46adaacde531cac483de7a9367"
   }
  },
  //
  {//vect[5]
   /*name*/ "D.2 AES-192 Example  6: Mlen = 128",
   /*keylen*/ 24,
   /*msglen*/ 16*1,
   /*Key*/  "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
   /*IV */  "",
   {// pt
    "6bc1bee22e409f96e93d7e117393172a",
   },
   {//ct
    "9e99a7bf31e710900662f65e617c5184"
   }
  },
  //
  {//vect[6]
   /*name*/ "D.2 AES-192 Example  7: Mlen = 320",
   /*keylen*/ 24,
   /*msglen*/ 16*5/2,
   /*Key*/  "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
   /*IV */  "",
   {// pt
    "6bc1bee22e409f96e93d7e117393172a",
    "ae2d8a571e03ac9c9eb76fac45af8e51",
    "30c81c46a35ce411"
   },
   {//ct
     "8a1de5be2eb31aad089a82e6ee908b0e"
   } 
  },
  //
  {//vect[7]
   /*name*/ "D.2 AES-192 Example  8: Mlen = 512",
   /*keylen*/ 24,
   /*msglen*/ 16*4,
   /*Key*/  "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
   /*IV */  "",
   {// pt
    "6bc1bee22e409f96e93d7e117393172a",
    "ae2d8a571e03ac9c9eb76fac45af8e51",
    "30c81c46a35ce411e5fbc1191a0a52ef",
    "f69f2445df4f9b17ad2b417be66c3710"
   },
   {//ct
    "a1d5df0eed790f794d77589659f39a11"
   }
  } ,
  //
  {//vect[8]
   /*name*/ "D.3 AES-256 Example  9: Mlen =   0",
   /*keylen*/ 32,
   /*msglen*/ 16*0,
   /*Key*/  "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",  
   /*IV */  "",
   {// pt
    "",
   },
   {//ct
    "028962f61b7bf89efc6b551f4667d983"
   }
  },
  //
  {//vect[9] 
   /*name*/ "D.3 AES-256 Example 10: Mlen = 128",
   /*keylen*/ 32,
   /*msglen*/ 16*1,
   /*Key*/  "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
   /*IV */  "",
   {// pt
    "6bc1bee22e409f96e93d7e117393172a",
   },
   {//ct
    "28a7023f452e8f82bd4bf28d8c37c35c"
   }
  },
  //
  {//vect[10] 
   /*name*/ "D.3 AES-256 Example 11: Mlen = 320",
   /*keylen*/ 32,
   /*msglen*/ 16*5/2,
   /*Key*/  "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
   /*IV */  "",
   {// pt
    "6bc1bee22e409f96e93d7e117393172a",
    "ae2d8a571e03ac9c9eb76fac45af8e51",
    "30c81c46a35ce411"
   },
   {//ct
    "aaf3d8f1de5640c232f5b169b9c911e6"
   } 
  },
  //
  {//vect[11]
   /*name*/ "D.3 AES-256 Example 12: Mlen = 512",
   /*keylen*/ 32,
   /*msglen*/ 16*4,
   /*Key*/  "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
   /*IV */  "",
   {// pt
    "6bc1bee22e409f96e93d7e117393172a",
    "ae2d8a571e03ac9c9eb76fac45af8e51",
    "30c81c46a35ce411e5fbc1191a0a52ef",
    "f69f2445df4f9b17ad2b417be66c3710"
   },
   {//ct
    "e1992190549f6ed5696a2c056c315410"
   }
  }
 };

 int idx, err, i, res;
 BYTE buf[16];

 int keylen, msglen, len;
 BYTE key[32], IV[16], pt[64], ct[64];


 /* AES can be under rijndael or aes... try to find it */
 if ( register_cipher (&aes_desc) != CRYPT_OK )
 {
  return CRYPT_INVALID_CIPHER;
 }

 if ((idx = find_cipher("aes")) == -1)
 {
  return CRYPT_NOP;
 }
 
 for ( i = 0; i < (int)(sizeof(vect)/sizeof(vect[0])); i++ )
 {
  keylen = vect[i].keylen;
  msglen = vect[i].msglen;

  Str2Num(vect[i].key, 1, key);
  Str2Num(vect[i].IV, 1, IV);
  Str2Num(vect[i].pt, 4, pt);
  Str2Num(vect[i].ct, 4, ct);

  len = 16;//sizeof(out);
  if ((err = omac_memory(idx, key, keylen, pt, msglen, buf, &len)) != CRYPT_OK)
  {
   return err;
  }

  res = XMEMCMP(buf, ct, 16);//(XMEMCMP(out, tests[x].tag, 16) 
  printf("Test Vetor : %s pass ? \t%s \n", vect[i].name, (res == 0)?"Yes":"No" );
 }

 printf("\nTest CMAC AES Finish!\n" );
 return CRYPT_OK;
}

需要的子函数


int char2int(BYTE ch)
{
 if ( ( '0' <= ch ) && ( ch <= '9' ) )   return ch - '0';
 else if ( ( 'a' <= ch ) && ( ch <= 'f' ) )  return ch - 'a' + 10;
 else if (( 'A' <= ch ) && ( ch <= 'F' ) )  return ch - 'A' + 10;
 else  { _ASSERT(0);  return 0;  }
}

void Str2Num(BYTE *t[], int size, BYTE *p_bytes)
{
 int i, j, k = 0;
 int tmp = 0;
 
 for( i = 0; i < size; ++i )
 {
  int len = ( t[i] != NULL ) ? (int)strlen(t[i]) : 0;
  for (j = 0; j<len; j +=2 )
  {
   p_bytes[k++] = ( ( char2int(t[i][j]) ) << 4 ) | ( char2int(t[i][j+1]) );
  }
 }
}
 

这篇关于LibTomCrypt学习笔记——工作模式——OMAC的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/295261

相关文章

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

SpringBoot如何通过Map实现策略模式

《SpringBoot如何通过Map实现策略模式》策略模式是一种行为设计模式,它允许在运行时选择算法的行为,在Spring框架中,我们可以利用@Resource注解和Map集合来优雅地实现策略模式,这... 目录前言底层机制解析Spring的集合类型自动装配@Resource注解的行为实现原理使用直接使用M

C#原型模式之如何通过克隆对象来优化创建过程

《C#原型模式之如何通过克隆对象来优化创建过程》原型模式是一种创建型设计模式,通过克隆现有对象来创建新对象,避免重复的创建成本和复杂的初始化过程,它适用于对象创建过程复杂、需要大量相似对象或避免重复初... 目录什么是原型模式?原型模式的工作原理C#中如何实现原型模式?1. 定义原型接口2. 实现原型接口3

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

大数据spark3.5安装部署之local模式详解

《大数据spark3.5安装部署之local模式详解》本文介绍了如何在本地模式下安装和配置Spark,并展示了如何使用SparkShell进行基本的数据处理操作,同时,还介绍了如何通过Spark-su... 目录下载上传解压配置jdk解压配置环境变量启动查看交互操作命令行提交应用spark,一个数据处理框架

kotlin中的模块化结构组件及工作原理

《kotlin中的模块化结构组件及工作原理》本文介绍了Kotlin中模块化结构组件,包括ViewModel、LiveData、Room和Navigation的工作原理和基础使用,本文通过实例代码给大家... 目录ViewModel 工作原理LiveData 工作原理Room 工作原理Navigation 工

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

SSID究竟是什么? WiFi网络名称及工作方式解析

《SSID究竟是什么?WiFi网络名称及工作方式解析》SID可以看作是无线网络的名称,类似于有线网络中的网络名称或者路由器的名称,在无线网络中,设备通过SSID来识别和连接到特定的无线网络... 当提到 Wi-Fi 网络时,就避不开「SSID」这个术语。简单来说,SSID 就是 Wi-Fi 网络的名称。比如

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert