风也温柔

计算机科学知识库

java aes加密解密算法 密码学加密算法——DES实现与验证(Java)

  DES全称为Data ,为密码体制中的对称密码体制,所谓对称加密就是加密和解密的过程使用相同的算法,是加密中最弱的算法,但是性能最好。

  概述:

  DES采用分组加密方法,以64位为一个最小分组对数据加密(明文8个字节为一个分组,每字节8位(bit)),每 组单独加密处理。

  密钥长64位,但密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是校验位,使得每个密钥都有奇数个1),分组后的明文组和56位的密钥按位替代或交换的方法形成密文组。

  密文长度和明文长度相同,为64位,DES的加密和解密算法相同,但解密子密钥与加密子密钥的使用顺序刚好相反。

  算法步骤

  本部分参考《物联网信息安全》第一版,桂小林版

  算法主要分为三步,流程图先给出

  java aes解密_java aes加密解密算法_java aes解密 偏移值

  第一步:

  对输入的64位的明文分组进行固定的“初始置换”( ,IP),即按固定的规则(后文解释)重新排列明文分组的64位二进制数据,再将重排后的64位数据前后32位分为独立64位明文的左右两个部分,前32位记为L0,后32位记为R0。

  第二步:

  进行16轮相同函数的迭代处理。将上一轮输出的Ri-1(注:i=1.....15)直接作为Li输入,同时将Ri-1与第i个48位的子密钥Ki经“轮函数f”转换后,得到一个32位的中间结果,再将此中间结果与上一轮的Li-1做异或运算,并将得到的新的32位结果作为下一轮的Ri。如此往复,迭代处理16次。每次的子密钥不同,16个子密钥的生成与轮函数在后面单独阐述。(是交换两个半分组java aes加密解密算法 密码学加密算法——DES实现与验证(Java),一轮运算的左半分组输入是上一轮的右半分组的输出)

  第三步:

  将第16轮迭代结果左右两半组L16、R16直接合并为64位 (L16,R16), 输入到初始逆置换来消除初始置换的影响。这一步的输出结果即为加密过程的密文。

  初始置换

  置换表中的数字为1~64,意为输入的64位二进制明文或密文数据从左至右的位置序号。置换表中的数字位置即为置换后java aes加密解密算法,数字对应的原位置数据在输出的64位序列中新的位置序号。比如表中第一个数字58,58表示输入64位明文或密文二进制数据的第58位;而58位于表中第一位,则表示将原二进制数的第58位置换到输出的第1位。

  轮函数

  工作流程如下,主要为4步

  java aes解密 偏移值_java aes解密_java aes加密解密算法

  第一步:扩展E变换( box,E盒),即将输入的32位数据扩展为48位。其扩展E变换如表3-3所示,表中元素的意义与初始置换表基本相同,按行顺序,从左至右共48位。比如第一个元素为32,表示48位输出结果的第一位数据为原输入32位数据中的第32位上的数据。

  第二步:将第一步输出结果的48位二进制数据与48位子密钥K按位做异或运算,结果自然为48位。然后将运算结果的48位二进制数据自左到右以6位为一组,共分8组。

  第三步:将8组6位二进制数据分别进入8个不同的S盒,每个S盒输入6位二进制数据,输出4位二进制数据(S盒相对复杂,后面单独阐述),然后再将8个S盒输出的8组4位数据,依次连接.重新合并为32位数据。

  第四步:将上一步合并生成的32位数据,经p盒( box)置换,输出新的32数据。

  按行的顺序从左到右java aes加密解密算法,表中第i个位置对应的数据j表示为输出的第i位为输入的第j位数据。P 盒输出的32位数据即为轮函数的最终输出结果。

  S盒

  S盒( box)是DES的核心部分。通过S盒定义的非线性替换,DES实现了明文消息在密文消息空间上的随机非线性分布。S盒的非线性替换特征意味着,给定一组输入输出值,很难预计所有S盒的输出。共有8种不同的S盒,每个S盒将接收6位输入数据,通过定义的非线性映射变换为4位输出。一个S盒有一个16列4行数表,它的每个元素是一个4位二进制数,通常表示成十进制数0~15。

  S盒的替代运算规则:设输入6位二进制数据为,则以b1b6饥足组成的二进制数为行号,组成的二进制数为列号,取出S盒中行列交点处的数,并转换成二进制输出。由于表中十进制数的范围是0~15,以二进制表示正好4位。下面以6 位输入数据经 Si盒变换为例进行说明。

  DES子密钥

  DES加密过程中需要16个48位的子密钥。子密钥由用户提供64位密钥 ,经16轮迭代运算依次生成。DES子密钥生成算法如图3所示,主要可分为如下三个阶段。

  java aes解密 偏移值_java aes解密_java aes加密解密算法

  第一阶段:用户提供8个字符密钥,转换成ASCII码的64位,经置换选择1(如表所示),去除8个奇偶校验位,并重新排列各位,置换选择1如表3-6所示,表中各位置上的元素意义与前面置换相同。由表可知,8、16、24、32、40、48、56、64位舍去了,重新组合后得56位。由于舍去规则是固定的,因而实际使用的初始密钥只有56位。

  第二阶段:将上一步置换选择后生成的56位密钥,分成左右两部分,前28位记为C0,后28位记为D0。然后分别将28位的C0,D0循环左移位一次,移位后分别得到的G、D,作为下一轮子密钥生成的位输入。每轮迭代循环左移位的次数遵循固定的规则,每轮左移次数如表所示。

  第三阶段:将C、D合并得到56位数据(C1,D1),经表中的置换选择2,也就是经固定的规则,置换选出重新排列的48位二进制数据,即为子密钥化K1。

  将C1,D1作下一轮的输入,采用前面相同的二、三两个阶段进行迭代,即可得到K2,依此类推,经过16轮迭代即可生成16个48位的子密钥。

  实现代码

  由于DES加密常用于网络传输,所以用JAVA来实现,有很多封装好的包,只需要就行。

  DES算法有三个入口参数:明文、密钥、模式(加密or解密)

  先定义一个类

  <pre>import FileOperate.FileOperate;
