当前位置:   article > 正文

AES-CMAC算法应用实例

aes-cmac

算法应用背景:

在27解锁密钥服务中有时候会应用到其AEC-CMAC的加密,其原理是在诊断仪发送27 01 给到ECU之后,ECU会产生一串随机数后反馈给诊断仪,诊断仪接着根据固定的KEY对随机数进行加密,得到加密后的数据Encrypt,诊断仪通过27 02 Encrypt发送给ECU,ECU则对发送出去的随机数同样进行ASE-CMAC的加密得到Encrypt1,之后Encrypt1与27 02的Encrypt进行对比,成功则返回67 02 ,失败则返回NRC 35 36等。

算法应用具体要求:

1.采用AES-CMAC的算法

2.密钥长度128bit,数据填充参考AEC-CMAC,并参考RFC4493

以上网络上其实也有相关的计算源码。

现在我直接放上可以执行的C代码,以供有需要的人进行查阅。

  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <string.h>
  4. //
  5. typedef struct{
  6. uint32_t eK[44], dK[44]; // encKey, decKey
  7. int Nr; // 10 rounds
  8. }AesKey;
  9. void printHex(uint8_t *ptr, int len, char *tag);
  10. #define BLOCKSIZE 16 //AES-128分组长度为16字节
  11. typedef unsigned char uint8_t;
  12. // uint8_t y[4] -> uint32_t x
  13. #define LOAD32H(x, y) \
  14. do { (x) = ((uint32_t)((y)[0] & 0xff)<<24) | ((uint32_t)((y)[1] & 0xff)<<16) | \
  15. ((uint32_t)((y)[2] & 0xff)<<8) | ((uint32_t)((y)[3] & 0xff));} while(0)
  16. // uint32_t x -> uint8_t y[4]
  17. #define STORE32H(x, y) \
  18. do { (y)[0] = (uint8_t)(((x)>>24) & 0xff); (y)[1] = (uint8_t)(((x)>>16) & 0xff); \
  19. (y)[2] = (uint8_t)(((x)>>8) & 0xff); (y)[3] = (uint8_t)((x) & 0xff); } while(0)
  20. // 从uint32_t x中提取从低位开始的第n个字节
  21. #define BYTE(x, n) (((x) >> (8 * (n))) & 0xff)
  22. /* used for keyExpansion */
  23. // 字节替换然后循环左移1位
  24. #define MIX(x) (((S[BYTE(x, 2)] << 24) & 0xff000000) ^ ((S[BYTE(x, 1)] << 16) & 0xff0000) ^ \
  25. ((S[BYTE(x, 0)] << 8) & 0xff00) ^ (S[BYTE(x, 3)] & 0xff))
  26. // uint32_t x循环左移n位
  27. #define ROF32(x, n) (((x) << (n)) | ((x) >> (32-(n))))
  28. // uint32_t x循环右移n位
  29. #define ROR32(x, n) (((x) >> (n)) | ((x) << (32-(n))))
  30. /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
  31. // AES-128轮常量
  32. static const uint32_t rcon[10] = {
  33. 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, 0x10000000UL,
  34. 0x20000000UL, 0x40000000UL, 0x80000000UL, 0x1B000000UL, 0x36000000UL
  35. };
  36. // S盒
  37. unsigned char S[256] = {
  38. 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
  39. 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
  40. 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
  41. 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
  42. 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
  43. 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
  44. 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
  45. 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
  46. 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
  47. 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
  48. 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
  49. 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
  50. 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
  51. 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
  52. 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
  53. 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
  54. };
  55. //逆S盒
  56. unsigned char inv_S[256] = {
  57. 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
  58. 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
  59. 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
  60. 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
  61. 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
  62. 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
  63. 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
  64. 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
  65. 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
  66. 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
  67. 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
  68. 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
  69. 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
  70. 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
  71. 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
  72. 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
  73. };
  74. /* copy in[16] to state[4][4] */
  75. int loadStateArray(uint8_t (*state)[4], const uint8_t *in) {
  76. int i,j;
  77. for (i = 0; i < 4; ++i) {
  78. for (j = 0; j < 4; ++j) {
  79. state[j][i] = *in++;
  80. }
  81. }
  82. return 0;
  83. }
  84. /* copy state[4][4] to out[16] */
  85. int storeStateArray(uint8_t (*state)[4], uint8_t *out) {
  86. int i,j;
  87. for (i = 0; i < 4; ++i) {
  88. for (j = 0; j < 4; ++j) {
  89. *out++ = state[j][i];
  90. }
  91. }
  92. return 0;
  93. }
  94. //秘钥扩展
  95. int keyExpansion(const uint8_t *key, uint32_t keyLen, AesKey *aesKey) {
  96. if (NULL == key || NULL == aesKey){
  97. printf("keyExpansion param is NULL\n");
  98. return -1;
  99. }
  100. if (keyLen != 16){
  101. printf("keyExpansion keyLen = %d, Not support.\n", keyLen);
  102. return -1;
  103. }
  104. uint32_t *w = aesKey->eK; //加密秘钥
  105. uint32_t *v = aesKey->dK; //解密秘钥
  106. /* keyLen is 16 Bytes, generate uint32_t W[44]. */
  107. /* W[0-3] */
  108. int i;
  109. for (i = 0; i < 4; ++i) {
  110. LOAD32H(w[i], key + 4*i);
  111. }
  112. /* W[4-43] */
  113. for (i = 0; i < 10; ++i) {
  114. w[4] = w[0] ^ MIX(w[3]) ^ rcon[i];
  115. w[5] = w[1] ^ w[4];
  116. w[6] = w[2] ^ w[5];
  117. w[7] = w[3] ^ w[6];
  118. w += 4;
  119. }
  120. w = aesKey->eK+44 - 4;
  121. //解密秘钥矩阵为加密秘钥矩阵的倒序,方便使用,把ek的11个矩阵倒序排列分配给dk作为解密秘钥
  122. //即dk[0-3]=ek[41-44], dk[4-7]=ek[37-40]... dk[41-44]=ek[0-3]
  123. int j;
  124. for (j = 0; j < 11; ++j) {
  125. for (i = 0; i < 4; ++i) {
  126. v[i] = w[i];
  127. }
  128. w -= 4;
  129. v += 4;
  130. }
  131. return 0;
  132. }
  133. // 轮秘钥加
  134. int addRoundKey(uint8_t (*state)[4], const uint32_t *key) {
  135. uint8_t k[4][4];
  136. int i;
  137. int j;
  138. /* i: row, j: col */
  139. for (i = 0; i < 4; ++i) {
  140. for (j = 0; j < 4; ++j) {
  141. k[i][j] = (uint8_t) BYTE(key[j], 3 - i); /* 把 uint32 key[4] 先转换为矩阵 uint8 k[4][4] */
  142. state[i][j] ^= k[i][j];
  143. }
  144. }
  145. return 0;
  146. }
  147. //字节替换
  148. int subBytes(uint8_t (*state)[4]) {
  149. /* i: row, j: col */
  150. int i,j;
  151. for (i = 0; i < 4; ++i) {
  152. for (j = 0; j < 4; ++j) {
  153. state[i][j] = S[state[i][j]]; //直接使用原始字节作为S盒数据下标
  154. }
  155. }
  156. return 0;
  157. }
  158. //逆字节替换
  159. int invSubBytes(uint8_t (*state)[4]) {
  160. /* i: row, j: col */
  161. int i,j;
  162. for (i = 0; i < 4; ++i) {
  163. for (j = 0; j < 4; ++j) {
  164. state[i][j] = inv_S[state[i][j]];
  165. }
  166. }
  167. return 0;
  168. }
  169. //行移位
  170. int shiftRows(uint8_t (*state)[4]) {
  171. uint32_t block[4] = {0};
  172. /* i: row */
  173. int i;
  174. for (i = 0; i < 4; ++i) {
  175. //便于行循环移位,先把一行4字节拼成uint_32结构,移位后再转成独立的4个字节uint8_t
  176. LOAD32H(block[i], state[i]);
  177. block[i] = ROF32(block[i], 8*i);
  178. STORE32H(block[i], state[i]);
  179. }
  180. return 0;
  181. }
  182. //逆行移位
  183. int invShiftRows(uint8_t (*state)[4]) {
  184. uint32_t block[4] = {0};
  185. /* i: row */
  186. int i;
  187. for (i = 0; i < 4; ++i) {
  188. LOAD32H(block[i], state[i]);
  189. block[i] = ROR32(block[i], 8*i);
  190. STORE32H(block[i], state[i]);
  191. }
  192. return 0;
  193. }
  194. /* Galois Field (256) Multiplication of two Bytes */
  195. // 两字节的伽罗华域乘法运算
  196. uint8_t GMul(uint8_t u, uint8_t v) {
  197. uint8_t p = 0;
  198. int i;
  199. for (i = 0; i < 8; ++i) {
  200. if (u & 0x01) { //
  201. p ^= v;
  202. }
  203. int flag = (v & 0x80);
  204. v <<= 1;
  205. if (flag) {
  206. v ^= 0x1B; /* x^8 + x^4 + x^3 + x + 1 */
  207. }
  208. u >>= 1;
  209. }
  210. return p;
  211. }
  212. // 列混合
  213. int mixColumns(uint8_t (*state)[4]) {
  214. uint8_t tmp[4][4];
  215. uint8_t M[4][4] = {{0x02, 0x03, 0x01, 0x01},
  216. {0x01, 0x02, 0x03, 0x01},
  217. {0x01, 0x01, 0x02, 0x03},
  218. {0x03, 0x01, 0x01, 0x02}};
  219. /* copy state[4][4] to tmp[4][4] */
  220. int i,j;
  221. for (i = 0; i < 4; ++i) {
  222. for (j = 0; j < 4; ++j){
  223. tmp[i][j] = state[i][j];
  224. }
  225. }
  226. for (i = 0; i < 4; ++i) {
  227. for (j = 0; j < 4; ++j) { //伽罗华域加法和乘法
  228. state[i][j] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j])
  229. ^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]);
  230. }
  231. }
  232. return 0;
  233. }
  234. // 逆列混合
  235. int invMixColumns(uint8_t (*state)[4]) {
  236. uint8_t tmp[4][4];
  237. uint8_t M[4][4] = {{0x0E, 0x0B, 0x0D, 0x09},
  238. {0x09, 0x0E, 0x0B, 0x0D},
  239. {0x0D, 0x09, 0x0E, 0x0B},
  240. {0x0B, 0x0D, 0x09, 0x0E}}; //使用列混合矩阵的逆矩阵
  241. int i,j;
  242. /* copy state[4][4] to tmp[4][4] */
  243. for (i = 0; i < 4; ++i) {
  244. for ( j = 0; j < 4; ++j){
  245. tmp[i][j] = state[i][j];
  246. }
  247. }
  248. for ( i = 0; i < 4; ++i) {
  249. for ( j = 0; j < 4; ++j) {
  250. state[i][j] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j])
  251. ^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]);
  252. }
  253. }
  254. return 0;
  255. }
  256. // AES-128加密接口,输入key应为16字节长度,输入长度应该是16字节整倍数,
  257. // 这样输出长度与输入长度相同,函数调用外部为输出数据分配内存
  258. int aesEncrypt(const uint8_t *key, uint32_t keyLen, const uint8_t *pt, uint8_t *ct, uint32_t len) {
  259. AesKey aesKey;
  260. uint8_t *pos = ct;
  261. const uint32_t *rk = aesKey.eK; //解密秘钥指针
  262. uint8_t out[BLOCKSIZE] = {0};
  263. uint8_t actualKey[16] = {0};
  264. uint8_t state[4][4] = {0};
  265. if (NULL == key || NULL == pt || NULL == ct){
  266. printf("param err.\n");
  267. return -1;
  268. }
  269. if (keyLen > 16){
  270. printf("keyLen must be 16.\n");
  271. return -1;
  272. }
  273. if (len % BLOCKSIZE){
  274. printf("inLen is invalid.\n");
  275. return -1;
  276. }
  277. memcpy(actualKey, key, keyLen);
  278. keyExpansion(actualKey, 16, &aesKey); // 秘钥扩展
  279. int i;
  280. // 使用ECB模式循环加密多个分组长度的数据
  281. for ( i = 0; i < len; i += BLOCKSIZE) {
  282. // 把16字节的明文转换为4x4状态矩阵来进行处理
  283. loadStateArray(state, pt);
  284. // 轮秘钥加
  285. addRoundKey(state, rk);
  286. int j;
  287. for (j = 1; j < 10; ++j) {
  288. rk += 4;
  289. subBytes(state); // 字节替换
  290. shiftRows(state); // 行移位
  291. mixColumns(state); // 列混合
  292. addRoundKey(state, rk); // 轮秘钥加
  293. }
  294. subBytes(state); // 字节替换
  295. shiftRows(state); // 行移位
  296. // 此处不进行列混合
  297. addRoundKey(state, rk+4); // 轮秘钥加
  298. // 把4x4状态矩阵转换为uint8_t一维数组输出保存
  299. storeStateArray(state, pos);
  300. pos += BLOCKSIZE; // 加密数据内存指针移动到下一个分组
  301. pt += BLOCKSIZE; // 明文数据指针移动到下一个分组
  302. rk = aesKey.eK; // 恢复rk指针到秘钥初始位置
  303. }
  304. return 0;
  305. }
  306. // AES128解密, 参数要求同加密
  307. int aesDecrypt(const uint8_t *key, uint32_t keyLen, const uint8_t *ct, uint8_t *pt, uint32_t len) {
  308. AesKey aesKey;
  309. uint8_t *pos = pt;
  310. const uint32_t *rk = aesKey.dK; //解密秘钥指针
  311. uint8_t out[BLOCKSIZE] = {0};
  312. uint8_t actualKey[16] = {0};
  313. uint8_t state[4][4] = {0};
  314. if (NULL == key || NULL == ct || NULL == pt){
  315. printf("param err.\n");
  316. return -1;
  317. }
  318. if (keyLen > 16){
  319. printf("keyLen must be 16.\n");
  320. return -1;
  321. }
  322. if (len % BLOCKSIZE){
  323. printf("inLen is invalid.\n");
  324. return -1;
  325. }
  326. memcpy(actualKey, key, keyLen);
  327. keyExpansion(actualKey, 16, &aesKey); //秘钥扩展,同加密
  328. int i,j;
  329. for ( i = 0; i < len; i += BLOCKSIZE) {
  330. // 把16字节的密文转换为4x4状态矩阵来进行处理
  331. loadStateArray(state, ct);
  332. // 轮秘钥加,同加密
  333. addRoundKey(state, rk);
  334. for ( j = 1; j < 10; ++j) {
  335. rk += 4;
  336. invShiftRows(state); // 逆行移位
  337. invSubBytes(state); // 逆字节替换,这两步顺序可以颠倒
  338. addRoundKey(state, rk); // 轮秘钥加,同加密
  339. invMixColumns(state); // 逆列混合
  340. }
  341. invSubBytes(state); // 逆字节替换
  342. invShiftRows(state); // 逆行移位
  343. // 此处没有逆列混合
  344. addRoundKey(state, rk+4); // 轮秘钥加,同加密
  345. storeStateArray(state, pos); // 保存明文数据
  346. pos += BLOCKSIZE; // 输出数据内存指针移位分组长度
  347. ct += BLOCKSIZE; // 输入数据内存指针移位分组长度
  348. rk = aesKey.dK; // 恢复rk指针到秘钥初始位置
  349. }
  350. return 0;
  351. }
  352. void printHex(uint8_t *ptr, int len, char *tag) {
  353. printf("%s\ndata[%d]: ", tag, len);
  354. int i;
  355. for ( i = 0; i < len; ++i) {
  356. printf("%.2X ", *ptr++);
  357. }
  358. printf("\n");
  359. }
  360. //
  361. /* For CMAC Calculation */
  362. unsigned char const_Rb[16] = {
  363. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  364. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
  365. };
  366. unsigned char const_Zero[16] = {
  367. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  368. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  369. };
  370. /* Basic Functions */
  371. void xor_128(unsigned char *a, unsigned char *b, unsigned char *out)
  372. {
  373. int i;
  374. for (i=0;i<16; i++)
  375. {
  376. out[i] = a[i] ^ b[i];
  377. }
  378. }
  379. void print_hex(char *str, unsigned char *buf, int len)
  380. {
  381. int i;
  382. for ( i=0; i<len; i++ ) {
  383. if ( (i % 16) == 0 && i != 0 ) printf(str);
  384. printf("%02x", buf[i]);
  385. if ( (i % 4) == 3 ) printf(" ");
  386. if ( (i % 16) == 15 ) printf("\n");
  387. }
  388. if ( (i % 16) != 0 ) printf("\n");
  389. }
  390. void print128(unsigned char *bytes)
  391. {
  392. int j;
  393. for (j=0; j<16;j++) {
  394. printf("%02x",bytes[j]);
  395. if ( (j%4) == 3 ) printf(" ");
  396. }
  397. }
  398. void print96(unsigned char *bytes)
  399. {
  400. int j;
  401. for (j=0; j<12;j++) {
  402. printf("%02x",bytes[j]);
  403. if ( (j%4) == 3 ) printf(" ");
  404. }
  405. }
  406. /* AES-CMAC Generation Function */
  407. void leftshift_onebit(unsigned char *input,unsigned char *output)
  408. {
  409. int i;
  410. unsigned char overflow = 0;
  411. for ( i=15; i>=0; i-- ) {
  412. output[i] = input[i] << 1;
  413. output[i] |= overflow;
  414. overflow = (input[i] & 0x80)?1:0;
  415. }
  416. return;
  417. }
  418. void generate_subkey(unsigned char *key, unsigned char *K1, unsigned
  419. char *K2)
  420. {
  421. unsigned char L[16];
  422. unsigned char Z[16];
  423. unsigned char tmp[16];
  424. int i;
  425. for ( i=0; i<16; i++ ) Z[i] = 0;
  426. aesEncrypt(key,16,Z,L,16);
  427. if ( (L[0] & 0x80) == 0 ) { /* If MSB(L) = 0, then K1 = L << 1 */
  428. leftshift_onebit(L,K1);
  429. } else { /* Else K1 = ( L << 1 ) (+) Rb */
  430. leftshift_onebit(L,tmp);
  431. xor_128(tmp,const_Rb,K1);
  432. }
  433. if ( (K1[0] & 0x80) == 0 ) {
  434. leftshift_onebit(K1,K2);
  435. } else {
  436. leftshift_onebit(K1,tmp);
  437. xor_128(tmp,const_Rb,K2);
  438. }
  439. return;
  440. }
  441. void padding ( unsigned char *lastb, unsigned char *pad, int length )
  442. {
  443. int j;
  444. /* original last block */
  445. for ( j=0; j<16; j++ ) {
  446. if ( j < length ) {
  447. pad[j] = lastb[j];
  448. } else if ( j == length ) {
  449. pad[j] = 0x80;
  450. } else {
  451. pad[j] = 0x00;
  452. }
  453. }
  454. }
  455. void AES_CMAC ( unsigned char *key, unsigned char *input, int length,
  456. unsigned char *mac )
  457. {
  458. unsigned char X[16],Y[16], M_last[16], padded[16];
  459. unsigned char K1[16], K2[16];
  460. int n, i, flag;
  461. generate_subkey(key,K1,K2);
  462. n = (length+15) / 16; /* n is number of rounds */
  463. if ( n == 0 ) {
  464. n = 1;
  465. flag = 0;
  466. } else {
  467. if ( (length%16) == 0 ) { /* last block is a complete block */
  468. flag = 1;
  469. } else { /* last block is not complete block */
  470. flag = 0;
  471. }
  472. }
  473. if ( flag ) { /* last block is complete block */
  474. xor_128(&input[16*(n-1)],K1,M_last);
  475. } else {
  476. padding(&input[16*(n-1)],padded,length%16);
  477. xor_128(padded,K2,M_last);
  478. }
  479. for ( i=0; i<16; i++ ) X[i] = 0;
  480. for ( i=0; i<n-1; i++ ) {
  481. xor_128(X,&input[16*i],Y); /* Y := Mi (+) X */
  482. aesEncrypt(key,16,Y,X,16); /* X := AES-128(KEY, Y); */
  483. }
  484. xor_128(X,M_last,Y);
  485. aesEncrypt(key,16,Y,X,16);
  486. for ( i=0; i<16; i++ ) {
  487. mac[i] = X[i];
  488. }
  489. }
  490. int main()
  491. {
  492. unsigned char L[16], K1[16], K2[16], T[16], TT[12];
  493. unsigned char M[64] = {
  494. 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
  495. 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
  496. 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
  497. 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
  498. 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
  499. 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
  500. 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
  501. 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
  502. };
  503. unsigned char key[16] = {
  504. 0x3d, 0x2e, 0x6d, 0xe2, 0xa1, 0x25, 0x17, 0xba,
  505. 0xc5, 0xb3, 0x1b, 0xbd, 0x0e, 0x7e, 0x3b, 0x54
  506. };
  507. printf("--------------------------------------------------\n");
  508. printf("K "); print128(key); printf("\n");
  509. printf("\nSubkey Generation\n");
  510. aesEncrypt(key,16,const_Zero,L,16);
  511. printf("AES_128(key,0) "); print128(L); printf("\n");
  512. generate_subkey(key,K1,K2);
  513. printf("K1 "); print128(K1); printf("\n");
  514. printf("K2 "); print128(K2); printf("\n");
  515. printf("\nExample 1: len = 0\n");
  516. printf("M "); printf("<empty string>\n");
  517. AES_CMAC(key,M,0,T);
  518. printf("AES_CMAC "); print128(T); printf("\n");
  519. printf("\nExample 2: len = 16\n");
  520. printf("M "); print_hex(" ",M,16);
  521. AES_CMAC(key,M,16,T);
  522. printf("AES_CMAC "); print128(T); printf("\n");
  523. printf("\nExample 3: len = 40\n");
  524. printf("M "); print_hex(" ",M,40);
  525. AES_CMAC(key,M,40,T);
  526. printf("AES_CMAC "); print128(T); printf("\n");
  527. printf("\nExample 4: len = 64\n");
  528. printf("M "); print_hex(" ",M,64);
  529. AES_CMAC(key,M,64,T);
  530. printf("AES_CMAC "); print128(T); printf("\n");
  531. printf("--------------------------------------------------\n");
  532. return 0;
  533. }

以上代码中,Key[16]为密钥,其是一个固定值,M则为需要加密的数据,上面最大支持64byte,根据自己项目实际情况去使用,其中int main里面写了0 ,16 ,40 ,64的时候执行的结果。

 AES_CMAC(key,M,64,T)函数中,形参Key表示密钥,M表示需要加密的数据,64表示填充为64byte的形式,T则表示加密之后得到的结果。以上根据自己要求来即可得到相应的结果。

实际测试结果:

以Key为  0x3d, 0x2e, 0x6d, 0xe2, 0xa1, 0x25, 0x17, 0xba,0xc5, 0xb3, 0x1b, 0xbd, 0x0e, 0x7e, 0x3b, 0x54为例,加密数据为0x00-0xff的16byte,加密长度为16byte,得到的结果为

a51eb807 bc447f92 fa33b569 9acb4cdf 

以上即为AES-CMAC的计算方法,仅供大家参考。

最后附上可以在线进行AES-CMAC的算法网站,供大家自己去验证:

CryptoJS extension by artjomb

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/51892
推荐阅读
相关标签
  

闽ICP备14008679号