Intel IPP密碼庫 IPPCP 2018——第二部分 對稱密碼演算法開發說明與示例程式碼
2. Symmetric Cryptography
2.1加解密步驟
其中<Alg>指具體的密碼演算法,<Mode>指ECB、CBC、OFB、CFB、CTR模式。
執行步驟:
步驟1. 獲取ctx大小:ipps<Alg>GetSize(int* pSize);其中<Alg>指具體的密碼演算法。
步驟2. 記憶體分配:pCtx = malloc(Size),分配Size位元組記憶體給密碼演算法的pCtx;
步驟3. 初始化(金鑰擴充套件):ipps<Alg>Init,需指定金鑰。
步驟4. 加解密:呼叫ipps<Alg>Encrypt<Mode>或者ipps<Alg>Decrypt<Mode>,這裡要設定IV,且IV在執行後會變化。
步驟5. 反初始化(資料清除):呼叫ipps<Alg>Init,但讓key置為NULL。
步驟6. 記憶體釋放:free(pCtx)。
注:
1. 還有個ipps<Alg>SetKey用於重新設定金鑰,功能與ipps<Alg>Init類似;兩者差異未知,猜測可能Init涉及一些別的特殊操作。
2.2 支援的密碼演算法和工作模式
表X 支援的密碼演算法和工作模式
模式演算法 |
AES |
TDES/DES |
SM4 |
ARCFour |
ECB |
Y |
Y |
Y |
RC4為流密碼 |
CBC |
Y |
Y |
Y |
|
CFB |
Y |
Y |
Y |
|
OFB |
Y |
Y |
Y |
|
CTR |
Y |
Y |
Y |
|
CCM |
Y |
X |
Y(2018版) |
|
GCM |
Y |
X |
X |
|
XTS |
Y |
X |
X |
|
SIV |
Y |
X |
X |
補充說明
- TDES = DES加密(K1) → DES解密(K2) → DES加密(K1) 。
- ARCFour即RC4演算法。
- CCM、GCM、SIV為認證加密模式;XTS為磁碟加密模式。
2.3 函式說明
2.3.1 獲取上下文大小GetSize
IppStatus ippsAESGetSize(int* pSize);
IppStatus ippsDESGetSize(int* pSize);
IppStatus ippsSMS4GetSize(int* pSize);
IppStatus ippsARCFourGetSize(int* pSize);
引數說明
- pSize:OUT,CTX大小,單位位元組。
2.3.2 初始化和反初始化Init
IppStatus ippsAESInit(const Ipp8u* pKey, int keylen, IppsAESSpec* pCtx, int ctxSize);
IppStatus ippsDESInit(const Ipp8u* pKey, IppsDESSpec* pCtx);
IppStatus ippsSMS4Init(const Ipp8u* pKey, int keyLen, IppsSMS4Spec* pCtx, int ctxSize);
IppStatus ippsARCFourInit(const Ipp8u* pKey, int keyLen, IppsARCFourState* pCtx);
引數說明
- pKey:IN,金鑰。
- keyLen:IN,金鑰位元組長度。
- pCtx:OUT,密碼演算法上下文。
- ctxSize:IN,CTX大小,單位位元組。
補充說明
- SM4的金鑰長度必須是16。RC4金鑰長度為1—256位元組。
- 將pKey設定為NULL則執行反初始化。
- TDES需要對三個金鑰各執行ippsDESInit以初始化三個IppsDESSpec*。
2.3.3 重置金鑰SetKey
僅AES和SM4有重置金鑰函式
IppStatus ippsAESSetKey(const Ipp8u* pKey, int keylen, IppsAESSpec* pCtx);
IppStatus ippsSMS4SetKey(const Ipp8u* pKey, int keyLen, IppsSMS4Spec* pCtx);
引數說明
- pKey:IN,金鑰。
- keyLen:IN,金鑰位元組長度。
- pCtx:OUT,密碼演算法上下文。
補充說明
- pCtx必須是已經Init了的才能呼叫此函式。
2.3.4 上下文匯入匯出Pack/Unpack
SM4無上下文匯入匯出。
IppStatus ippsAESPack (const IppsAESSpec* pCtx, Ipp8u* pBuffer, int bufSize);
IppStatus ippsAESUnpack (const Ipp8u* pBuffer, IppsAESSpec* pCtx, int ctxSize);
IppStatus ippsDESPack (const IppsDESSpec* pCtx, Ipp8u* pBuffer);
IppStatus ippsDESUnpack (const Ipp8u* pBuffer, IppsDESSpec* pCtx);
IppStatus ippsARCFourPack (const IppsARCFourState* pCtx, Ipp8u* pBuffer);
IppStatus ippsARCFourUnpack (const Ipp8u* pBuffer, IppsARCFourState* pCtx);
引數說明
(A)匯出/Pack時
- pCtx:IN,上下文。
- pBuffer:OUT,匯出緩衝區。
- bufSize:IN,有的函式無。
(B)匯入/Unpack時
- pBuffer:IN,匯入緩衝區。
- pCtx:OUT,上下文。
- ctxSize:IN,上下文。
備註:
- 無論緩衝區pBuffer位元組大小還是上下文pCtx位元組大小,都呼叫ipps***GetSize獲得。
- SM4無上下文匯入匯出。
- AES有bufSize和ctxSize是因為AES的金鑰有三種長度,使得其buf和ctx不定長。
2.3.5 AES加解密
IppStatus ippsAESEncryptECB( const Ipp8u *pSrc, Ipp8u *pDst, int srclen, const IppsAESSpec* pCtx);
IppStatus ippsAESDecryptECB( const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsAESSpec* pCtx);
IppStatus ippsAESEncryptCBC( const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsAESSpec* pCtx, const Ipp8u* pIV);
IppStatus ippsAESDecryptCBC( const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsAESSpec* pCtx, const Ipp8u* pIV);
IppStatus ippsAESEncryptCFB( const Ipp8u* pSrc, Ipp8u* pDst, int srcLen, int cfbBlkSize, const IppsAESSpec* pCtx, const Ipp8u *pIV);
IppStatus ippsAESDecryptCFB( const Ipp8u* pSrc, Ipp8u* pDst, int srclen, int cfbBlkSize, const IppsAESSpec* pCtx, const Ipp8u*pIV);
IppStatus ippsAESEncryptOFB ( const Ipp8u* pSrc, Ipp8u* pDst, int srclen, int ofbBlkSize, const IppsAESSpec* pCtx, Ipp8u* pIV);
IppStatus ippsAESDecryptOFB ( const Ipp8u* pSrc, Ipp8u* pDst, int srclen, int ofbBlkSize, const IppsAESSpec* pCtx, Ipp8u* pIV);
IppStatus ippsAESEncryptCTR( const Ipp8u* pSrc, Ipp8u* pDst, int srcLen,const IppsAESSpec* pCtx, Ipp8u* pCtrValue , int ctrNumBitSize);
IppStatus ippsAESDecryptCTR( const Ipp8u* pSrc, Ipp8u* pDst, int srcLen,const IppsAESSpec* pCtx, Ipp8u* pCtrValue, int ctrNumBitSize);
以下是在2018版中發現的新增介面,CBC的CS模式,2017版無。
IppStatus ippsAESEncryptCBC_CS1 (const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsAESSpec* pCtx, const Ipp8u* pIV);
IppStatus ippsAESEncryptCBC_CS2 (const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsAESSpec* pCtx, const Ipp8u* pIV);
IppStatus ippsAESEncryptCBC_CS3 (const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsAESSpec* pCtx, const Ipp8u* pIV);
IppStatus ippsAESDecryptCBC_CS1 (const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsAESSpec* pCtx, const Ipp8u* pIV);
IppStatus ippsAESDecryptCBC_CS2 (const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsAESSpec* pCtx, const Ipp8u* pIV);
IppStatus ippsAESDecryptCBC_CS3 (const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsAESSpec* pCtx, const Ipp8u* pIV);
表X 引數列表
AES |
pSrc |
pDst |
srcLen |
pCtx |
pIV |
其它 |
ECB |
Y |
Y |
Y |
Y |
— |
— |
CBC |
Y |
Y |
Y |
Y |
Y |
— |
CBC_CS1 |
Y |
Y |
Y |
Y |
Y |
— |
CBC_CS2 |
Y |
Y |
Y |
Y |
Y |
— |
CBC_CS3 |
Y |
Y |
Y |
Y |
Y |
— |
CFB |
Y |
Y |
Y |
Y |
Y |
cfbBlkSize |
OFB |
Y |
Y |
Y |
Y |
Y |
ofbBlkSize |
CTR |
Y |
Y |
Y |
Y |
— |
pCtrValue ctrNumBitSize |
引數說明
- pSrc:IN,加密時為明文,解密時為密文。
- srclen:IN,Src的位元組長度。
- pDst:OUT,加密時為密文,解密時為明文。長度等於srclen。
- pCtx:IO,密碼演算法上下文。
- pIV:IO,初始化向量,長度同分組大小,呼叫後會改變。ECB無。
- pCtrValue:IO,CTR的計數器,相當於其它模式的初始化向量。
- ctrNumBitSize:IN,計數器中有效的計數位元長度(從右端計)。
- cfbBlkSize/ ofbBlkSize:CFB/OFB每拍輸出的金鑰流位元組數,小於分組大小。
備註1:CBC_CS採用密文偷取技術,使得資料多次加密時使用不便。因此,建議這種模式下一次性輸入完畢明文/密文。
備註2:srcLen長度說明。
表X srcLen說明
AES |
srcLen |
ECB |
16 | srcLen |
CBC |
16 | srcLen |
CFB |
cfbBlkSize | srcLen |
OFB |
ofbBlkSize | srcLen |
CTR |
任意長度。 但非最後一次呼叫時都要求16 | srcLen |
CTR中srcLen長度的進一步說明
若srcLen不是16的整數倍,則生成的多餘的金鑰流會被丟棄。下次再送入資料時,會用新的CTR值加密作為金鑰流。
例如,第1次送入33位元組,第二次再送入31位元組。第一次生成48位元組金鑰流,前33位元組金鑰流用於加密,後15位元組金鑰流丟棄;第二次重新產生32位元組,前31位元組金鑰流用於加密,後1位元組金鑰流丟棄。這樣一來,由於第一次加密時丟棄了15位元組金鑰流,就導致了其加密結果和我們期望的結果不一致。
2.3.6 AES其它模式
AES加密認證涉及CCM、GCM、SIV,詳情參見官方文件。本文件略。
AES磁碟加密涉及XTS模式,詳情參見官方文件。本文件略。
2.3.7 TDES加解密
IppStatus ippsTDESEncryptECB(const Ipp8u *pSrc, Ipp8u *pDst, int srclen, const IppsDESSpec *pCtx1, const IppsDESSpec *pCtx2, const IppsDESSpec * pCtx3, IppsCPPadding padding);
IppStatus ippsTDESDecryptECB(const Ipp8u *pSrc, Ipp8u *pDst, int srclen, const IppsDESSpec *pCtx1, const IppsDESSpec *pCtx2, const IppsDESSpec * pCtx3, IppsCPPadding padding);
IppStatus ippsTDESEncryptCBC(const Ipp8u *pSrc, Ipp8u *pDst, int srclen, const IppsDESSpec *pCtx1, const IppsDESSpec *pCtx2, const IppsDESSpec * pCtx3, const Ipp8u *pIV, IppsCPPadding padding);
IppStatus ippsTDESDecryptCBC(const Ipp8u *pSrc, Ipp8u *pDst, int srclen, const IppsDESSpec *pCtx1, const IppsDESSpec *pCtx2, const IppsDESSpec * pCtx3, const Ipp8u *pIV, IppsCPPadding padding);
IppStatus ippsTDESEncryptCFB(const Ipp8u *pSrc, Ipp8u *pDst, int srclen, int cfbBlkSize, const IppsDESSpec *pCtx1, const IppsDESSpec *pCtx2, const IppsDESSpec *pCtx3, const Ipp8u *pIV, IppsCPPadding padding);
IppStatus ippsTDESDecryptCFB(const Ipp8u *pSrc, Ipp8u *pDst, int srclen, int cfbBlkSize, const IppsDESSpec *pCtx1, const IppsDESSpec *pCtx2, const IppsDESSpec *pCtx3, const Ipp8u *pIV, IppsCPPadding padding);
IppStatus ippsTDESEncryptOFB (const Ipp8u* pSrc, Ipp8u* pDst, int srclen, int ofbBlkSize, const IppsDESSpec *pCtx1, const IppsDESSpec *pCtx2, const IppsDESSpec *pCtx3, Ipp8u* pIV);
IppStatus ippsTDESDecryptOFB (const Ipp8u* pSrc, Ipp8u* pDst, int srclen, int ofbBlkSize, const IppsDESSpec *pCtx1, const IppsDESSpec *pCtx2, const IppsDESSpec *pCtx3, Ipp8u* pIV);
IppStatus ippsTDESEncryptCTR(const Ipp8u *pSrc, Ipp8u *pDst, int srclen, const IppsDESSpec *pCtx1, const IppsDESSpec *pCtx2, const IppsDESSpec *pCtx3,Ipp8u *pCtrValue, int ctrNumBitSize);
IppStatus ippsTDESDecryptCTR(const Ipp8u *pSrc, Ipp8u *pDst, int srcLen,const IppsDESSpec *pCtx1, const IppsDESSpec *pCtx2, const IppsDESSpec *pCtx3, Ipp8u *pCtrValue, int ctrNumBitSize);
表X 引數列表
TDES |
pSrc |
pDst |
srcLen |
pCtx1-3 |
pIV |
padding |
其它 |
ECB |
Y |
Y |
Y |
Y |
— |
Y |
— |
CBC |
Y |
Y |
Y |
Y |
Y |
Y |
— |
CFB |
Y |
Y |
Y |
Y |
Y |
Y |
cfbBlkSize |
OFB |
Y |
Y |
Y |
Y |
Y |
— |
ofbBlkSize |
CTR |
Y |
Y |
Y |
Y |
— |
— |
pCtrValue ctrNumBitSize |
引數說明
- pSrc:IN,加密時為明文,解密時為密文。
- srclen:IN,Src的位元組長度。
- pDst:OUT,加密時為密文,解密時為明文。長度等於srclen。
- pCtx1,pCtx2,pCtx3:IO,密碼演算法上下文,三個金鑰對應三個上下文。
- pIV:IO,初始化向量,長度同分組大小,呼叫後會改變。ECB無。
- padding:IN,目前好像只支援IppsPaddingNONE(不填充)。具體待查。
- pCtrValue:IO,CTR的計數器,相當於其它模式的初始化向量。
- ctrNumBitSize:IN,計數器中有效的計數位元長度(從右端計)。
- cfbBlkSize/ ofbBlkSize:CFB/OFB每拍輸出的金鑰流位元組數,小於分組大小。
備註:
- padding:具體待查。
2.3.8 SM4加解密
IppStatus ippsSMS4EncryptECB(const Ipp8u *pSrc, Ipp8u *pDst, int len, const IppsSMS4Spec* pCtx);
IppStatus ippsSMS4DecryptECB(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx);
IppStatus ippsSMS4EncryptCBC(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx, const Ipp8u* pIV);
IppStatus ippsSMS4DecryptCBC(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx, const Ipp8u* pIV);
IppStatus ippsSMS4EncryptCFB(const Ipp8u* pSrc, Ipp8u* pDst, int len, int cfbBlkSize, const IppsSMS4Spec* pCtx, const Ipp8u *pIV);
IppStatus ippsSMS4DecryptCFB(const Ipp8u* pSrc, Ipp8u* pDst, int len, int cfbBlkSize, const IppsSMS4Spec* pCtx, const Ipp8u* pIV);
IppStatus ippsSMS4EncryptOFB (const Ipp8u* pSrc, Ipp8u* pDst, int len, int ofbBlkSize, const IppsSMS4Spec* pCtx, Ipp8u* pIV);
IppStatus ippsSMS4DecryptOFB (const Ipp8u* pSrc, Ipp8u* pDst, int len, int ofbBlkSize, const IppsSMS4Spec* pCtx, Ipp8u* pIV);
IppStatus ippsSMS4EncryptCTR(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx, Ipp8u* pCtrValue , int ctrNumBitSize);
IppStatus ippsSMS4DecryptCTR(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec * pCtx, Ipp8u* pCtrValue, int ctrNumBitSize);
以下是在2018版中發現的新增介面,CBC的CS模式,2017版無。
IppStatus ipps SMS4EncryptCBC_CS1 (const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsSMS4Spec * pCtx, const Ipp8u* pIV);
IppStatus ipps SMS4EncryptCBC_CS2 (const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsSMS4Spec * pCtx, const Ipp8u* pIV);
IppStatus ipps SMS4EncryptCBC_CS3 (const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsSMS4Spec * pCtx, const Ipp8u* pIV);
IppStatus ipps SMS4DecryptCBC_CS1 (const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsSMS4Spec * pCtx, const Ipp8u* pIV);
IppStatus ipps SMS4DecryptCBC_CS2 (const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsSMS4Spec * pCtx, const Ipp8u* pIV);
IppStatus ipps SMS4DecryptCBC_CS3 (const Ipp8u* pSrc, Ipp8u* pDst, int srclen, const IppsSMS4Spec * pCtx, const Ipp8u* pIV);
表X 引數列表
SM4 |
pSrc |
pDst |
srcLen |
pCtx |
pIV |
其它 |
ECB |
Y |
Y |
Y |
Y |
— |
— |
CBC |
Y |
Y |
Y |
Y |
Y |
— |
CBC-CS1 |
Y |
Y |
Y |
Y |
Y |
— |
CBC-CS2 |
Y |
Y |
Y |
Y |
Y |
— |
CBC-CS3 |
Y |
Y |
Y |
Y |
Y |
— |
CFB |
Y |
Y |
Y |
Y |
Y |
cfbBlkSize |
OFB |
Y |
Y |
Y |
Y |
Y |
ofbBlkSize |
CTR |
Y |
Y |
Y |
Y |
— |
pCtrValue ctrNumBitSize |
引數說明
- pSrc:IN,加密時為明文,解密時為密文。
- srclen:IN,Src的位元組長度。
- pDst:OUT,加密時為密文,解密時為明文。長度等於srclen。
- pCtx:IO,密碼演算法上下文。
- pIV:IO,初始化向量,長度同分組大小,呼叫後會改變。ECB無。
- pCtrValue:IO,CTR的計數器,相當於其它模式的初始化向量。
- ctrNumBitSize:IN,計數器中有效的計數位元長度(從右端計)。
- cfbBlkSize/ ofbBlkSize:CFB/OFB每拍輸出的金鑰流位元組數,小於分組大小。
備註1:CBC_CS採用密文偷取技術,使得資料多次加密時使用不便。因此,建議這種模式下一次性輸入完畢明文/密文。
備註2:srcLen長度說明。
表X srcLen說明
AES |
srcLen |
ECB |
16 | srcLen |
CBC |
16 | srcLen |
CFB |
cfbBlkSize | srcLen |
OFB |
ofbBlkSize | srcLen |
CTR |
任意長度。 但非最後一次呼叫時都要求16 | srcLen |
CTR中srcLen長度的進一步說明
若srcLen不是16的整數倍,則生成的多餘的金鑰流會被丟棄。下次再送入資料時,會用新的CTR值加密作為金鑰流。
例如,第1次送入33位元組,第二次再送入31位元組。第一次生成48位元組金鑰流,前33位元組金鑰流用於加密,後15位元組金鑰流丟棄;第二次重新產生32位元組,前31位元組金鑰流用於加密,後1位元組金鑰流丟棄。這樣一來,由於第一次加密時丟棄了15位元組金鑰流,就導致了其加密結果和我們期望的結果不一致。
2.3.8 SM4-CCM加解認證
在2018版中發現有SM4-CCM,但是SM4執行CCM的可能性較低,所以本部分略。
2.3.9 ARCFour加解密
ARCFour即RC4流密碼。本部分略。
2.4 示例程式碼
2.4.1 AES示例程式碼
#include “ippcp.h”
// use of the CTR mode
int AES_sample(void)
{
// secret key
Ipp8u key[] = "\x00\x01\x02\x03\x04\x05\x06\x07"
"\x08\x09\x10\x11\x12\x13\x14\x15";
// define and setup AES cipher
int ctxSize;
ippsAESGetSize(&ctxSize);
IppsAESSpec* pAES = (IppsAESSpec*)( new Ipp8u [ctxSize] );
ippsAESInit(key, sizeof(key)-1, pAES, ctxSize);
// message to be encrypted
Ipp8u msg[] = "the quick brown fox jumps over the lazy dog";
// and initial counter
Ipp8u ctr0[] = "\xff\xee\xdd\xcc\xbb\xaa\x99\x88"
"\x77\x66\x55\x44\x33\x22\x11\x00";
// counter
Ipp8u ctr[16];
// init counter before encryption
memcpy(ctr, ctr0, sizeof(ctr));
// encrypted message
Ipp8u ctext[sizeof(msg)];
// encryption
ippsAESEncryptCTR(msg, ctext, sizeof(msg), pAES, ctr, 64);
// init counter before decryption
memcpy(ctr, ctr0, sizeof(ctr));
// decrypted message
Ipp8u rtext[sizeof(ctext)];
// decryption
ippsAESDecryptCTR(ctext, rtext, sizeof(ctext), pAES, ctr, 64);
// remove secret and release resource
ippsAESInit(0, sizeof(key)-1, pAES, ctxSize);
delete [] (Ipp8u*)pAES;
int error = memcmp(rtext, msg, sizeof(msg));
return 0==error;
}
2.4.2 TDES示例程式碼
// Use of the ECB mode
void TDES_sample(void){
// size of the TDES algorithm block is equal to 8
const int tdesBlkSize = 8;
// get size of the context needed for the encryption/decryption operation
int ctxSize;
ippsDESGetSize(&ctxSize);
// and allocate one
IppsDESSpec* pCtx1 = (IppsDESSpec*)( new Ipp8u [ctxSize] );
IppsDESSpec* pCtx2 = (IppsDESSpec*)( new Ipp8u [ctxSize] );
IppsDESSpec* pCtx3 = (IppsDESSpec*)( new Ipp8u [ctxSize] );
// define the key
Ipp8u key1[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
Ipp8u key2[] = {0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18};
Ipp8u key3[] = {0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28};
Ipp8u keyX[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
// and prepare the context for the TDES usage
ippsDESInit(key1, pCtx1);
ippsDESInit(key2, pCtx2);
ippsDESInit(key3, pCtx3);
// define the message to be encrypted
Ipp8u ptext[] = {"the quick brown fox jumps over the lazy dog"};
// allocate enough memory for the ciphertext
// note that
// the size of ciphertext is always a multiple of the cipher block size
Ipp8u ctext[(sizeof(ptext)+desBlkSize-1) &~(desBlkSize-1)];
// encrypt (ECB mode) ptext message
// pay attention to the 'length' parameter
// it defines the number of bytes to be encrypted
ippsTDESEncryptECB(ptext, ctext, sizeof(ctext), pCtx1, pCtx2, pCtx3, IppsCPPaddingNONE);
// allocate memory for the decrypted message
Ipp8u rtext[sizeof(ctext)];
// decrypt (ECB mode) ctext message
// pay attention to the 'length' parameter
// it defines the number of bytes to be decrypted
ippsTDESDecryptECB(ctext, rtext, sizeof(ctext), pCtx1, pCtx2, pCtx3, IppsCPPaddingNONE);
// remove actual secret from contexts
ippsDESInit(keyX, pCtx1);
ippsDESInit(keyX, pCtx2);
ippsDESInit(keyX, pCtx3);
// release resources
delete (Ipp8u*)pCtx1;
delete (Ipp8u*)pCtx2;
delete (Ipp8u*)pCtx3;
}