import ParseSystemUtil.ParseSystemUtil;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
final class DESEncryptTools {
<p>java aes解密_java aes解密 偏移值_java aes加密解密算法

//加密算是是[des][9]
private static final String ALGORITHM = "DES";
//转换格式
private static final String TRANSFORMATION = "DES/ECB/PKCS5Padding";
/* DES在实际应用中有多种模式(ECB、CBC、CBR等)和填充方式(PKCS5Padding、NoPadding、ZeroPadding)
   此处以最为广泛使用的ECB模式、PKCS5填充举例
*/
//利用8个字节64位的key给src加密
@SuppressWarnings("unused")
public static byte[] encrypt(byte[] src, byte[] key) {//加密函数
    try {
        //加密
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        KeySpec keySpec = new DESKeySpec(key);
        SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new SecureRandom());
        byte[] enMsgBytes = cipher.doFinal(src);
        return enMsgBytes;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
//利用8个字节64位的key给src解密
@SuppressWarnings("unused")
public static byte[] decrypt(byte[] encryptBytes, byte[] key) {//解密函数
    try {
        //解密
        //Cipher deCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        Cipher deCipher = Cipher.getInstance(TRANSFORMATION);
        SecretKeyFactory deDecretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        KeySpec deKeySpec = new DESKeySpec(key);
        SecretKey deSecretKey = deDecretKeyFactory.generateSecret(deKeySpec);
        deCipher.init(Cipher.DECRYPT_MODE, deSecretKey, new SecureRandom());
        byte[] deMsgBytes = deCipher.doFinal(encryptBytes);
        return deMsgBytes;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

}
再定义一个测试函数blic class DesMainTest {

private static String key = "12345678";//密钥

public static void main(String[] args) throws Exception {
    System.out.println("DES密钥算法测试:");
    String msg = null;
    try {
        msg = FileOperate.fileRead("D:\\IDEA_java\\src\\DES\\test.txt");
        System.out.println("文件读取成功,明文为:" + msg);
        System.out.println("明文长度:" + msg.getBytes().length * 8+"bit");
        System.out.println("密钥长度:" + key.getBytes().length * 8+"bit");
    } catch (Exception e) {
        System.out.println(e.getMessage().toString());

  java aes解密_java aes加密解密算法_java aes解密 偏移值

    }
    long startTime = System.nanoTime();
    byte[] encryptBytes = DESEncryptTools.encrypt(msg.getBytes(), key.getBytes());
    String hexStrResult = ParseSystemUtil.parseByte2HexStr(encryptBytes);
    System.out.println("加密后的16进制密文为:" + hexStrResult);
   // 此处密文长度计算不可用String类型的hexStrResult求长度,必须用Byte[]型的encryptBytes
    System.out.println("密文长度:" + returnActualLength(encryptBytes) * 8+"bit");
    long endTime = System.nanoTime();
    System.out.println("加密耗时:" + (endTime - startTime) + "ns");
    try {
        FileOperate.fileWrite("D:\\IDEA_java\\src\\DES\\密文.txt", new String(encryptBytes));
    } catch (Exception e) {
        System.out.println(e.getMessage().toString());
    }
    startTime = System.nanoTime();
    byte[] deMsgBytes = DESEncryptTools.decrypt(encryptBytes, key.getBytes());
    System.out.println("解密后的明文为:" + new String(deMsgBytes));
    endTime = System.nanoTime();
    System.out.println("明文长度:" + returnActualLength(deMsgBytes) * 8+"bit");
    System.out.println("解密耗时:" + (endTime - startTime) + "ns");
    try {
        FileOperate.fileWrite("D:\\IDEA_java\\src\\DES\\明文.txt", new String(deMsgBytes));
    } catch (Exception e) {
        System.out.println(e.getMessage().toString());
    }
}
public static int returnActualLength(byte[] data) {//计算Byte[]到底占用几个字节
    int i = 0;
    for (; i = 201103L

include

include

include

include

include

include

include

include

include

endif

// C++

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

  java aes加密解密算法_java aes解密 偏移值_java aes解密

include

include

include

include

if __cplusplus >= 201103L

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

endif

bool key[66], C[29], D[29];
int k(0);
int table1[56] = { 57,49,41,33,25,17,9,1 //置换选择表1,用于从64位初始密钥中选择56位

            ,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 };

int table2[48] = { 14,17,11,24,1,5, //置换选择表2,将得到的56位进行置换选择2,得到真正的圈密钥

            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 };

int dis[16] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 };//C寄存器和D寄存器循环左移的位数
void to_binary(int n) //将10进制数转换为4位2进制数
{

int K = k + 3;
while (n)
{
    key[K--] = n % 2;
    n /= 2;
}
while (k