-
-
[原创]常见密码算法总结--(4)加密模式的openssl代码分析之cfb模式
-
发表于: 2010-6-16 12:39 6216
-
其他见:
《常见密码算法总结--(1)分组对称密码》见
http://bbs.pediy.com/showthread.php?t=113921
http://blog.csdn.net/NJZhuJinhua/archive/2010/05/27/5629455.aspx
《常见密码算法总结--(2)分组密码加密模式》见
http://bbs.pediy.com/showthread.php?t=114169
http://blog.csdn.net/NJZhuJinhua/archive/2010/05/30/5635313.aspx
《常见密码算法总结--(3)加密模式的openssl代码分析之cbc模式》
NJZhuJinhua@csdn May.30, 2010
http://bbs.pediy.com/showthread.php?t=114170
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/NJZhuJinhua/archive/2010/05/30/5635343.aspx
NJZhuJinhua@csdn Jun.6, 2010
转载请注明出处。
(2)CRYPTO_cfb128_encrypt CRYPTO_cfb128_1_encrypt CRYPTO_cfb128_8_encrypt
这三个实现了cfb模式的三种制式。其函数声明见上文描述。
这三种均被seed_cfb.c cmll_cfb.c aes_cfb.c引用。
在aes_cfb.c内使用情况如下:
上述中的cfb1,cfb8,cfb128分别指cfb模式中分组继续分段的段的大小,分别为1位,8位机128位
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/NJZhuJinhua/archive/2010/06/06/5651871.aspx
《常见密码算法总结--(1)分组对称密码》见
http://bbs.pediy.com/showthread.php?t=113921
http://blog.csdn.net/NJZhuJinhua/archive/2010/05/27/5629455.aspx
《常见密码算法总结--(2)分组密码加密模式》见
http://bbs.pediy.com/showthread.php?t=114169
http://blog.csdn.net/NJZhuJinhua/archive/2010/05/30/5635313.aspx
《常见密码算法总结--(3)加密模式的openssl代码分析之cbc模式》
NJZhuJinhua@csdn May.30, 2010
http://bbs.pediy.com/showthread.php?t=114170
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/NJZhuJinhua/archive/2010/05/30/5635343.aspx
NJZhuJinhua@csdn Jun.6, 2010
转载请注明出处。
(2)CRYPTO_cfb128_encrypt CRYPTO_cfb128_1_encrypt CRYPTO_cfb128_8_encrypt
这三个实现了cfb模式的三种制式。其函数声明见上文描述。
这三种均被seed_cfb.c cmll_cfb.c aes_cfb.c引用。
在aes_cfb.c内使用情况如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | void AES_cfb128_encrypt(const unsigned char * in , unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, int *num, const int enc) { CRYPTO_cfb128_encrypt( in ,out,length,key,ivec,num,enc,(block128_f)AES_encrypt); } /* N.B. This expects the input to be packed, MS bit first */ void AES_cfb1_encrypt(const unsigned char * in , unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, int *num, const int enc) { CRYPTO_cfb128_1_encrypt( in ,out,length,key,ivec,num,enc,(block128_f)AES_encrypt); } void AES_cfb8_encrypt(const unsigned char * in , unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, int *num, const int enc) { CRYPTO_cfb128_8_encrypt( in ,out,length,key,ivec,num,enc,(block128_f)AES_encrypt); } |
上述中的cfb1,cfb8,cfb128分别指cfb模式中分组继续分段的段的大小,分别为1位,8位机128位
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | /* The input and output encrypted as though 128bit cfb mode is being * used. The extra state information to record how much of the * 128bit block we have used is contained in *num; */ void CRYPTO_cfb128_encrypt(const unsigned char * in , unsigned char *out, size_t len, const void *key, unsigned char ivec[16], int *num, int enc, block128_f block) { unsigned int n; size_t l = 0; assert( in && out && key && ivec && num); n = *num; if (enc) 加密时 { #if !defined(OPENSSL_SMALL_FOOTPRINT) if (16%sizeof(size_t) == 0) /* always true actually */ { do { while (n && len) { *(out++) = ivec[n] ^= *( in ++); --len; n = (n+1) % 16; } 上述代码段中n最多在n,(n+1)%16,...,15之间,len最多在len,len-1,...,len-14之间变动,具体变动范围还要看16-n与len的关系。 16-n>len时 依次执行的是ivec[n...n+(len-1)]和明文 in [0...(len-1)]的异或,之后len的值变为0了,即明文已用完。 假设len为6, n=3的话是 ivec [0 1 2 3 4 5 6 7 8 9 0 a b c d e f] in [0 1 2 3 4 5] 的异或得到out,此时得到的out后后面没机会执行了,没加密意义。 16-n<=len时依次执行的是ivec[n...n+(len-1)]和明文 in [0...(15-n)]的异或,之后n的值变为0了。 假设len为>=13, n=3的话是 ivec [0 1 2 3 4 5 6 7 8 9 a b c d e f] in [0 1 2 3 4 5 6 7 8 9 a b c] 的异或得到out及新的ivec,如 out[0]=ivec[3]^ in [0];out[c]=ivec[f]^ in [c],out[d]=0; ivec[0]=ivec[0],ivec[5]=ivec[5]^ in [2]; 如上生成的out均算是成品了, #if defined(STRICT_ALIGNMENT) if (((size_t) in |(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) break ; #endif while (len>=16) { 对于剩余的明文长度大于等于16时进行迭代,即用密钥key加密上面或上一次的本处循环生成的生成ivec,ivec的密文继续作为ivec,并与明文分组进行异或。如此循环知道len<16了 (*block)(ivec, ivec, key); for (n=0; n<16; n+=sizeof(size_t)) { *(size_t*)(out+n) = *(size_t*)(ivec+n) ^= *(size_t*)( in +n); } len -= 16; out += 16; in += 16; } n = 0; if (len) {这里意味着len大于0小于16了,那么生成新的一组流ivec,并将前len长度字节与剩余的len长度明文进行异或,得到最后不足一分组的密文输出。 (*block)(ivec, ivec, key); while (len--) { out[n] = ivec[n] ^= in [n]; ++n; } } *num = n; 设置num值,这里n为最后一个ivec那个使用的字节数。 设明文长度为len,入参*num值为num_in可以推断出,出参*num值为(len+(num_in-1))%16 return ; } while (0); } /* the rest would be commonly eliminated by x86* compiler */ #endif while (l<len) {这里根本就不会执行 if (n == 0) { (*block)(ivec, ivec, key); } out[l] = ivec[n] ^= in [l]; ++l; n = (n+1) % 16; } *num = n; } else { // 解密 原理同上,只是一个逆过程,不再赘述。 #if !defined(OPENSSL_SMALL_FOOTPRINT) if (16%sizeof(size_t) == 0) do { /* always true actually */ while (n && len) { unsigned char c; *(out++) = ivec[n] ^ (c = *( in ++)); ivec[n] = c; --len; n = (n+1) % 16; } #if defined(STRICT_ALIGNMENT) if (((size_t) in |(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) break ; #endif while (len>=16) { (*block)(ivec, ivec, key); for (n=0; n<16; n+=sizeof(size_t)) { size_t t = *(size_t*)( in +n); *(size_t*)(out+n) = *(size_t*)(ivec+n) ^ t; *(size_t*)(ivec+n) = t; } len -= 16; out += 16; in += 16; } n = 0; if (len) { (*block)(ivec, ivec, key); while (len--) { unsigned char c; out[n] = ivec[n] ^ (c = in [n]); ivec[n] = c; ++n; } } *num = n; return ; } while (0); /* the rest would be commonly eliminated by x86* compiler */ #endif while (l<len) { unsigned char c; if (n == 0) { (*block)(ivec, ivec, key); } out[l] = ivec[n] ^ (c = in [l]); ivec[n] = c; ++l; n = (n+1) % 16; } *num=n; } } /* This expects a single block of size nbits for both in and out. Note that it corrupts any extra bits in the last byte of out */ static void cfbr_encrypt_block(const unsigned char * in ,unsigned char *out, int nbits,const void *key, unsigned char ivec[16],int enc, block128_f block) { int n,rem,num; unsigned char ovec[16*2 + 1]; /* +1 because we dererefence (but don't use) one byte off the end */ if (nbits<=0 || nbits>128) return ; /* fill in the first half of the new IV with the current IV */ memcpy(ovec,ivec,16); // 向量变化:ovec=ivec[0...15]|NULL /* construct the new IV */ (*block)(ivec,ivec,key); //Ek (ivec) num = (nbits+7) /8 ; // nbits位对应的字节数 if (enc) /* encrypt the input */ { // 对应加密过程 for (n=0 ; n < num ; ++n) out[n] = (ovec[16+n] = in [n] ^ ivec[n]); // 设1<=nbits<=8 则num为1。则此处仅 // out[0]=ovec[16]= in [0]^ivec[0]= in [0]^(Ek(ivec))[0]; // 向量变化:ovec=ivec[0...15]| in [0]^(Ek(ivec))[0]; } else /* decrypt the input */ { // 对应解密过程 for (n=0 ; n < num ; ++n) out[n] = (ovec[16+n] = in [n]) ^ ivec[n]; // 与上完全一样,不过 in 代表密文,out代表输出的明文了 // 向量变化:ovec=ivec[0...15]| in [0]^(Ek(ivec))[0]; } /* shift ovec left... */ rem = nbits%8; //ovec 要左移的位数 num = nbits /8 ; if (rem==0) { // 可见 1<=num<=16 memcpy(ivec,ovec+num,16); // 如果在nbits为8的整倍数的时候,如8时用ivec[1...15]|(Ek(ivec)[0]^ in [0]) 作为下一轮的ivec // 如nbits为16时用ivec[2...15]|(Ek(ivec)[0]^ in [0])|(Ek(ivec)[1]^ in [1]) 作为下一轮的ivec // 向量变化:ivec=ivec[num...15]| in [0...(num-1)]^(Ek(ivec))[0...(num-1)]; } else { // 可见 0<=num<=15 for (n=0 ; n < 16 ; ++n) { ivec[n] = ovec[n+num]<<rem | ovec[n+num+1]>>(8-rem); } // 如果nbits不为8的倍数,则需要将ivec[num]字节的右边低8-rem位直到ivec[16+num]的左边高rem位共计128位作为下一轮的ivec } /* it is not necessary to cleanse ovec, since the IV is not secret */ } /* N.B. This expects the input to be packed, MS bit first */ void CRYPTO_cfb128_1_encrypt(const unsigned char * in , unsigned char *out, size_t bits, const void *key, unsigned char ivec[16], int *num, int enc, block128_f block) { size_t n; unsigned char c[1],d[1]; assert( in && out && key && ivec && num); assert(*num == 0); for (n=0 ; n<bits ; ++n) { c[0]=( in [n /8 ]&(1 << (7-n%8))) ? 0x80 : 0; // in 的第n位为1 则 c[0]=0x80 否则 c[0]=0;即最高位为 in 的第n位的值,其他位为0. cfbr_encrypt_block(c,d,1,key,ivec,enc,block); out[n /8 ]=(out[n /8 ]&~(1 << (unsigned int)(7-n%8))) | ((d[0]&0x80) >> (unsigned int)(n%8)); // 设置out结果的第n位为d[0]最高位的值。 } } void CRYPTO_cfb128_8_encrypt(const unsigned char * in , unsigned char *out, size_t length, const void *key, unsigned char ivec[16], int *num, int enc, block128_f block) { size_t n; assert( in && out && key && ivec && num); assert(*num == 0); for (n=0 ; n<length ; ++n) cfbr_encrypt_block(& in [n],&out[n],8,key,ivec,enc,block); // 对于每次偏移位数为8时,为整字节运算,本函数的第3参数为字节数。 } |
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/NJZhuJinhua/archive/2010/06/06/5651871.aspx
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
赞赏
雪币:
留言: