关于DES算法的一些入门
来源:互联网 发布:java url decode函数 编辑:程序博客网 时间:2024/05/20 00:35
对称密钥算法又分为两种:分组密码和流密码。分组密码将明文分割为若干个定长的数据块(称为一个分组),每次 对一个分组进行处理;流密码又称序列密码,依次对输入每个元素进行处理。
DES是对称秘钥算法,且是分组秘钥算法,它主要是经过一系列的置换变换和异或相加,
首先我得知道,DES的解密算法与加密算法完全相同,只需要将密钥的应用次序与加密时相反应用即可。即解密过程是初始置换函数IP接受长度为64比特的密文输入,将16个子密钥按照K16到K1的顺序应用与函数F的16轮迭代运算中,然后将迭代的结果经由末置换函数IP-1得到64位的明文输出。
主要可以分为下面四个步骤:
1.初始置换函数 IP(InitDataValue)
private int[] InitDataValue(int[] data){int[] dataValue = new int[64];for(int i=0;i<64;i++){dataValue[i] = data[ DATA_IP[i] - 1 ];}return dataValue;} private static final int[] DATA_IP = {58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7};//64
2.子秘钥Ki的获取。
//生成16个 子秘钥private void InitKeyValue(int[] key, int[][] keyArray){int[] keyTemp = new int[56];for(int i=0;i<56;i++){keyTemp[i] = key[ KEY_PC_1[i] - 1];}//生成16个子秘钥for(int i=0; i<16; i++){// 左移秘钥是 56 位的LEFT_MOVE( keyTemp, MOVE_LEFT[i] );for(int j=0; j<48; j++){keyArray[i][j] = keyTemp[ KEY_PC_2[j] - 1 ];}}}// 秘钥左移函数private void LEFT_MOVE(int[] key, int offset){int[] keyLeft = new int[28];int[] keyRight = new int[28];int[] keyLeftTemp = new int[28];int[] keyRightTemp = new int[28]; for(int i=0; i<28; i++){keyLeft[i] = key[i];keyRight[i] = key[i+28];}if(offset == 1){for(int i=0;i<27;i++){keyLeftTemp[i] = keyLeft[ i+1 ];keyRightTemp[i] = keyRight[ i+1 ];}keyLeftTemp[27] = keyLeft[0];keyRightTemp[27] = keyRight[0];}else if(offset == 2){for(int i=0;i<26;i++){keyLeftTemp[i] = keyLeft[ i+2 ];keyRightTemp[i] = keyRight[ i+2 ];}keyLeftTemp[26] = keyLeft[0];keyRightTemp[26] = keyRight[0];keyLeftTemp[27] = keyLeft[1];keyRightTemp[27] = keyRight[1];}// 重新组织 key 数组for (int i=0; i<28; i++) { key[i] = keyLeftTemp[i]; key[i+28] = keyRightTemp[i]; }}
3.加密解密函数(这个最重要)
// 秘钥函数F, 接受32位 数据和48位秘钥的输入 , 包含S盒运算的整个过程private void loopF(int[] dataValue, int times, int flag, int[][] keyArray){int[] leftData = new int[32];int[] rightData = new int[32];int[] leftDataTemp = new int[32];int[] rightDataTemp = new int[32];int[] temp = new int[48];//作为 中转的 48位数组存放过程int[] sBoxData = new int[8];int[] SValue = new int[32];int[][] SboxTemp = new int[8][6];int[] S_PValue = new int[32];for(int i=0;i<32;i++){leftData[i] = dataValue[i];rightData[i] = dataValue[ i+32 ];}for(int i=0; i<48; i++){//temp[i] = dataValue[ E[i] - 1 ];temp[i] = rightData[ E[i] - 1 ];//将上面的结果 同 48位秘钥Ki 做异或运算temp[i] = temp[i] + keyArray[times][i];if(temp[i] == 2)temp[i] = 0;}//分组成8份for(int i=0; i<8; i++){for(int j=0; j<6; j++){SboxTemp[i][j] = temp[ (i*6) + j ];}//做S盒变换sBoxData[i] = S_BOX[i][ (SboxTemp[i][0]<<1) + SboxTemp[i][5] ]//取第一位和第六位组合成X[ (SboxTemp[i][1]<<3) + (SboxTemp[i][2]<<2) + (SboxTemp[i][3]<<1) +SboxTemp[i][4] ];//取第2-5位作为Y//换成二进制的 4位数for(int j=0; j<4; j++ ){SValue[((i * 4) + 3) - j] = sBoxData[i] % 2;sBoxData[i] = sBoxData[i] / 2;}}for(int i=0; i<32; i++){S_PValue[i] = SValue[ P[i] - 1 ];//存储经过P置换的值leftDataTemp[i] = rightData[i]; // 右边移到左边rightDataTemp[i] = leftData[i] + S_PValue[i];if( rightDataTemp[i] ==2 )rightDataTemp[i] = 0;//重新组合 密文if( ((flag == 0) && (times == 0)) || ((flag == 1) && (times == 15)) ){dataValue[i] = rightDataTemp[i];dataValue[i+32] = leftDataTemp[i]; }else{dataValue[i] = leftDataTemp[i];dataValue[i+32] = rightDataTemp[i];}}}4.末置换函数IP-1
private int[] FinalDataValue(int[] data){int[] dataValue = new int[64];for(int i=0;i<64;i++){dataValue[i] = data[ DATA_IP_1[i] - 1 ];}return dataValue;}
经过上面的算法,我们知道算法的输入和输出都是64bit的数据,一般我们的输入是 byte[ ]、String,这里就需要进行数据转换,笔者对这里有点不理解??加密之后,密文出现乱码。但是解密之后,又出现了正常明文~~囧。。。
还有一点就是数据处理的时候每次都是8bytes处理,并且当数据不是8bytes的时候需要补位。这里笔者还不知道怎么处理。。继续研究一下
明白了DES的原理之后,我们可以展望一下3DES算法。从Data和Key的输入,可以分为3DES和DES两种,也就是复杂度不同。
3DES加密过程为:C=Ek3(Dk2(Ek1(P))),3DES解密过程为:P=Dk1(EK2(Dk3(C)))。其中P为明文,C为密文,E()为加密函数,D()为解密函数。
下面贴出根据别人代码总结的代码:
public class DES {byte[] key;public DES(String key){this.key = key.getBytes();}// 加密数据 开始置换的数组private static final int[] DATA_IP = {58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7};//64// 加密数据 最后的置换数组private static final int[] DATA_IP_1 = {40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,38, 6, 46, 14, 54, 22, 62, 30,37, 5, 45, 13, 53, 21, 61, 29,36, 4, 44, 12, 52, 20, 60, 28,35, 3, 43, 11, 51, 19, 59, 27,34, 2, 42, 10, 50, 18, 58, 26,33, 1, 41, 9, 49, 17, 57, 25,};//64// 初始秘钥置换函数, 变成56位private static final int[] KEY_PC_1 = { 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4};//56//获得的秘钥 进行的压缩和置换, 生成16组子秘钥必须的函数private static final int[] KEY_PC_2 = { 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32};//48// 循环左移函数,用于生成16个子秘钥private static final int[] MOVE_LEFT = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};// E盒运算, 扩展函数, 用于扩展 Ri(秘钥的右半部分), 生成 16 个子秘钥 E(Ri)private static final int[] E = {32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1};// P盒运算 用于参加16个子秘钥的运算。private static final int[] P = {16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25};// S盒函数, 这个函数用于 组成 半边子秘钥 取 1和6位 为X 取2345为Y, 找到对应的值, 刚好8组private static final int[][][] S_BOX = {{// S_Box[1] OK { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 }, { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 }, { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 }, { 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 } }, { // S_Box[2] OK { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 }, { 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 }, { 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 }, { 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 } }, { // S_Box[3] OK { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 }, { 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 }, { 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 }, { 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 } }, { // S_Box[4] OK { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 }, { 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 }, { 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 }, { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } }, { // S_Box[5] OK { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 }, { 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 }, { 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 }, { 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 } }, { // S_Box[6] OK { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 }, { 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 }, { 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 }, { 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 } }, { // S_Box[7] OK { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 }, { 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 }, { 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 }, { 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 } }, { // S_Box[8] OK { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 }, { 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 }, { 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 }, { 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } } };/** 第一步,生成初始化 置换数据 数组 */private int[] InitDataValue(int[] data){int[] dataValue = new int[64];for(int i=0;i<64;i++){dataValue[i] = data[ DATA_IP[i] - 1 ];}return dataValue;} /** 第二步,生成子秘钥 *///生成16个 子秘钥private void InitKeyValue(int[] key, int[][] keyArray){int[] keyTemp = new int[56];for(int i=0;i<56;i++){keyTemp[i] = key[ KEY_PC_1[i] - 1];}//生成16个子秘钥for(int i=0; i<16; i++){// 左移秘钥是 56 位的LEFT_MOVE( keyTemp, MOVE_LEFT[i] );for(int j=0; j<48; j++){keyArray[i][j] = keyTemp[ KEY_PC_2[j] - 1 ];}}}// 秘钥左移函数private void LEFT_MOVE(int[] key, int offset){int[] keyLeft = new int[28];int[] keyRight = new int[28];int[] keyLeftTemp = new int[28];int[] keyRightTemp = new int[28]; for(int i=0; i<28; i++){keyLeft[i] = key[i];keyRight[i] = key[i+28];}if(offset == 1){for(int i=0;i<27;i++){keyLeftTemp[i] = keyLeft[ i+1 ];keyRightTemp[i] = keyRight[ i+1 ];}keyLeftTemp[27] = keyLeft[0];keyRightTemp[27] = keyRight[0];}else if(offset == 2){for(int i=0;i<26;i++){keyLeftTemp[i] = keyLeft[ i+2 ];keyRightTemp[i] = keyRight[ i+2 ];}keyLeftTemp[26] = keyLeft[0];keyRightTemp[26] = keyRight[0];keyLeftTemp[27] = keyLeft[1];keyRightTemp[27] = keyRight[1];}// 重新组织 key 数组for (int i=0; i<28; i++) { key[i] = keyLeftTemp[i]; key[i+28] = keyRightTemp[i]; }}/** 第三步,秘钥函数 F */// 秘钥函数F, 接受32位 数据和48位秘钥的输入 , 包含S盒运算的整个过程private void loopF(int[] dataValue, int times, int flag, int[][] keyArray){int[] leftData = new int[32];int[] rightData = new int[32];int[] leftDataTemp = new int[32];int[] rightDataTemp = new int[32];int[] temp = new int[48];//作为 中转的 48位数组存放过程int[] sBoxData = new int[8];int[] SValue = new int[32];int[][] SboxTemp = new int[8][6];int[] S_PValue = new int[32];for(int i=0;i<32;i++){leftData[i] = dataValue[i];rightData[i] = dataValue[ i+32 ];}for(int i=0; i<48; i++){//temp[i] = dataValue[ E[i] - 1 ];temp[i] = rightData[ E[i] - 1 ];//将上面的结果 同 48位秘钥Ki 做异或运算temp[i] = temp[i] + keyArray[times][i];if(temp[i] == 2)temp[i] = 0;}//分组成8份for(int i=0; i<8; i++){for(int j=0; j<6; j++){SboxTemp[i][j] = temp[ (i*6) + j ];}//做S盒变换sBoxData[i] = S_BOX[i][ (SboxTemp[i][0]<<1) + SboxTemp[i][5] ]//取第一位和第六位组合成X[ (SboxTemp[i][1]<<3) + (SboxTemp[i][2]<<2) + (SboxTemp[i][3]<<1) +SboxTemp[i][4] ];//取第2-5位作为Y//换成二进制的 4位数for(int j=0; j<4; j++ ){SValue[((i * 4) + 3) - j] = sBoxData[i] % 2;sBoxData[i] = sBoxData[i] / 2;}}for(int i=0; i<32; i++){S_PValue[i] = SValue[ P[i] - 1 ];//存储经过P置换的值leftDataTemp[i] = rightData[i]; // 右边移到左边rightDataTemp[i] = leftData[i] + S_PValue[i];if( rightDataTemp[i] ==2 )rightDataTemp[i] = 0;//重新组合 密文if( ((flag == 0) && (times == 0)) || ((flag == 1) && (times == 15)) ){dataValue[i] = rightDataTemp[i];dataValue[i+32] = leftDataTemp[i]; }else{dataValue[i] = leftDataTemp[i];dataValue[i+32] = rightDataTemp[i];}}}/** 第四步,最后置换函数 */private int[] FinalDataValue(int[] data){int[] dataValue = new int[64];for(int i=0;i<64;i++){dataValue[i] = data[ DATA_IP_1[i] - 1 ];}return dataValue;}/**执行 “加密-解密” 操作 * @param timeData (int[64])二进制加密数据 * @param flag 1或0,1为加密,0为解密 * @param keyarray new int[16][48] * @return 长度为8的字节数组 */private byte[] EncryptMain(int[] timeData, int flag, int[][] keyarray) { byte[] encrypt = new byte[8]; int flags = flag; int[] M = new int[64];//明文数组 int[] MIP_1 = new int[64]; M = InitDataValue(timeData);//初始化密文 IP if (flags == 1) { // 加密 for (int i=0; i < 16; i++) { loopF(M, i, flags, keyarray);//S盒处理 } } else if (flags == 0) { // 解密 for (int i = 15; i > -1; i--) { loopF(M, i, flags, keyarray);//S盒处理 } } MIP_1 = FinalDataValue(M);//处理 IP_1 //将(int[64]二进制数据字节数组,经过IP、S盒、IP-1处理后,得到的新的)int[64]二进制数据字节数组转换成byte[8]的字节数组 GetEncryptResultOfByteArray(MIP_1, encrypt); // 返回加密数据 return encrypt; }/**----------------------上面的是算法,下面的是输入的问题--------------------------*/ /**加密解密(主要方法) * @param des_key 密钥字节数组 * @param des_data 要处理的数据字节数组 * @param flag (1或0),1为加密,0为解密 * @return 处理后的数据 */ private byte[] DesEncrypt(byte[] des_key, byte[] des_data, int flag) { byte[] format_data = ByteDataFormat(des_data);//补齐原始数据字节数组的长度为8的倍数,不足元素用0补 byte[] format_key = ByteDataFormat(des_key);//补齐密钥字节数组的长度为8的倍数,不足元素用0补 int datalen = format_data.length;//补齐后的原始数据字节数组的长度 int unitcount = datalen / 8;//补齐后的原始数据字节数组长度是8的多少倍 byte[] result_data = new byte[datalen];//用于盛放加密后的结果 //每一次循环,都操作8个字节(加密解密) for (int i = 0; i < unitcount; i++) { byte[] tmpkey = new byte[8];//真正起作用的密钥字节数组,只有8个字节 byte[] tmpdata = new byte[8];//用于参与操作的数据字节数组,只有8个字节 System.arraycopy(format_key, i * 8, tmpkey, 0, 8); System.arraycopy(format_data, i * 8, tmpdata, 0, 8); byte[] tmpresult = UnitDes(tmpkey, tmpdata, flag);//执行操作 System.arraycopy(tmpresult, 0, result_data, i * 8, 8); } return result_data; } /** @param des_key 8个字节的密钥字节数组 * @param des_data 8个字节的数据字节数组 * @param flag 1或0,1为加密,0为解密 * @return 8个字节的字节数组 */ private byte[] UnitDes(byte[] des_key, byte[] des_data, int flag) { // 检测输入参数格式是否正确,错误直接返回空值(null) if ((des_key.length != 8) || (des_data.length != 8) || ((flag != 1) && (flag != 0))) { throw new RuntimeException("Data Format Error !"); } int flags = flag; int[] keyData = new int[64]; // 二进制加密密钥 int[] encryptdata = new int[64]; // 二进制加密数据 byte[] EncryptCode = new byte[8]; // 加密操作完成后的字节数组 int[][] KeyArray = new int[16][48]; // 密钥初试化成二维数组 // 将密钥字节数组转换成二进制字节数组 keyData = ReadDataToBirnaryIntArray(des_key); // 将加密数据字节数组转换成二进制字节数组 encryptdata = ReadDataToBirnaryIntArray(des_data); // 初试化密钥为二维密钥数组 (3个子秘钥全部都初始化了) InitKeyValue(keyData, KeyArray);// 执行加密解密操作 EncryptCode = EncryptMain(encryptdata, flags, KeyArray); return EncryptCode; } /** DES加密 * @param data 原始数据(长度不能超过9999位) * @return 加密后的数据字节数组 */ public byte[] encrypt(String data){//先不考虑填充问题 byte[] bytekey = key; byte[] bytedata = data.getBytes(); byte[] result = new byte[data.length()]; result = DesEncrypt(bytekey, bytedata, 1); return result; } /** DES解密 * @param encryptData 加密后的数据字节数组 * @return 还原后的数据字符串 */ public byte[] decrypt(byte[] encryptData){ byte[] bytekey = key; //这里还得注意一下填充问题,先不考虑填充问题 byte[] result = new byte[encryptData.length]; result = DesEncrypt(bytekey, encryptData, 0);//解密处理 return result; } /** * 格式化字节数组,使其的长度为8的倍数,那些不足的部分元素用0填充 * @return 一个新的字节数组,其长度比原数组长1-8位(在byte的情况增加了7位,好像并没有表现出来) */ private byte[] ByteDataFormat(byte[] data) { int len = data.length; int newlen; int padlen = 8 - (len % 8);//要格式化的字节数组的长度与8的倍数的差值 if(padlen !=8 ){ newlen = len + padlen; }else{ newlen = len; } byte[] newdata = new byte[newlen]; System.arraycopy(data, 0, newdata, 0, len); for (int i = len; i < newlen; i++) newdata[i] = 0; return newdata; } /** 转换8个字节长度的数据字节数组为二进制数组 * (一个字节转换为8个二进制) * @param intdata 8个字节的数据字节数组 * @return 长度为64的二进制数组 */ private int[] ReadDataToBirnaryIntArray(byte[] intdata) { int i; int j; // 将数据转换为二进制数,存储到数组(这里我真是觉得很蛋疼啊??~~直接变成了16位) int[] IntDa = new int[8]; for (i = 0; i < 8; i++) { IntDa[i] = intdata[i];//intdata[i]为byte,范围是-128~127 if (IntDa[i] < 0) {//故:IntDa[i]范围是-128~127 IntDa[i] += 256;//IntDa[i]永远不会超过256 IntDa[i] %= 256;//所以该处不需要取模,取模后结果还是自己 } } int[] IntVa = new int[64]; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { IntVa[((i * 8) + 7) - j] = IntDa[i] % 2; IntDa[i] = IntDa[i] / 2; } } return IntVa; } /**int[64]二进制数据字节数组转换成byte[8]的字节数组 * @param data int[64]二进制数据字节数组 * @param value byte[8] byte[8]的字节数组 */ private void GetEncryptResultOfByteArray(int[] data, byte[] value) { int i; int j; // 将存储64位二进制数据的数组中的数据转换为八个整数(byte) for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { value[i] += (byte)(data[(i << 3) + j] << (7 - j)); } } for (i = 0; i < 8; i++) { value[i] %= 256; if (value[i] > 128) { value[i] -= 255; } } }}
0 0
- 关于DES算法的一些入门
- 【0】密码学关于des算法的了解
- 关于3DES算法
- 关于3DES算法
- openssl关于des算法
- DES的一些笔记
- 求助!关于DES的
- 关于DES的若干问题:
- 关于DES 的 问题
- DES算法的实现
- Des算法的实现
- DES 算法的使用
- DES 算法的使用
- DES算法的实现
- C#一些常用机密算法DES
- 关于算法的一些想法
- 关于算法的一些想法
- 关于算法的一些想法
- poj2499
- dede列表命名规则
- 整理项目中用到的javascript全局规则
- 获取文件的MD5码
- Scrollbarstyle属性的设置对scrollbar位置的影响
- 关于DES算法的一些入门
- vs2010编译c++程序出现的错误(LINK fatal error LNK1123)
- HDU 1253 胜利大逃亡 三维BFS
- UVa-673-Parentheses Balance
- 面试逻辑思维 参考答案(二)
- LeetCode | Triangle(三角形路径和)
- Windows消息机制
- Map和EntrySet、keySet的迭代效率
- brctl配置linux bridge及虚拟bridge实现