crypt.tex

来自「文件驱动加密,功能强大,可产生加密分区,支持AES,MD2,MD4,MD5MD2」· TEX 代码 · 共 1,456 行 · 第 1/5 页

TEX
1,456
字号
      return -1;   }   /* ... use cipher ... */}\end{verbatim}\end{small}A good safety would be to check the return value of ``find\_cipher()'' before accessing the desired function.  In orderto use a cipher with the descriptor table you must register it first using:\begin{verbatim}int register_cipher(const struct _cipher_descriptor *cipher);\end{verbatim}Which accepts a pointer to a descriptor and returns the index into the global descriptor table.  If an error occurs suchas there is no more room (it can have 32 ciphers at most) it will return {\bf{-1}}.  If you try to add the same cipher morethan once it will just return the index of the first copy.  To remove a cipher call:\begin{verbatim}int unregister_cipher(const struct _cipher_descriptor *cipher);\end{verbatim}Which returns {\bf CRYPT\_OK} if it removes it otherwise it returns {\bf CRYPT\_ERROR}.  Consider:\begin{small}\begin{verbatim}#include <mycrypt.h>int main(void){   int errno;      /* register the cipher */   if (register_cipher(&rijndael_desc) == -1) {      printf("Error registering Rijndael\n");      return -1;   }   /* use Rijndael */   /* remove it */   if ((errno = unregister_cipher(&rijndael_desc)) != CRYPT_OK) {      printf("Error removing Rijndael: %s\n", error_to_string(errno));      return -1;   }   return 0;}\end{verbatim}\end{small}This snippet is a small program that registers only Rijndael only.  Note you must register ciphers beforeusing the PK code since all of the PK code (RSA, DH and ECC) rely heavily on the descriptor tables.\section{Symmetric Modes of Operations}\subsection{Background}A typical symmetric block cipher can be used in chaining modes to effectively encrypt messages larger than the blocksize of the cipher.  Given a key $k$, a plaintext $P$ and a cipher $E$ we shall denote the encryption of the block$P$ under the key $k$ as $E_k(P)$.  In some modes there exists an initial vector denoted as $C_{-1}$.\subsubsection{ECB Mode}ECB or Electronic Codebook Mode is the simplest method to use.  It is given as:\begin{equation}C_i = E_k(P_i)\end{equation}This mode is very weak since it allows people to swap blocks and perform replay attacks if the same key is used morethan once.\subsubsection{CBC Mode}CBC or Cipher Block Chaining mode is a simple mode designed to prevent trivial forms of replay and swap attacks on ciphers.It is given as:\begin{equation}C_i = E_k(P_i \oplus C_{i - 1})\end{equation}It is important that the initial vector be unique and preferably random for each message encrypted under the same key.\subsubsection{CTR Mode}CTR or Counter Mode is a mode which only uses the encryption function of the cipher.  Given a initial vector which istreated as a large binary counter the CTR mode is given as:\begin{eqnarray}C_{-1} = C_{-1} + 1\mbox{ }(\mbox{mod }2^W) \nonumber \\C_i = P_i \oplus E_k(C_{-1})\end{eqnarray}Where $W$ is the size of a block in bits (e.g. 64 for Blowfish).  As long as the initial vector is random for each messageencrypted under the same key replay and swap attacks are infeasible.  CTR mode may look simple but it is as secureas the block cipher is under a chosen plaintext attack (provided the initial vector is unique).\subsubsection{CFB Mode}CFB or Ciphertext Feedback Mode is a mode akin to CBC.  It is given as:\begin{eqnarray}C_i = P_i \oplus C_{-1} \nonumber \\C_{-1} = E_k(C_i)\end{eqnarray}Note that in this library the output feedback width is equal to the size of the block cipher.  That is this mode is usedto encrypt whole blocks at a time.  However, the library will buffer data allowing the user to encrypt or decrypt partialblocks without a delay.  When this mode is first setup it will initially encrypt the initial vector as required.\subsubsection{OFB Mode}OFB or Output Feedback Mode is a mode akin to CBC as well.  It is given as:\begin{eqnarray}C_{-1} = E_k(C_{-1}) \nonumber \\C_i = P_i \oplus C_{-1}\end{eqnarray}Like the CFB mode the output width in CFB mode is the same as the width of the block cipher.  OFB mode will alsobuffer the output which will allow you to encrypt or decrypt partial blocks without delay.\subsection{Choice of Mode}My personal preference is for the CTR mode since it has several key benefits:\begin{enumerate}   \item No short cycles which is possible in the OFB and CFB modes.   \item Provably as secure as the block cipher being used under a chosen plaintext attack.   \item Technically does not require the decryption routine of the cipher.   \item Allows random access to the plaintext.   \item Allows the encryption of block sizes that are not equal to the size of the block cipher.\end{enumerate}The CTR, CFB and OFB routines provided allow you to encrypt block sizes that differ from the ciphers block size.  They accomplish this by buffering the data required to complete a block.  This allows you to encrypt or decrypt any size block of memory with either of the three modes.The ECB and CBC modes process blocks of the same size as the cipher at a time.  Therefore they are less flexible than theother modes.\subsection{Implementation}\index{CBC Mode} \index{CTR Mode}\index{OFB Mode} \index{CFB Mode}The library provides simple support routines for handling CBC, CTR, CFB, OFB and ECB encoded messages.  Assuming the mode you want is XXX there is a structure called ``symmetric\_XXX'' that will contain the information required touse that mode.  They have identical setup routines (except ECB mode for obvious reasons):\begin{verbatim}int XXX_start(int cipher, const unsigned char *IV,               const unsigned char *key, int keylen,               int num_rounds, symmetric_XXX *XXX);int ecb_start(int cipher, const unsigned char *key, int keylen,               int num_rounds, symmetric_ECB *ecb);\end{verbatim}In each case ``cipher'' is the index into the cipher\_descriptor array of the cipher you want to use.  The ``IV'' value is the initialization vector to be used with the cipher.  You must fill the IV yourself and it is assumed they are the same length as the block size\footnote{In otherwords the size of a block of plaintext for the cipher, e.g. 8 for DES, 16 for AES, etc.} of the cipher you choose.  It is important that the IV  be random for each unique message you want to encrypt.  The parameters ``key'', ``keylen'' and ``num\_rounds'' are the same as in the XXX\_setup() function call.  The final parameter is a pointer to the structure you want to hold the information for the mode of operation.Both routines return {\bf CRYPT\_OK} if the cipher initialized correctly, otherwise they return an error code.  To actually encrypt or decrypt the following routines are provided:\begin{verbatim}int XXX_encrypt(const unsigned char *pt, unsigned char *ct,                 symmetric_XXX *XXX);int XXX_decrypt(const unsigned char *ct, unsigned char *pt,                symmetric_XXX *XXX);int YYY_encrypt(const unsigned char *pt, unsigned char *ct,                 unsigned long len, symmetric_YYY *YYY);int YYY_decrypt(const unsigned char *ct, unsigned char *pt,                 unsigned long len, symmetric_YYY *YYY);\end{verbatim}Where ``XXX'' is one of (ecb, cbc) and ``YYY'' is one of (ctr, ofb, cfb).  In the CTR, OFB and CFB cases ``len'' is thesize of the buffer (as number of chars) to encrypt or decrypt.  The CTR, OFB and CFB modes are order sensitive but notchunk sensitive.  That is you can encrypt ``ABCDEF'' in three calls like ``AB'', ``CD'', ``EF'' or two like ``ABCDE'' and ``F''and end up with the same ciphertext.  However, encrypting ``ABC'' and ``DABC'' will result in different ciphertexts.  Allfive of the modes will return {\bf CRYPT\_OK} on success from the encrypt or decrypt functions.To decrypt in either mode you simply perform the setup like before (recall you have to fetch the IV value you used)and use the decrypt routine on all of the blocks.  When you are done working with either mode you should wipe the memory (using ``zeromem()'') to help prevent the key from leaking.  For example:\newpage\begin{small}\begin{verbatim}#include <mycrypt.h>int main(void){   unsigned char key[16], IV[16], buffer[512];   symmetric_CTR ctr;   int x, errno;   /* register twofish first */   if (register_cipher(&twofish_desc) == -1) {      printf("Error registering cipher.\n");      return -1;   }   /* somehow fill out key and IV */   /* start up CTR mode */   if ((errno = ctr_start(find_cipher("twofish"), IV, key, 16, 0, &ctr)) != CRYPT_OK) {      printf("ctr_start error: %s\n", error_to_string(errno));      return -1;   }   /* somehow fill buffer than encrypt it */   if ((errno = ctr_encrypt(buffer, buffer, sizeof(buffer), &ctr)) != CRYPT_OK) {      printf("ctr_encrypt error: %s\n", error_to_string(errno));      return -1;   }   /* make use of ciphertext... */   /* clear up and return */   zeromem(key, sizeof(key));   zeromem(&ctr, sizeof(ctr));   return 0;}\end{verbatim}\end{small}\section{Encrypt and Authenticate Modes}\subsection{EAX Mode}LibTomCrypt provides support for a mode called EAX\footnote{See M. Bellare, P. Rogaway, D. Wagner, A Conventional Authenticated-Encryption Mode.} in a manner similar to theway it was intended to be used.First a short description of what EAX mode is before I explain how to use it.  EAX is a mode that requires a cipher,CTR and OMAC support and provides encryption and authentication.  It is initialized with a random ``nonce'' that canbe shared publicly as well as a ``header'' which can be fixed and public as well as a random secret symmetric key.The ``header'' data is meant to be meta-data associated with a stream that isn't private (e.g. protocol messages).  It canbe added at anytime during an EAX stream and is part of the authentication tag.  That is, changes in the meta-data canbe detected by an invalid output tag.The mode can then process plaintext producing ciphertext as well as compute a partial checksum.  The actual checksumcalled a ``tag'' is only emitted when the message is finished.  In the interim though the user can process any arbitrarysized message block to send to the recipient as ciphertext.  This makes the EAX mode especially suited for streaming modesof operation.The mode is initialized with the following function.\begin{verbatim}int eax_init(eax_state *eax, int cipher,              const unsigned char *key, unsigned long keylen,             const unsigned char *nonce, unsigned long noncelen,             const unsigned char *header, unsigned long headerlen);\end{verbatim}Where ``eax'' is the EAX state.  ``cipher'' is the index of the desired cipher in the descriptor table.  ``key'' is the shared secret symmetric key of length ``keylen''.  ``nonce'' is the random public string oflength ``noncelen''.  ``header'' is the random (or fixed or \textbf{NULL}) header for the message of length``headerlen''.When this function completes ``eax'' will be initialized such that you can now either have data decrypted or encrypted in EAX mode.  Note that if ``headerlen'' is zero you may pass ``header'' as \textbf{NULL}.  It will stillinitialize the EAX ``H'' value to the correct value.  To encrypt or decrypt data in a streaming mode use the following.\begin{verbatim}int eax_encrypt(eax_state *eax, const unsigned char *pt,                 unsigned char *ct, unsigned long length);int eax_decrypt(eax_state *eax, const unsigned char *ct,                 unsigned char *pt, unsigned long length);\end{verbatim}The function ``eax\_encrypt'' will encrypt the bytes in ``pt'' of ``length'' bytes and store the ciphertext in``ct''.  Note that ``ct'' and ``pt'' may be the same region in memory.   This function will also send the ciphertextthrough the OMAC function.  The function ``eax\_decrypt'' decrypts ``ct'' and stores it in ``pt''.  This also allows ``pt'' and ``ct'' to be the same region in memory.  Note that both of these functions allow you to send the data in any granularity but the order is important.  Whilethe eax\_init() function allows you to add initial header data to the stream you can also add header data during theEAX stream with the following.Also note that you cannot both encrypt or decrypt with the same ``eax'' context.  For bi-directional communication youwill need to initialize two EAX contexts (preferably with different headers and nonces).  \begin{verbatim}int eax_addheader(eax_state *eax,                   const unsigned char *header, unsigned long length);\end{verbatim}This will add the ``length'' bytes from ``header'' to the given ``eax'' stream.  Once the message is finished the ``tag'' (checksum) may be computed with the following function.\begin{verbatim}int eax_done(eax_state *eax,              unsigned char *tag, unsigned long *taglen);\end{verbatim}This will terminate the EAX state ``eax'' and store upto ``taglen'' bytes of the message tag in ``tag''.  The functionthen stores how many bytes of the tag were written out back into ``taglen''.The EAX mode code can be tested to ensure it matches the test vectors by calling the following function.\begin{verbatim}int eax_test(void);\end{verbatim}This requires that the AES (or Rijndael) block cipher be registered with the cipher\_descriptor table first.\subsection{OCB Mode}LibTomCrypt provides support for a mode called OCB\footnote{See P. Rogaway, M. Bellare, J. Black, T. Krovetz, ``OCB: A Block Cipher Mode of Operation for Efficient Authenticated Encryption''.}in a mode somewhat similar to as it was meant to be used.OCB is an encryption protocol that simultaneously provides authentication.  It is slightly faster to use than EAX modebut is less flexible.  Let's review how to initialize an OCB context.\begin{verbatim}int ocb_init(ocb_state *ocb, int cipher,              const unsigned char *key, unsigned long keylen,              const unsigned char *nonce);\end{verbatim}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?