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
Post a Comment