DES加密注意的地方

最近在调研DES算法的时候,遇到了一个问题,最后终于发现……

Base64的加密与解密java代码

[code="java"]package com.secure.test;
import java.io.IOException;
import org.junit.Test;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class MyTest {

/**
* base64解密
* @param key
* @return
* @throws IOException
         */
public static byte[] decryptBase64(String key) throws IOException {
return (new BASE64Decoder()).decodeBuffer(key);
}

/**
         * base64加密
* @param key
* @return
*/
public static String encryptBase64(byte[] key){
return (new BASE64Encoder()).encodeBuffer(key);
       }
    }
}



  Des加密与解密的java代码

[code="java"]package com.secure.test;

import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.junit.Test;

public class DesTest {
public static final String ALGORITHM = "DES";

/**
* 转换密钥
* @param key 初始化一个密钥
* @return 密钥
* @throws Exception
*/
private static Key tokey(byte[] key) throws Exception{
DESKeySpec spec = new DESKeySpec(key);
SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey secretkey = factory.generateSecret(spec);
return secretkey;
}

/**
* 用于解密操作
* @param date 用于解密的数据
* @param key 约定的密钥
* @return 返回一个解密过后的byte数组
* @throws Exception
*/
public static byte[] decrypt(byte[] date,String key) throws Exception{
Key dKey = tokey(Base64Test.decryptBase64(key));
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, dKey);
return cipher.doFinal(date);
}

/**
* 用于加密操作
* @param date 用于加密操作的数据
* @param key 约定的密钥
* @return 返回一个加密过后的byte数组
* @throws Exception
*/
public static byte[] encrpty(byte[] date,String key) throws Exception{
Key dKey = tokey(Base64Test.decryptBase64(key));
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, dKey);
return cipher.doFinal(date);

}

/**
* 用于产生密钥
* @param seed
* @return
* @throws Exception
*/
public static String initKey(String seed) throws Exception{
SecureRandom random = null;
if(seed != null){
random = new SecureRandom(Base64Test.decryptBase64(seed));
}else{
random = new SecureRandom();
}

KeyGenerator generator = KeyGenerator.getInstance(ALGORITHM);
generator.init(random);
SecretKey secretKey = generator.generateKey();
return Base64Test.encryptBase64(secretKey.getEncoded());

}

/**
* 重载的方法
* @return
* @throws Exception
*/
public static String initKey() throws Exception{
return initKey(null);
}

}

然后这里有一个测试的方法

[code="java"]@Test
public void testTwo() throws Exception{
String text = "Test";
System.out.println("原始文字:"+text);
String secretKey = DesTest.initKey("DES").trim();
System.out.println("密钥为:"+secretKey);
byte[] sDate = DesTest.encrpty(text.getBytes(), secretKey);
String eStr = new String(sDate);
System.out.println("加密后:"+eStr);
byte[] dDate = eStr.getBytes();
byte[] cDate = DesTest.decrypt(dDate, secretKey);
String dStr = new String(cDate);
System.out.println("解密后:"+dStr);
}


测试之后报错

[code="java"]javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
at com.sun.crypto.provider.DESCipher.engineDoFinal(DashoA12275)
at javax.crypto.Cipher.doFinal(DashoA12275)
at com.secure.test.DesTest.decrypt(DesTest.java:40)
at com.secure.test.DesTest.testTwo(DesTest.java:110)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:592)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)



原因是因为

[code="java"]byte[] sDate = DesTest.encrpty(text.getBytes(), secretKey);
这是一个经过加密之后的byte数组,然后在经过

[code="java"]String eStr = new String(sDate);
byte[] dDate = eStr.getBytes();
之后,其数组内容已经被改变了,所以存在问题。

你可能感兴趣的:(java,eclipse,JUnit,Security,sun)