⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 crypt.tex

📁 NIST推荐的素域上的椭圆曲线
💻 TEX
📖 第 1 页 / 共 5 页
字号:
    if ((errno = rsa_export(buffer, &x, PK_PUBLIC, &key)) != CRYPT_OK) {       printf("Export error: %s\n", error_to_string(errno));       return -1;    }        /* if rsa_export() was successful then x will have the size of the output */    printf("RSA exported key takes %d bytes\n", x);    /* ... do something with the buffer */    return 0;}\end{verbatim}\end{small}In the above example if the size of the RSA public key was more than 1024 bytes this function would not store anything ineither ``buffer'' or ``x'' and simply return an error code.  If the function suceeds it stores the length of the outputback into ``x'' so that the calling application will know how many bytes used.\section{Functions that need a PRNG}Certain functions such as ``rsa\_make\_key()'' require a PRNG.  These functions do not setup the PRNG themselves so it is the responsibility of the calling function to initialize the PRNG before calling them.\section{Functions that use Arrays of Octets}Most functions require inputs that are arrays of the data type ``unsigned char''.  Whether it is a symmetric key, IVfor a chaining mode or public key packet it is assumed that regardless of the actual size of ``unsigned char'' only thelower eight bits contain data.  For example, if you want to pass a 256 bit key to a symmetric ciphers setup routineyou must pass it in (a pointer to) an array of 32 ``unsigned char'' variables.  Certain routines (such as SAFER+) take special care to work properly on platforms where an ``unsigned char'' is not eight bits.For the purposes of this library the term ``byte'' will refer to an octet or eight bit word.  Typically an array oftype ``byte'' will be synonymous with an array of type ``unsigned char''.\chapter{Symmetric Block Ciphers}\section{Core Functions}Libtomcrypt provides several block ciphers all in a plain vanilla ECB block mode.  Its important to first note that you should never use the ECB modes directly to encrypt data.  Instead you should use the ECB functions to make a chaining modeor use one of the provided chaining modes.  All of the ciphers are written as ECB interfaces since it allows the rest ofthe API to grow in a modular fashion.All ciphers store their scheduled keys in a single data type called ``symmetric\_key''.  This allows all ciphers to have the same prototype and store their keys as  naturally as possible.  All ciphers provide five visible functions whichare (given that XXX is the name of the cipher):\index{Cipher Setup}\begin{verbatim}int XXX_setup(const unsigned char *key, int keylen, int rounds,               symmetric_key *skey);\end{verbatim}The XXX\_setup() routine will setup the cipher to be used with a given number of rounds and a given key length (in bytes).The number of rounds can be set to zero to use the default, which is generally a good idea.If the function returns successfully the variable ``skey'' will have a scheduled key stored in it.  Its important to notethat you should only used this scheduled key with the intended cipher.  For example, if you call ``blowfish\_setup()'' do not pass the scheduled key onto ``rc5\_ecb\_encrypt()''.  All setup functions do not allocate memory off the heap so when you are done with a key you can simply discard it (e.g. they can be on the stack).To encrypt or decrypt a block in ECB mode there are these two functions:\index{Cipher Encrypt} \index{Cipher Decrypt}\begin{verbatim}void XXX_ecb_encrypt(const unsigned char *pt, unsigned char *ct,                     symmetric_key *skey);void XXX_ecb_decrypt(const unsigned char *ct, unsigned char *pt,                     symmetric_key *skey);\end{verbatim}These two functions will encrypt or decrypt (respectively) a single block of text\footnote{The size of which depends onwhich cipher you are using.} and store the result where you want it.  It is possible that the input and output buffer are the same buffer.  For the encrypt function ``pt''\footnote{pt stands for plaintext.} is the input and ``ct'' is the output.For the decryption function its the opposite.  To test a particular cipher against test vectors\footnote{As published in their design papers.} call: \index{Cipher Testing}\begin{verbatim}int XXX_test(void);\end{verbatim}This function will return {\bf CRYPT\_OK} if the cipher matches the test vectors from the design publication it is based upon.  Finally for each cipher there is a function which will help find a desired key size:\begin{verbatim}int XXX_keysize(int *keysize);\end{verbatim}Essentially it will round the input keysize in ``keysize'' down to the next appropriate key size.  This functionreturn {\bf CRYPT\_OK} if the key size specified is acceptable.  For example:\begin{small}\begin{verbatim}#include <mycrypt.h>int main(void){   int keysize, errno;   /* now given a 20 byte key what keysize does Twofish want to use? */   keysize = 20;   if ((errno = twofish_keysize(&keysize)) != CRYPT_OK) {      printf("Error getting key size: %s\n", error_to_string(errno));      return -1;   }   printf("Twofish suggested a key size of %d\n", keysize);   return 0;}\end{verbatim}\end{small}This should indicate a keysize of sixteen bytes is suggested.  An example snippet that encodes a block with Blowfish in ECB mode is below.\begin{small}\begin{verbatim}#include <mycrypt.h>int main(void){    unsigned char pt[8], ct[8], key[8];   symmetric_key skey;   int errno;   /* first register Blowfish */   if (register_cipher(&blowfish_desc) == -1) {      printf("Error registering Blowfish.\n");      return -1;   }   /* ... key is loaded appropriately in ``key'' ... */   /* ... load a block of plaintext in ``pt'' ... */   /* schedule the key */   if ((errno = blowfish_setup(key, 8, 0, &skey)) != CRYPT_OK) {      printf("Setup error: %s\n", error_to_string(errno));      return -1;   }   /* encrypt the block */   blowfish_ecb_encrypt(pt, ct, &skey);   /* decrypt the block */   blowfish_ecb_decrypt(ct, pt, &skey);   return 0;}\end{verbatim}\end{small}\section{Key Sizes and Number of Rounds}\index{Symmetric Keys}As a general rule of thumb do not use symmetric keys under 80 bits if you can.  Only a few of the ciphers support smallerkeys (mainly for test vectors anyways).  Ideally your application should be making at least 256 bit keys.  This is notbecause you're supposed to be paranoid.  Its because if your PRNG has a bias of any sort the more bits the better.  Forexample, if you have $\mbox{Pr}\left[X = 1\right] = {1 \over 2} \pm \gamma$ where $\vert \gamma \vert > 0$ then thetotal amount of entropy in N bits is $N \cdot -log_2\left ({1 \over 2} + \vert \gamma \vert \right)$.  So if $\gamma$were $0.25$ (a severe bias) a 256-bit string would have about 106 bits of entropy whereas a 128-bit string would haveonly 53 bits of entropy.The number of rounds of most ciphers is not an option you can change.  Only RC5 allows you to change the number ofrounds.  By passing zero as the number of rounds all ciphers will use their default number of rounds.  Generally theciphers are configured such that the default number of rounds provide adequate security for the given block size.\section{The Cipher Descriptors}\index{Cipher Descriptor}To facilitate automatic routines an array of cipher descriptors is provided in the array ``cipher\_descriptor''.  An elementof this array has the following format:\begin{verbatim}struct _cipher_descriptor {   char *name;   unsigned long min_key_length, max_key_length,                  block_length, default_rounds;   int  (*setup)      (const unsigned char *key, int keylength,                        int num_rounds, symmetric_key *skey);   void (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct,                        symmetric_key *key);   void (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt,                       symmetric_key *key);   int  (*test)       (void);   int  (*keysize)    (int *desired_keysize);};\end{verbatim}Where ``name'' is the lower case ASCII version of the name.  The fields ``min\_key\_length'', ``max\_key\_length'' and``block\_length'' are all the number of bytes not bits.  As a good rule of thumb it is assumed that the cipher supportsthe min and max key lengths but not always everything in between.  The ``default\_rounds'' field is the default numberof rounds that will be used.The remaining fields are all pointers to the core functions for each cipher.  The end of the cipher\_descriptor array ismarked when ``name'' equals {\bf NULL}.As of this release the current cipher\_descriptors elements are\begin{small}\begin{center}\begin{tabular}{|c|c|c|c|c|c|}     \hline Name & Descriptor Name & Block Size (bytes) & Key Range (bytes) & Rounds \\     \hline Blowfish & blowfish\_desc & 8 & 8 ... 56 & 16 \\     \hline X-Tea & xtea\_desc & 8 & 16 & 32 \\     \hline RC2 & rc2\_desc & 8 & 8 .. 128 & 16 \\     \hline RC5-32/12/b & rc5\_desc & 8 & 8 ... 128 & 12 ... 24 \\     \hline RC6-32/20/b & rc6\_desc & 16 & 8 ... 128 & 20 \\     \hline SAFER+ & saferp\_desc &16 & 16, 24, 32 & 8, 12, 16 \\     \hline Safer K64   & safer\_k64\_desc & 8 & 8 & 6 .. 13 \\     \hline Safer SK64  & safer\_sk64\_desc & 8 & 8 & 6 .. 13 \\     \hline Safer K128  & safer\_k128\_desc & 8 & 16 & 6 .. 13 \\     \hline Safer SK128 & safer\_sk128\_desc & 8 & 16 & 6 .. 13 \\     \hline Serpent & serpent\_desc & 16 & 16 .. 32 & 32 \\     \hline Rijndael (AES) & rijndael\_desc & 16 & 16, 24, 32 & 10, 12, 14 \\     \hline Twofish & twofish\_desc & 16 & 16, 24, 32 & 16 \\     \hline DES & des\_desc & 8 & 7 & 16 \\     \hline 3DES (EDE mode) & des3\_desc & 8 & 21 & 16 \\     \hline CAST5 (CAST-128) & cast5\_desc & 8 & 5 .. 16 & 12, 16 \\     \hline\end{tabular}\end{center}\end{small}\subsection{Notes}For the 64-bit SAFER famliy of ciphers (e.g K64, SK64, K128, SK128) the ecb\_encrypt() and ecb\_decrypt()functions are the same.  So if you want to use those functions directly just call safer\_ecb\_encrypt()or safer\_ecb\_decrypt() respectively.Note that for ``DES'' and ``3DES'' they use 8 and 24 byte keys but only 7 and 21 [respectively] bytes of the keys are infact used for the purposes of encryption.  My suggestion is just to use random 8/24 byte keys instead of trying to make a 8/24byte string from the real 7/21 byte key.Note that ``Twofish'' has additional configuration options that take place at build time.  These options are found inthe file ``mycrypt\_cfg.h''.  The first option is ``TWOFISH\_SMALL'' which when defined will force the Twofish codeto not pre-compute the Twofish ``$g(X)$'' function as a set of four $8 \times 32$ s-boxes.  This means that a scheduledkey will require less ram but the resulting cipher will be slower.  The second option is ``TWOFISH\_TABLES'' which whendefined will force the Twofish code to use pre-computed tables for the two s-boxes $q_0, q_1$ as well as the multiplicationby the polynomials 5B and EF used in the MDS multiplication.  As a result the code is faster and slightly larger.  Thespeed increase is useful when ``TWOFISH\_SMALL'' is defined since the s-boxes and MDS multiply form the heart of theTwofish round function.\begin{small}\begin{center}\begin{tabular}{|l|l|l|}\hline TWOFISH\_SMALL & TWOFISH\_TABLES & Speed and Memory (per key) \\\hline undefined & undefined & Very fast, 4.2KB of ram. \\\hline undefined & defined & As above, faster keysetup, larger code (1KB more). \\\hline defined & undefined & Very slow, 0.2KB of ram. \\\hline defined & defined & Somewhat faster, 0.2KB of ram, larger code. \\\hline\end{tabular}\end{center}\end{small}To work with the cipher\_descriptor array there is a function:\begin{verbatim}int find_cipher(char *name)\end{verbatim}Which will search for a given name in the array.  It returns negative one if the cipher is not found, otherwise it returnsthe location in the array where the cipher was found.  For example, to indirectly setup Blowfish you can also use:\begin{small}\begin{verbatim}#include <mycrypt.h>int main(void){   unsigned char key[8];   symmetric_key skey;   int errno;   /* you must register a cipher before you use it */   if (register_cipher(&blowfish_desc)) == -1) {      printf("Unable to register Blowfish cipher.");      return -1;   }   /* generic call to function (assuming the key in key[] was already setup) */   if ((errno = cipher_descriptor[find_cipher("blowfish")].setup(key, 8, 0, &skey)) != CRYPT_OK) {      printf("Error setting up Blowfish: %s\n", error_to_string(errno));      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) {

⌨️ 快捷键说明

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