c - How to change a block cipher algorithms ciphertext and plaintext length -


i designing encryption program. use sm4 block cipher algorithm. now, program requires ciphertext , plaintext 64bit long , key 128bit long, sm4's ciphertext , plaintext 128bit long. try more different way, result of decrypt incorrect. how can change 64bit?

this source code:

sm4.h:

/**  * \file sm4.h  */ #ifndef xyssl_sm4_h #define xyssl_sm4_h  #define sm4_encrypt     1 #define sm4_decrypt     0  /**  * \brief          sm4 context structure  */ typedef struct {     int mode;                   /*!<  encrypt/decrypt   */     unsigned long sk[32];       /*!<  sm4 subkeys       */ } sm4_context;   #ifdef __cplusplus extern "c" { #endif  /**  * \brief          sm4 key schedule (128-bit, encryption)  *  * \param ctx      sm4 context initialized  * \param key      16-byte secret key  */ void sm4_setkey_enc( sm4_context *ctx, unsigned char key[16] );  /**  * \brief          sm4 key schedule (128-bit, decryption)  *  * \param ctx      sm4 context initialized  * \param key      16-byte secret key  */ void sm4_setkey_dec( sm4_context *ctx, unsigned char key[16] );  /**  * \brief          sm4-ecb block encryption/decryption  * \param ctx      sm4 context  * \param mode     sm4_encrypt or sm4_decrypt  * \param length   length of input data  * \param input    input block  * \param output   output block  */ void sm4_crypt_ecb( sm4_context *ctx,                      int mode,                      int length,                      unsigned char *input,                      unsigned char *output);  /**  * \brief          sm4-cbc buffer encryption/decryption  * \param ctx      sm4 context  * \param mode     sm4_encrypt or sm4_decrypt  * \param length   length of input data  * \param iv       initialization vector (updated after use)  * \param input    buffer holding input data  * \param output   buffer holding output data  */ void sm4_crypt_cbc( sm4_context *ctx,                      int mode,                      int length,                      unsigned char iv[16],                      unsigned char *input,                      unsigned char *output );  #ifdef __cplusplus } #endif  #endif /* sm4.h */ 

sm4.c

