openssl學習之ccm,gcm 模式
openssl中添加了對AES ccm 和gcm模式的支援。下面的內容主要是對這兩個模式相關資料的收集以及整理。
一,CCM
CCM (counter with CBC-MAC)定義在分組長度為128位的加密演算法中,如,AES 的分組長度為128。組成AES-CCM演算法的關鍵組成是CTR工作模式以及CMAC認證演算法。Wifi 的WPE協議中使用了AES-CCM。在HMAC中我們介紹CCM是屬於一種E&M(認證並且加密),首先我們來看一下AES-CCM模式的輸入輸出。
首先介紹兩個引數設定:
L:長度域,取值為2~8 ,openssl中預設的為8。
M:tag的長度,合法的值為:4,6,8,10,12,14 和16。openssl中預設的為12
key | 16,24,32 |
None | 15-L |
Message to authenticate and encrypt | len(Msg) |
Additional authenticated data | len(AAD) |
對附加資料長度有:0<= len(AAD)< 2^64;
2,GCM/* Simple AES CCM test program, uses the same NIST data used for the FIPS * self test but uses the application level EVP APIs. */ #include <stdio.h> #include <openssl/bio.h> #include <openssl/evp.h> /* AES-CCM test data from NIST public test vectors */ static const unsigned char ccm_key[] = { 0xce,0xb0,0x09,0xae,0xa4,0x45,0x44,0x51,0xfe,0xad,0xf0,0xe6, 0xb3,0x6f,0x45,0x55,0x5d,0xd0,0x47,0x23,0xba,0xa4,0x48,0xe8 }; // 隨機數,每次加密針對相同的KEY使用不同的NONCE。否則會破壞CCM模式的安全性(RFC3610) static const unsigned char ccm_nonce[] = { 0x76,0x40,0x43,0xc4,0x94,0x60,0xb7 }; //附加資料 static const unsigned char ccm_adata[] = { 0x6e,0x80,0xdd,0x7f,0x1b,0xad,0xf3,0xa1,0xc9,0xab,0x25,0xc7, 0x5f,0x10,0xbd,0xe7,0x8c,0x23,0xfa,0x0e,0xb8,0xf9,0xaa,0xa5, 0x3a,0xde,0xfb,0xf4,0xcb,0xf7,0x8f,0xe4 }; //plaintext 表示明文 static const unsigned char ccm_pt[] = { 0xc8,0xd2,0x75,0xf9,0x19,0xe1,0x7d,0x7f,0xe6,0x9c,0x2a,0x1f, 0x58,0x93,0x9d,0xfe,0x4d,0x40,0x37,0x91,0xb5,0xdf,0x13,0x10 }; //ciphertext 表示密文 static const unsigned char ccm_ct[] = { 0x8a,0x0f,0x3d,0x82,0x29,0xe4,0x8e,0x74,0x87,0xfd,0x95,0xa2, 0x8a,0xd3,0x92,0xc8,0x0b,0x36,0x81,0xd4,0xfb,0xc7,0xbb,0xfd }; //tag 表示tag資料 static const unsigned char ccm_tag[] = { 0x2d,0xd6,0xef,0x1c,0x45,0xd4,0xcc,0xb7,0x23,0xdc,0x07,0x44, 0x14,0xdb,0x50,0x6d }; void aes_ccm_encrypt(void) { EVP_CIPHER_CTX *ctx; int outlen, tmplen; unsigned char outbuf[1024]; printf("AES CCM Encrypt:\n"); printf("Plaintext:\n"); BIO_dump_fp(stdout, ccm_pt, sizeof(ccm_pt)); ctx = EVP_CIPHER_CTX_new(); /* Set cipher type and mode */ EVP_EncryptInit_ex(ctx, EVP_aes_192_ccm(), NULL, NULL, NULL); /* Set nonce length if default 96 bits is not appropriate */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, sizeof(ccm_nonce), NULL); /* Set tag length */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, sizeof(ccm_tag), NULL); /* Initialise key and IV */ EVP_EncryptInit_ex(ctx, NULL, NULL, ccm_key, ccm_nonce); /* Set plaintext length: only needed if AAD is used*/ //輸入輸出需設定為NULL EVP_EncryptUpdate(ctx, NULL, &outlen, NULL, sizeof(ccm_pt)); /* Zero or one call to specify any AAD */ //設定AAD,out引數需設定為NULL EVP_EncryptUpdate(ctx, NULL, &outlen, ccm_adata, sizeof(ccm_adata)); /* Encrypt plaintext: can only be called once */ EVP_EncryptUpdate(ctx, outbuf, &outlen, ccm_pt, sizeof(ccm_pt)); /* Output encrypted block */ printf("Ciphertext:\n"); BIO_dump_fp(stdout, outbuf, outlen); /* Finalise: note get no output for CCM */ EVP_EncryptFinal_ex(ctx, outbuf, &outlen); /* Get tag */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, 16, outbuf); /* Output tag */ printf("Tag:\n"); BIO_dump_fp(stdout, outbuf, 16); EVP_CIPHER_CTX_free(ctx); } void aes_ccm_decrypt(void) { EVP_CIPHER_CTX *ctx; int outlen, tmplen, rv; unsigned char outbuf[1024]; printf("AES CCM Derypt:\n"); printf("Ciphertext:\n"); BIO_dump_fp(stdout, ccm_ct, sizeof(ccm_ct)); ctx = EVP_CIPHER_CTX_new(); /* Select cipher */ EVP_DecryptInit_ex(ctx, EVP_aes_192_ccm(), NULL, NULL, NULL); /* Set nonce length, omit for 96 bits */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, sizeof(ccm_nonce), NULL); /* Set expected tag value */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, sizeof(ccm_tag), (void *)ccm_tag); /* Specify key and IV */ EVP_DecryptInit_ex(ctx, NULL, NULL, ccm_key, ccm_nonce); /* Set ciphertext length: only needed if we have AAD */ EVP_DecryptUpdate(ctx, NULL, &outlen, NULL, sizeof(ccm_ct)); /* Zero or one call to specify any AAD */ EVP_DecryptUpdate(ctx, NULL, &outlen, ccm_adata, sizeof(ccm_adata)); /* Decrypt plaintext, verify tag: can only be called once */ rv = EVP_DecryptUpdate(ctx, outbuf, &outlen, ccm_ct, sizeof(ccm_ct)); /* Output decrypted block: if tag verify failed we get nothing */ if (rv > 0) { printf("Plaintext:\n"); BIO_dump_fp(stdout, outbuf, outlen); } else printf("Plaintext not available: tag verify failed.\n"); EVP_CIPHER_CTX_free(ctx); } int main(int argc, char **argv) { aes_ccm_encrypt(); aes_ccm_decrypt(); }
GCM基於並行化設計,因此可以提供高效的吞吐率和低成本、低時延。本質是訊息在變形的CTR模式下加密,密文結果與金鑰以及訊息長度在GF(2^128)域上相乘,計算流程如下所示。其輸入輸出和CCM基本一致。CCM和GCM的具體計算過程可以參看《密碼學與網路安全》第五版,書中有詳細的介紹。FRC5288 中介紹了TLS1.2 中的GCM應用。下面貼出openssl中AES-GCM的例項。
/* Simple AES GCM test program, uses the same NIST data used for the FIPS * self test but uses the application level EVP APIs. */ #include <stdio.h> #include <openssl/bio.h> #include <openssl/evp.h> /* AES-GCM test data from NIST public test vectors */ static const unsigned char gcm_key[] = { 0xee,0xbc,0x1f,0x57,0x48,0x7f,0x51,0x92,0x1c,0x04,0x65,0x66, 0x5f,0x8a,0xe6,0xd1,0x65,0x8b,0xb2,0x6d,0xe6,0xf8,0xa0,0x69, 0xa3,0x52,0x02,0x93,0xa5,0x72,0x07,0x8f }; static const unsigned char gcm_iv[] = { 0x99,0xaa,0x3e,0x68,0xed,0x81,0x73,0xa0,0xee,0xd0,0x66,0x84 }; static const unsigned char gcm_pt[] = { 0xf5,0x6e,0x87,0x05,0x5b,0xc3,0x2d,0x0e,0xeb,0x31,0xb2,0xea, 0xcc,0x2b,0xf2,0xa5 }; static const unsigned char gcm_aad[] = { 0x4d,0x23,0xc3,0xce,0xc3,0x34,0xb4,0x9b,0xdb,0x37,0x0c,0x43, 0x7f,0xec,0x78,0xde }; static const unsigned char gcm_ct[] = { 0xf7,0x26,0x44,0x13,0xa8,0x4c,0x0e,0x7c,0xd5,0x36,0x86,0x7e, 0xb9,0xf2,0x17,0x36 }; static const unsigned char gcm_tag[] = { 0x67,0xba,0x05,0x10,0x26,0x2a,0xe4,0x87,0xd7,0x37,0xee,0x62, 0x98,0xf7,0x7e,0x0c }; void aes_gcm_encrypt(void) { EVP_CIPHER_CTX *ctx; int outlen, tmplen; unsigned char outbuf[1024]; printf("AES GCM Encrypt:\n"); printf("Plaintext:\n"); BIO_dump_fp(stdout, gcm_pt, sizeof(gcm_pt)); ctx = EVP_CIPHER_CTX_new(); /* Set cipher type and mode */ EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); /* Set IV length if default 96 bits is not appropriate */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, sizeof(gcm_iv), NULL); /* Initialise key and IV */ EVP_EncryptInit_ex(ctx, NULL, NULL, gcm_key, gcm_iv); /* Zero or more calls to specify any AAD */ EVP_EncryptUpdate(ctx, NULL, &outlen, gcm_aad, sizeof(gcm_aad)); /* Encrypt plaintext */ EVP_EncryptUpdate(ctx, outbuf, &outlen, gcm_pt, sizeof(gcm_pt)); /* Output encrypted block */ printf("Ciphertext:\n"); BIO_dump_fp(stdout, outbuf, outlen); /* Finalise: note get no output for GCM */ EVP_EncryptFinal_ex(ctx, outbuf, &outlen); /* Get tag */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, outbuf); /* Output tag */ printf("Tag:\n"); BIO_dump_fp(stdout, outbuf, 16); EVP_CIPHER_CTX_free(ctx); } void aes_gcm_decrypt(void) { EVP_CIPHER_CTX *ctx; int outlen, tmplen, rv; unsigned char outbuf[1024]; printf("AES GCM Derypt:\n"); printf("Ciphertext:\n"); BIO_dump_fp(stdout, gcm_ct, sizeof(gcm_ct)); ctx = EVP_CIPHER_CTX_new(); /* Select cipher */ EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); /* Set IV length, omit for 96 bits */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, sizeof(gcm_iv), NULL); /* Specify key and IV */ EVP_DecryptInit_ex(ctx, NULL, NULL, gcm_key, gcm_iv); #if 0 /* Set expected tag value. A restriction in OpenSSL 1.0.1c and earlier * required the tag before any AAD or ciphertext */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, sizeof(gcm_tag), gcm_tag); #endif /* Zero or more calls to specify any AAD */ EVP_DecryptUpdate(ctx, NULL, &outlen, gcm_aad, sizeof(gcm_aad)); /* Decrypt plaintext */ EVP_DecryptUpdate(ctx, outbuf, &outlen, gcm_ct, sizeof(gcm_ct)); /* Output decrypted block */ printf("Plaintext:\n"); BIO_dump_fp(stdout, outbuf, outlen); /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, sizeof(gcm_tag), gcm_tag); /* Finalise: note get no output for GCM */ rv = EVP_DecryptFinal_ex(ctx, outbuf, &outlen); /* Print out return value. If this is not successful authentication * failed and plaintext is not trustworthy. */ printf("Tag Verify %s\n", rv > 0 ? "Successful!" : "Failed!"); EVP_CIPHER_CTX_free(ctx); } int main(int argc, char **argv) { aes_gcm_encrypt(); aes_gcm_decrypt(); }
相關推薦
openssl學習之ccm,gcm 模式
openssl中添加了對AES ccm 和gcm模式的支援。下面的內容主要是對這兩個模式相關資料的收集以及整理。 一,CCM CCM (counter with CBC-MAC)定義在分組長度為128位的加密演算法中,如,AES 的分組長度為128。組成AES-CCM演算法
python學習之pyc,pyo,pyd文件
加載 -s 提高 font ont mic 優化 ros 學習 pyc:二進制文件,python文件經過編譯器編譯之後的文件。可以提高文件加載速度。 pyo:二進制文件,優化編譯後的文件。可以通過`python -O file.py`生成。 pyd:python的動態鏈接庫
Python學習之路,Day1 – Python基礎1
inf avr jet 源代碼 pre 創始人 UC 修改 學習python 寫在前面的話: 大學畢業之後沒有從事自己專業方面的工作,期間也做了很多工作,現在來到了一家物流公司,但是每天日復一日的工作,枯燥,乏味,發現這並不是自己想要的,自己也有自己的夢想,也有自己的追
自動傳輸軟件(學習之余,給自己弄得一個學習小結)
完成 ima 頁面 code 使用 不能 else str2 查詢系統 學習了一段時間後,總覺得有些地方不能融會貫通,因此給自己定了一個小的學習總結目標,自動傳輸軟件 項目要求:需要擁有首頁、傳輸界面、接收界面及尾頁,實現自動跳轉功能 1 #include<st
小白學習之路,基礎三(函數)
但是 iter 使用 問題 個數 函數作為參數 無限 中間 ble 一,函數的基本介紹 首先談到函數,相信大家都不陌生,不管是其他語言都會用到,可能就是叫法不一樣。就我知道的跟python中函數類似的,在C中只有function,在Java裏面叫做method,在js中也是
小白學習之路,基礎四(函數的進階)
strong 部分 iter 讀者 結果 http 內部 mod 取數 一,內置函數 前面已經認識了函數,對函數都有所了解了,其實呢,在Python中提供了很多內置的函數方便給我們調用。下面會給大家提到一些常用的常用內置函數的用法,當然還有一些其他沒講到的,你也可以看參考文
小白學習之路,初識面向對象
指針 -i 路徑 語句 程序 eat -- 不可 不用 一,編程範式 所謂編程範式(programming paradigm),指的是計算機編程的基本風格或典範模式。怎麽說呢,每個人都有自己不同的習慣,當然編程也是一樣的,每個程序組員根據自己不同的習慣會寫出不同的代碼。當然
小白學習之路,網絡編程(下)
多人 困難 get err lose imp 出現 popen one 一,socket進階 在前面的博客中講到了一些基本的計算機網絡知識,有一點也是為我在要考傳輸與交換看到一個題,然後就看到說ARP屬於網絡層,因為ARP協議跟網絡相關,但是我前面的博客說的是ARP協議屬於
模擬電路學習-之電容,電感重新認識
呵呵 由於 img 哈哈 實驗 觀察 效果 圖片 重新 一、電容 電容是構成基礎電路的原件,它的重要性就不多說了,下面是關於電容的一些特性: 【1】線性電容端電壓和積聚的電荷量的關系是:q=Cu(其中C就是電容,單位法拉,u是電壓,單位福特,q單位庫倫) 【2】電容伏安特
整合學習之boosting,Adaboost、GBDT 和 xgboost(二)
AdaBoost 演算法的訓練誤差分析 AdaBoost最基本的性質是它能在學習過程中不斷減少訓練誤差,即在訓練資料集上的分類誤差率。 定理:AdaBoost的訓練誤差界: 1
整合學習之boosting,Adaboost、GBDT 和 xgboost(一)
在前面的部落格(https://blog.csdn.net/qq_16608563/article/details/82878127) 介紹了整合學習的bagging方法及其代表性的隨機森林。此次接著介紹整合學習的另一個方法boosting以及boosting系列的一些演算法,具體包括 Ad
整合學習之boosting,Adaboost、GBDT 和 xgboost(三)
AdaBoost演算法的解釋——前向分步法與提升樹(GBDT) 可以認為AdaBoost演算法是模型為加法模型,損失函式為指數函式、學習演算法為前向分步演算法時的二類分類學習方法。 前向分步演算法: 考慮加法模型
python學習之scipy,matplotlib,pandas解讀
scipy可參考:https://www.jianshu.com/p/6c742912047f matplotlib可參考:https://www.jianshu.com/p/250eaa709b73 pandas可參考:https://www.jianshu.com/p/8b6137b1f
2018年11月4日java學習之關鍵字,識別符號,命名規範
1關鍵字 java 語言中的關鍵字都是小寫的,java嚴格區分大小寫 藍色的都是關鍵字,紅色的是類 還有一些保留字比如goto 2.識別符號 -》自己可以起名字的叫識別符號:類名,方法,變數,介面名 數字不可以開頭 由26個大小寫字母,數字
openssl 學習之證書中提取N 和 E
通常數字證書包含很多資訊,其中N和E值即我們稱為的公鑰。如何從PEM 或者DER格式的證書中提出證書呢?下面給出程式碼實現從PEM和DER編碼的證書中提出N、E。 #include <openssl/evp.h> #include <openssl/x
nio學習之channel,基於流的方式獲取channel
package nio; import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileCh
mongoDB學習之路,安裝、配置、啟動、命令、應用(一)
mongoDB初學 mongoDB學習了一段時間,今天整理一下,以便自己回顧,加深印象,同時讓更多mongo初學者有個好的資料。真好 在學習mongoDB之前,我們先了解什麼是mongoDB,以及相關概念 MongoDB 是一個基於分散式檔案儲存的資料庫。由 C++
mongoDB學習之路,安裝、配置、啟動、命令、應用(五)-
上篇說了java連線mongo,並進行增刪改查 這篇說一下spring整合mongo github上也有小demo,很簡單,適合初學者,地址:點選跳轉 1、首先建立maven專案,新增依賴 <!-- mongo驅動 --> <dependen
C++PrimerPlus學習之輸入,輸出和檔案
流和緩衝區 C++程式把輸入和輸出看作位元組流。輸入時,程式從輸入流中抽取位元組;輸出時,程式將位元組插入到輸出流中。 流充當了程式和流源或流目標之間的橋樑。C++程式只是檢查位元組流,而不需要知道位
Web 基礎學習之 JS ,迴圈練習
1.判斷閏年 var i; for(i=1980;i<=2016;i++) { if( i % 4 == 0 && i % 100 != 0 || i % 400 == 0) document.write( i + " "); } 2.九