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

相关文章

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

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识