/*  * sm4 encryption alogrithm (sms4 algorithm)  * gm/t 0002-2012 chinese national standard ref:http://www.oscca.gov.cn/   * xyssl  * thnaks , refers http://hi.baidu.com/numax/blog/item/80addfefddfb93e4cf1b3e61.html  * author:goldboar  * email:goldboar@163.com  * 2012-4-20  */  // test vector 1 // plain: 01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10 // key:   01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10 //     round key , temp computing result: //     rk[ 0] = f12186f9 x[ 0] = 27fad345 //         rk[ 1] = 41662b61 x[ 1] = a18b4cb2 //         rk[ 2] = 5a6ab19a x[ 2] = 11c1e22a //         rk[ 3] = 7ba92077 x[ 3] = cc13e2ee //         rk[ 4] = 367360f4 x[ 4] = f87c5bd5 //         rk[ 5] = 776a0c61 x[ 5] = 33220757 //         rk[ 6] = b6bb89b3 x[ 6] = 77f4c297 //         rk[ 7] = 24763151 x[ 7] = 7a96f2eb //         rk[ 8] = a520307c x[ 8] = 27dac07f //         rk[ 9] = b7584dbd x[ 9] = 42dd0f19 //         rk[10] = c30753ed x[10] = b8a5da02 //         rk[11] = 7ee55b57 x[11] = 907127fa //         rk[12] = 6988608c x[12] = 8b952b83 //         rk[13] = 30d895b7 x[13] = d42b7c59 //         rk[14] = 44ba14af x[14] = 2ffc5831 //         rk[15] = 104495a1 x[15] = f69e6888 //         rk[16] = d120b428 x[16] = af2432c4 //         rk[17] = 73b55fa3 x[17] = ed1ec85e //         rk[18] = cc874966 x[18] = 55a3ba22 //         rk[19] = 92244439 x[19] = 124b18aa //         rk[20] = e89e641f x[20] = 6ae7725f //         rk[21] = 98ca015a x[21] = f4cba1f9 //         rk[22] = c7159060 x[22] = 1dcdfa10 //         rk[23] = 99e1fd2e x[23] = 2ff60603 //         rk[24] = b79bd80c x[24] = eff24fdc //         rk[25] = 1d2115b0 x[25] = 6fe46b75 //         rk[26] = 0e228aeb x[26] = 893450ad //         rk[27] = f1780c81 x[27] = 7b938f4c //         rk[28] = 428d3654 x[28] = 536e4246 //         rk[29] = 62293496 x[29] = 86b3e94f //         rk[30] = 01cf72e5 x[30] = d206965e //         rk[31] = 9124a012 x[31] = 681edf34 // cypher: 68 1e df 34 d2 06 96 5e 86 b3 e9 4f 53 6e 42 46 //       // test vector 2 // same key , plain 1000000 times coumpting  // plain:  01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10 // key:    01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10 // cypher: 59 52 98 c7 c6 fd 27 1f 04 02 f8 04 c3 3d 3f 66  #include "sm4.h" #include <string.h> #include <stdio.h>  /*  * 32-bit integer manipulation macros (big endian)  */ #ifndef get_ulong_be #define get_ulong_be(n,b,i)                             \ {                                                       \     (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \         | ( (unsigned long) (b)[(i) + 1] << 16 )        \         | ( (unsigned long) (b)[(i) + 2] <<  8 )        \         | ( (unsigned long) (b)[(i) + 3]       );       \ } #endif  #ifndef put_ulong_be #define put_ulong_be(n,b,i)                             \ {                                                       \     (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \     (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \     (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \     (b)[(i) + 3] = (unsigned char) ( (n)       );       \ } #endif  /*  *rotate shift left marco definition  *  */ #define  shl(x,n) (((x) & 0xffffffff) << n) #define rotl(x,n) (shl((x),n) | ((x) >> (32 - n)))  #define swap(a,b) { unsigned long t = a; = b; b = t; t = 0; }  /*  * expanded sm4 s-boxes  /* sbox table: 8bits input convert 8 bits output*/  static const unsigned char sboxtable[16][16] =  { {0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05}, {0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99}, {0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62}, {0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6}, {0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8}, {0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35}, {0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87}, {0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e}, {0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1}, {0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3}, {0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f}, {0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51}, {0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8}, {0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0}, {0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84}, {0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48} };  /* system parameter */ static const unsigned long fk[4] = {0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc};  /* fixed parameter */ static const unsigned long ck[32] = { 0x00070e15,0x1c232a31,0x383f464d,0x545b6269, 0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9, 0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249, 0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9, 0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229, 0x30373e45,0x4c535a61,0x686f767d,0x848b9299, 0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209, 0x10171e25,0x2c333a41,0x484f565d,0x646b7279 };   /*  * private function:  * in sboxtable , related value.  * args:    [in] inch: 0x00~0xff (8 bits unsigned value).  */ static unsigned char sm4sbox(unsigned char inch) {     unsigned char *ptable = (unsigned char *)sboxtable;     unsigned char retval = (unsigned char)(ptable[inch]);     return retval; }  /*  * private f(lt) function:  * "t algorithm" == "l algorithm" + "t algorithm".  * args:    [in] a: 32 bits unsigned value;  * return: c: c calculated line algorithm "l" , nonline algorithm "t"  */ static unsigned long sm4lt(unsigned long ka) {     unsigned long bb = 0;     unsigned long c = 0;     unsigned char a[4];     unsigned char b[4];     put_ulong_be(ka,a,0)     b[0] = sm4sbox(a[0]);     b[1] = sm4sbox(a[1]);     b[2] = sm4sbox(a[2]);     b[3] = sm4sbox(a[3]);     get_ulong_be(bb,b,0)     c =bb^(rotl(bb, 2))^(rotl(bb, 10))^(rotl(bb, 18))^(rotl(bb, 24));     return c; }  /*  * private f function:  * calculating , getting encryption/decryption contents.  * args:    [in] x0: original contents;  * args:    [in] x1: original contents;  * args:    [in] x2: original contents;  * args:    [in] x3: original contents;  * args:    [in] rk: encryption/decryption key;  * return contents of encryption/decryption contents.  */ static unsigned long sm4f(unsigned long x0, unsigned long x1, unsigned long x2, unsigned long x3, unsigned long rk) {     return (x0^sm4lt(x1^x2^x3^rk)); }   /* private function:  * calculating round encryption key.  * args:    [in] a: 32 bits unsigned value;  * return: sk[i]: i{0,1,2,3,...31}.  */ static unsigned long sm4calcirk(unsigned long ka) {     unsigned long bb = 0;     unsigned long rk = 0;     unsigned char a[4];     unsigned char b[4];     put_ulong_be(ka,a,0)     b[0] = sm4sbox(a[0]);     b[1] = sm4sbox(a[1]);     b[2] = sm4sbox(a[2]);     b[3] = sm4sbox(a[3]);     get_ulong_be(bb,b,0)     rk = bb^(rotl(bb, 13))^(rotl(bb, 23));     return rk; }  static void sm4_setkey( unsigned long sk[32], unsigned char key[16] ) {     unsigned long mk[4];     unsigned long k[36];     unsigned long = 0;      get_ulong_be( mk[0], key, 0 );     get_ulong_be( mk[1], key, 4 );     get_ulong_be( mk[2], key, 8 );     get_ulong_be( mk[3], key, 12 );     k[0] = mk[0]^fk[0];     k[1] = mk[1]^fk[1];     k[2] = mk[2]^fk[2];     k[3] = mk[3]^fk[3];     for(; i<32; i++)     {         k[i+4] = k[i] ^ (sm4calcirk(k[i+1]^k[i+2]^k[i+3]^ck[i]));         sk[i] = k[i+4];     }  }  /*  * sm4 standard 1 round processing  *  */ static void sm4_one_round( unsigned long sk[32],                     unsigned char input[16],                     unsigned char output[16] ) {     unsigned long = 0;     unsigned long ulbuf[36];      memset(ulbuf, 0, sizeof(ulbuf));     get_ulong_be( ulbuf[0], input, 0 )     get_ulong_be( ulbuf[1], input, 4 )     get_ulong_be( ulbuf[2], input, 8 )     get_ulong_be( ulbuf[3], input, 12 )     while(i<32)     {         ulbuf[i+4] = sm4f(ulbuf[i], ulbuf[i+1], ulbuf[i+2], ulbuf[i+3], sk[i]); // #ifdef _debug //          printf("rk(%02d) = 0x%08x,  x(%02d) = 0x%08x \n",i,sk[i], i, ulbuf[i+4] ); // #endif         i++;     }     put_ulong_be(ulbuf[35],output,0);     put_ulong_be(ulbuf[34],output,4);     put_ulong_be(ulbuf[33],output,8);     put_ulong_be(ulbuf[32],output,12); }  /*  * sm4 key schedule (128-bit, encryption)  */ void sm4_setkey_enc( sm4_context *ctx, unsigned char key[16] ) {     ctx->mode = sm4_encrypt;     sm4_setkey( ctx->sk, key ); }  /*  * sm4 key schedule (128-bit, decryption)  */ void sm4_setkey_dec( sm4_context *ctx, unsigned char key[16] ) {     int i;     ctx->mode = sm4_encrypt;     sm4_setkey( ctx->sk, key );     for( = 0; < 16; ++ )     {         swap( ctx->sk[ ], ctx->sk[ 31-i] );     } }   /*  * sm4-ecb block encryption/decryption  */  void sm4_crypt_ecb( sm4_context *ctx,                    int mode,                    int length,                    unsigned char *input,                    unsigned char *output) {     while( length > 0 )     {         sm4_one_round( ctx->sk, input, output );         input  += 16;         output += 16;         length -= 16;     }  }  /*  * sm4-cbc buffer encryption/decryption  */ void sm4_crypt_cbc( sm4_context *ctx,                     int mode,                     int length,                     unsigned char iv[16],                     unsigned char *input,                     unsigned char *output ) {     int i;     unsigned char temp[16];      if( mode == sm4_encrypt )     {         while( length > 0 )         {             for( = 0; < 16; i++ )                 output[i] = (unsigned char)( input[i] ^ iv[i] );              sm4_one_round( ctx->sk, output, output );             memcpy( iv, output, 16 );              input  += 16;             output += 16;             length -= 16;         }     }     else /* sm4_decrypt */     {         while( length > 0 )         {             memcpy( temp, input, 16 );             sm4_one_round( ctx->sk, input, output );              for( = 0; < 16; i++ )                 output[i] = (unsigned char)( output[i] ^ iv[i] );              memcpy( iv, temp, 16 );              input  += 16;             output += 16;             length -= 16;         }     } } 

