位和字节的重排在密码学算法中有广泛的应用。 /* rearran.c:位和字节的重排 */ /* 位反转:以字的中心为对称点进行位反射 例如: abcd efgh ijkl mnop ABCD EFGH IJKL MNOP 位反转:PONM LKJI HGFE DCBA ponm lkji hgfe dcba */ unsigned rev(unsigned x){ /* 交换相邻的单个位 */ x=(x & 0x55555555)<<1 | (x & 0xaaaaaaaa)>>1; /* 交换相邻的2位字段 */ x=(x & 0x33333333)<<2 | (x & 0xcccccccc)>>2; /* 交换相邻的4位字段 */ x=(x & 0x0f0f0f0f)<<4 | (x & 0xf0f0f0f0)>>4; /* 交换相邻的8位字段 */ x=(x & 0x00ff00ff)<<8 | (x & 0xff00ff00)>>8; /* 交换相邻的16位字段 */ x=(x & 0x0000ffff)<<16 | (x & 0xffff0000)>>16; return x; } /* 字节反转:以字的中心为对称点进行字节反射 例如: abcd efgh ijkl mnop ABCD EFGH IJKL MNOP 字节反转:IJKL MNOP ABCD EFGH ijkl mnop abcd efgh */ unsigned revw(unsigned x){ x=(x & 0x00ff00ff)<<8 | (x & 0xff00ff00)>>8; x=(x & 0x0000ffff)<<16 | (x & 0xffff0000)>>16; return x; } /* 位混洗:将右半字的各个位相间地插入到左半字中,尾部的位仍然保留在尾部 例如:abcd efgh ijkl mnop ABCD EFGH IJKL MNOP 混洗:aAbB cCdD eEfF gGhH iIjJ kKlL mMnN oOpP */ unsigned shuffling(unsigned x){ unsigned t; /* 初始:abcd efgh ijkl mnop ABCD EFGH IJKL MNOP */ /* abcd efgh ABCD EFGH ijkl mnop IJKL MNOP */ t=(x ^ (x>>8)) & 0x0000ff00; x=x ^ t ^ (t<<8); /* abcd ABCD efgh EFGH ijkl IJKL mnop MNOP */ t=(x ^ (x>>4)) & 0x00f000f0; x=x ^ t ^ (t<<4); /* abAB cdCD efEf ghGH ijIJ klKL mnMN opOP */ t=(x ^ (x>>2)) & 0x0c0c0c0c; x=x ^ t ^ (t<<2); /* aAbB cCdD eEfF gGhH iIjJ kKlL mMnN oOpP */ t=(x ^ (x>>1)) & 0x22222222; x=x ^ t ^ (t<<1); return x; } /* 逆混洗 */ unsigned unshuffling(unsigned x){ /* 以相反的顺序进行交换即可实现逆混洗 */ t=(x ^ (x>>1)) & 0x22222222; x=x ^ t ^ (t<<1); t=(x ^ (x>>2)) & 0x0c0c0c0c; x=x ^ t ^ (t<<2); t=(x ^ (x>>4)) & 0x00f000f0; x=x ^ t ^ (t<<4); t=(x ^ (x>>8)) & 0x0000ff00; x=x ^ t ^ (t<<8); } /* 位矩阵转置:转置8*8位的矩阵,注意算法以“左上-右下”对角线为基准进行转置 (1) 看作16个2*2位矩阵:转置这些2*2位矩阵; (2) 看作4个2*2子矩阵:子矩阵的元素是2*2位矩阵,转置这些2*2子矩阵; (3) 看作1个2*2子矩阵:子矩阵的元素是4*4位矩阵,转置这个2*2子矩阵。 0 1 2 3 4 5 6 7 0 8 2 a 4 c 6 e 0 8 g o 4 c k s 0 8 g o w E M U 8 9 a b c d e f 1 9 3 b 5 d 7 f 1 9 h p 5 d l t 1 9 h p x F N V g h i j k l m n g o i q k s m u 2 a i q 6 e m u 2 a i q y G O W o p q r s t u v (1) h p j r l t n v (2) 3 b j r 7 f n v (3) 3 b j r z H P X w x y z A B C D ===> w E y G A I C K ===> w E M U A I Q Y ===> 4 c k s A I Q Y E F G H I J K L x F Z H B J D L x F N V B J R Z 5 d l t B J R Z M N O P Q R S T M U O W Q Y S $ Y G O W C K S $ 6 e m u C K S $ U V W X Y Z $ . N V P X R Z T . z H P X D L T . 7 f n v D L T . 参数A是8m*8n位源矩阵中的8*8子矩阵的第一个字节的地址,B是8n*8m位目标矩阵中的8*8子矩阵的 第一个字节的地址。整个源矩阵是8m*n字节,目标矩阵是8n*m字节 */ void transpose8(unsigned char A[8], int m, int n, unsigned char B[8]){ unsigned x,y,t; /* 载入数组,并把它装入到x和y中 */ x=(A[0]<<24) | (A[m]<<16) | (A[2*m]<<8) | A[3*m]; y=(A[4*m]<<24) | (A[5*m]<<16) | (A[6*m]<<8) | A[7*m]; /* 交换字中(从右编号)第1位和第8位、第3位和第10位、第5位和第12位,以此类推; 而不移动第0位、第2位、第4位,以此类推。 例如: 01234567 89abcdef ghijklmn opqrstuv 交换后:082a4c6e 193b5d7f goiqksmu hpjrltnv */ t=(x ^ (x>>7) & 0x00aa00aa; x=x ^ t ^ (t<<7); t=(y ^ (y>>7) & 0x00aa00aa; y=y ^ t ^ (t<<7); t=(x ^ (x>>14) & 0x0000cccc; x=x ^ t ^ (t<<14); t=(x ^ (y>>14) & 0x0000cccc; y=y ^ t ^ (t<<14); t=(x & 0xf0f0f0f0) | ((y>>4) & 0x0f0f0f0f); y=((x<<4) & 0xf0f0f0f0) | (y & 0x0f0f0f0f); x=t; B[0]=x>>24; B[n]=x>>16; B[2*n]=x>>8; B[3*n]=x; B[4*n]=y>>24; B[5*n]=y>>16; B[6*n]=y>>8; B[7*n]=y; } /* 转置32*32位矩阵 */ void transpose32(unsigned A[32]){ int j,k; unsigned m,t; m=0x0000ffff; for(j=16; j!=0; j=j>>1, m=m^(m<<j)){ for(k=0; k<32; k=(k+j+1) & ~j){ t=(A[k] ^ (A[k+j]>>j)) & m; A[k]=A[k] ^ t; A[k+j]=A[k+j] ^ (t<<j); } } } /* 位压缩:根据一个掩码m对字x进行压缩,即将x中所有与m中的1位对应的位移动到右端, 从而压缩成一个新字,例如 给定字: abcd efgh ijkl mnop qrst uvwx yzAB CDEF 掩码: 0000 1111 0011 0011 1010 1010 0101 0101 压缩后: 0000 0000 0000 0000 efgh klop qsuw zBDF */ unsigned compress(unsigned x,unsigned m){ unsigned r,s,b; /* 结果、移动位数、掩码位 */ r=0; s=0; do{ b=m & 1; /* 获取m的当前位 */ /* b为1时x的相应位就要放入r中,b为0时x的相应位不放入r中 */ r=r | ((x & b)<<s); s=s+b; x=x>>1; m=m>>1; }while(x!=0); return r; }