使用AES+Base64加密方式加密、解密以及异常的解决

import java.security.Key;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;


/**
 * @author
 * 加密/解密 公共类
 */
@SuppressWarnings("restriction")
public class DESUtils 

    private static Key key; 
    private static String KEY_STR="mykey"; 
   
    static{ 

// 在之前的linux服务器上这样使用没有问题,但同事往新的linux服务器上部署时出现以下异常:

// java.lang.RuntimeException: javax.crypto.BadPaddingException: Invalid pad value!

// 原因分析:

 

/* SecureRandom 实现完全随操作系统本身的內部状态,除非调用方在调用 getInstance 方法之后又调用 了 setSeed 方法;该实现在 windows 上每次生成的 key 都相同,但是在 solaris 或部分 linux 系统上则不同。
*/

//        try 
//        { 
//            KeyGenerator generator = KeyGenerator.getInstance("DES"); 
//            SecureRandom secureRandom=SecureRandom.getInstance("SHA1PRNG"); 
//            secureRandom.setSeed(KEY_STR.getBytes()); 
//            generator.init(secureRandom); 
//            key = generator.generateKey(); 
//            generator=null; 
//        } 
//        catch (Exception e) 
//        { 
//            throw new RuntimeException(e); 
//        }

 

// 改成这样后,就解决了!
        try {
            KeyGenerator generator=KeyGenerator.getInstance("AES");
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(KEY_STR.getBytes());
            generator.init(128,secureRandom);
            key = generator.generateKey();
            generator=null;
          }  catch (Exception e) {
              throw new RuntimeException("初始化密钥出现异常");
          }
       
    } 
     
    /**
     * 对字符串进行加密,返回BASE64的加密字符串
     * <功能详细描述>
     * @param str
     * @return
     * @see [类、类#方法、类#成员]
     */ 
    public static String getEncryptString(String str){ 
        BASE64Encoder base64Encoder = new BASE64Encoder(); 
        System.out.println(key); 
        try 
        { 
            byte[] strBytes = str.getBytes("UTF-8"); 
            Cipher cipher = Cipher.getInstance("AES"); 
            cipher.init(Cipher.ENCRYPT_MODE, key); 
            byte[] encryptStrBytes = cipher.doFinal(strBytes); 
            return base64Encoder.encode(encryptStrBytes); 
        } 
        catch (Exception e) 
        { 
            throw new RuntimeException(e); 
        } 
         
    } 
     
    /**
     * 对BASE64加密字符串进行解密
     * <功能详细描述>
     * @param str
     * @return
     * @see [类、类#方法、类#成员]
     */ 
    public static String getDecryptString(String str){ 
        BASE64Decoder base64Decoder = new BASE64Decoder(); 
        try 
        { 
            byte[] strBytes = base64Decoder.decodeBuffer(str); 
            Cipher cipher = Cipher.getInstance("AES"); 
            cipher.init(Cipher.DECRYPT_MODE, key); 
            byte[] encryptStrBytes = cipher.doFinal(strBytes); 
            return new String(encryptStrBytes,"UTF-8"); 
        } 
        catch (Exception e) 
        { 
            throw new RuntimeException(e); 
        } 
         
    } 
     
    //main测试
//    public static void main(String[] args) 
//    { 
//        String name ="admin"; 
//        String password="123456"; 

//        String encryname = getEncryptString(name); 
//        String encrypassword = getEncryptString(password); 
//        System.out.println("用户名加密后:"+encryname); 
//        System.out.println("密码加密后:"+encrypassword); 
//         
//        System.out.println("用户名解密后:"+getDecryptString(encryname)); 
//        System.out.println("密码解密后:"+getDecryptString(encrypassword)); 
//    } 
}

 

===================================================================================

 

import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

/**
 * @author
 * 扩展PropertyPlaceholderConfigurer将prop文件中加密后的属性解密后递交给Spring
 */
public class EncryptPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer 

    //encryptPropNames存储需要解密的属性
    private String[] encryptPropNames = {"jdbc.username", "jdbc.password"}; 
     
    /*
     *重写convertProperty,对已有加密特征的属性进行解密
     */
    @Override 
    protected String convertProperty(String propertyName, String propertyValue) 
    { 
         
        //如果在加密属性名单中发现该属性 
        if (isEncryptProp(propertyName)) 
        { 
            String decryptValue = DESUtils.getDecryptString(propertyValue); 
            return decryptValue; 
        }else {
            return propertyValue; 
        } 
         
    } 
     
    /**
     * 判断属性值是否加密
     * @param propertyName
     * @return
     */
    private boolean isEncryptProp(String propertyName) 
    { 
        for (String encryptName : encryptPropNames) 
        { 
            if (encryptName.equals(propertyName)) 
            { 
                return true; 
            } 
        } 
        return false; 
    } 
}

 

 

===================================================================================

在spring.xml文件中增加如下配置:


       
           
                classpath:jdbc.properties
           

       

 

你可能感兴趣的:(java)