sm4test.c:

/*  * sm4/sms4 algorithm test programme  * 2012-4-21  */  #include <string.h> #include <stdio.h> #include "sm4.h"  int main() {     unsigned char key[16] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};     unsigned char input[16] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};     unsigned char output[16];     sm4_context ctx;     unsigned long i;      //encrypt standard testing vector     sm4_setkey_enc(&ctx,key);     sm4_crypt_ecb(&ctx,1,16,input,output);     for(i=0;i<16;i++)         printf("%02x ", output[i]);     printf("\n");      //decrypt testing     sm4_setkey_dec(&ctx,key);     sm4_crypt_ecb(&ctx,0,16,output,output);     for(i=0;i<16;i++)         printf("%02x ", output[i]);     printf("\n");      //decrypt 1m times testing vector based on standards.     = 0;     sm4_setkey_enc(&ctx,key);     while (i<1000000)      {         sm4_crypt_ecb(&ctx,1,16,input,input);         i++;     }     for(i=0;i<16;i++)         printf("%02x ", input[i]);     printf("\n");      return 0; } 

the normal way use block cipher encrypt/decrypt plaintext of arbitrary length pad whole number of blocks known padding method - example, pkcs7 - , use block chaining method encrypt sequence of blocks. when decrypt, padding tells how many bytes remove recover original length of plaintext. ciphertext whole number of blocks in length. in case, there single block anyway because plaintext short.

if fixed length, , know input/output 64 bits, discard later 64 bits. otherwise, @ block cipher chaining mode (cbc, ctr, gcm etc) , padding - normal way block cipher used.


Comments

Popular posts from this blog

qt - Using float or double for own QML classes -

Create Outlook appointment via C# .Net -

ios - Swift Array Resetting Itself -