DES加密与解密

 

 

             随着互联网的发展,信息安全的重要性日益突出,我们需要各种各样的方法对我们的信息进行加密,DES就是大量用于社会中的一种加密和解密方法。

DES (Data Entryption Standard) 对称密码算法(也就是加密密钥和解密密钥相同的加密算法 )可以用于明文的加密和解密 ,DES这种安全性还算可以加密算法多用于民间,以前常用于 ATM机等,应用非常广泛。

是以64bit为一个小组来处理所要加密的明文(好多用于加密的算法都是以小分组的方式处理数据 的,如MD5是512bit为一个大分组 。用它进行数据加密大体上分为4个步骤:

1: 初始置换

2:子 密钥Ki的获取。           

3:密码函数F

4:末置换函数IP-1。(是IP的逆置换

上面的方法涉中相应的置换均有相应的对照表可以实现,涉及到一些离散数学的知识,如果大家有兴趣搞懂它的话, 具体的方法详可以参考度娘百科,讲的很

java一个显著的好处就是将我们要用到的一些功能封装起来,DES加密就可以可以通过我们KeyGenerator、Cipher等类来实现。

 

/**
	 * 根据用户所提供的密钥转换为符合DES加密要求的密钥
	 * @param str
	 */
	public void createKey(String str){
		try {
			KeyGenerator generator = KeyGenerator.getInstance("DES");
			//SecureRandom可以提供安全的随机数(平时我们用的随机数是伪随机数)
			generator.init(new SecureRandom(str.getBytes()));
			key = generator.generateKey();//得到符合要求的密钥
		} catch (NoSuchAlgorithmException e) {//如果没有用户所指定的算法抛出异常
			e.printStackTrace();
		}
	}

我们平时用的随机数是有一个周期的可预测的伪随机数发生器产生的,既然可以预测就是不安全的,所以这里要用SecureRamdom来产生随机数。

/**
	 * 加密明文得到密文
	 * @param str
	 * @return 密文
	 */
	public String desEncrypt(String str){
		Cipher cipher;
		try {
			cipher = Cipher.getInstance("DES");
			//用所得到的key初始化这个cipher
			cipher.init(Cipher.ENCRYPT_MODE, key);
			return  bytetohex((cipher.doFinal(str.getBytes())));
		}
		catch(Exception e){
			e.printStackTrace();
		}
		finally{
			cipher = null;
		}
		return null;
	}
	/**
	 * 解密密文输出明文
	 * @param str
	 * @return 明文
	 */
	public String deDesEncrypt(String str){
		Cipher cipher;
		try{
		cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.DECRYPT_MODE, key);
		ciphertext_1 = new String((cipher.doFinal(hextobyte(str.getBytes()))));
		}
		catch(Exception e){
			e.printStackTrace();
		}
		finally {
			cipher = null;
		}
		return ciphertext_1;
	}
//主函数
	public static void main(String [] agrs){
		DesEncrypt_0 encrypt_0 = new DesEncrypt_0();
		encrypt_0.createKey("你好!!");
		ciphertext_0 = encrypt_0.desEncrypt("贫僧从东土大唐而来。。。");
		System.out.println("加密后的结果是:"ciphertext_0);
		ciphertext_1 = encrypt_0.deDesEncrypt(ciphertext_0);
		System.out.println("解密得到的明文是:"ciphertext_1);
	}

                      这样直接运行会报下面的错误,这是因为加密后的byte[]数组是不能随意转换为string类型,为什么在这种情况下byte[]和string是不可逆的。这个我暂时还没搞明白,我想这应该深入研究一下byte和string相互转化的机制 。。。希望有大神来指导一下。。。

 

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher( 输入长度必须是8的倍数时,解密密文) at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:750)
	at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
	at com.sun.crypto.provider.DESCipher.engineDoFinal(DESCipher.java:314)
	at javax.crypto.Cipher.doFinal(Cipher.java:2086)
	at Test.DesEncrypt_0.deDesEncrypt(DesEncrypt_0.java:62)
	at Test.DesEncrypt_0.main(DesEncrypt_0.java:78)

将二进制转化为16进制的输出的方法如下:因为我的32bit调用的这个Integer.toHexString()是用32bit存储数据的,所以一个一个byte型的数据和0xff进行了与运算后可以保证它前面的24bit的数据均为0(否则前面24bit会出一些数字干扰我们的结果 ),同时如果调用了toHexString()方法后返回的两个16进制的数字为0Y(Y代表0~E)那么返回的String会自动将0去掉,所以为了避免这种情况的发生,我们要在这里分情况补0.

/**
	 * 二进制转换为十六进制
	 * @param b
	 * @return
	 */
	public String bytetohex(byte [] b){
		String temp="";
		String string="";
		for(int i =0;i<b.length;i++){
			 string = Integer.toHexString(b[i]&0xff);
			 if (string.length() == 1)
				 temp = temp + "0" + string;
				else
					temp+= string;
		}
		return temp;
	}
/**
	 * 将十六进制的数字还原为byte
	 * @param b
	 * @return
	 */
	public byte[] hextobyte(byte[] b){
		byte [] bb = new byte [b.length/2];
		for(int i=0;i<b.length;i+=2){
			//将得到的byte分解为2个byte为一组的string
			String string = new String(b,i,2);
			bb[i/2] = (byte)Integer.parseInt(string,16);
		}
		return bb;
	}

最后我们的测试结果见下:

"加密结果是:"1ca4abf326613caf25e0a684d70cf2c1f233b275fa823aeb075440376a4324ac
"解密得到的明文是:"贫僧从东土大唐而来。。。

安全的,合理的利用他们才是关键。希望感兴趣的同学看完之给我提出一些意见,水平有限,欢迎指正。