ice world

          There is nothing too difficult if you put your heart into it.
          posts - 104, comments - 103, trackbacks - 0, articles - 0
          本工具類經過測試可用,之前寫的沒有使用CipherInputStream和CipherOutputStream,生成的加密文件與源文件大小不一致,加密時沒有問題,解密時總是拋出如下異常:
          Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
              at com
          .sun.crypto.provider.SunJCE_f.b(DashoA13*..)
              at com
          .sun.crypto.provider.SunJCE_f.b(DashoA13*..)
              at com
          .sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
              at javax
          .crypto.Cipher.doFinal(DashoA13*..)


          其中BASE64底層依賴庫沒有使用SUN的,而是下載的“javabase64-1.3.1.jar”

          DESUtils.java
          package demo.security;

          import java.io.File;
          import java.io.FileInputStream;
          import java.io.FileOutputStream;
          import java.io.InputStream;
          import java.io.OutputStream;
          import java.security.Key;
          import java.security.SecureRandom;

          import javax.crypto.Cipher;
          import javax.crypto.CipherInputStream;
          import javax.crypto.CipherOutputStream;
          import javax.crypto.KeyGenerator;
          import javax.crypto.SecretKey;
          import javax.crypto.SecretKeyFactory;
          import javax.crypto.spec.DESKeySpec;

          /**
           * <p>
           * DES加密解密工具包
           * </p>
           * 
           * 
          @author IceWee
           * @date 2012-5-19
           * 
          @version 1.0
           
          */

          public class DESUtils {
              
              
          private static final String ALGORITHM = "DES";
              
          private static final int CACHE_SIZE = 1024;

              
          /**
               * <p>
               * 生成隨機密鑰
               * </p>
               * 
               * 
          @return
               * 
          @throws Exception
               
          */

              
          public static String getSecretKey() throws Exception {
                  
          return getSecretKey(null);
              }

              
              
          /**
               * <p>
               * 生成密鑰
               * </p>
               * 
               * 
          @param seed 密鑰種子
               * 
          @return
               * 
          @throws Exception
               
          */

              
          public static String getSecretKey(String seed) throws Exception {
                  SecureRandom secureRandom;
                  
          if (seed != null && !"".equals(seed))
                      secureRandom 
          = new SecureRandom(seed.getBytes());
                  
          else
                      secureRandom 
          = new SecureRandom();
                  KeyGenerator keyGenerator 
          = KeyGenerator.getInstance(ALGORITHM);
                  keyGenerator.init(secureRandom);
                  SecretKey secretKey 
          = keyGenerator.generateKey();
                  
          return Base64Utils.encode(secretKey.getEncoded());
              }

              
              
          /**
               * <p>
               * 加密
               * </p>
               * 
               * 
          @param data
               * 
          @param key
               * 
          @return
               * 
          @throws Exception
               
          */

              
          public static byte[] encrypt(byte[] data, String key) throws Exception {
                  Key k 
          = toKey(Base64Utils.decode(key));
                  Cipher cipher 
          = Cipher.getInstance(ALGORITHM);
                  cipher.init(Cipher.ENCRYPT_MODE, k);
                  
          return cipher.doFinal(data);
              }

              
              
          /**
               * <p>
               * 文件加密
               * </p>
               * 
               * 
          @param key
               * 
          @param sourceFilePath
               * 
          @param destFilePath
               * 
          @throws Exception
               
          */

              
          public static void encryptFile(String key, String sourceFilePath, String destFilePath) throws Exception {
                  File sourceFile 
          = new File(sourceFilePath);
                  File destFile 
          = new File(destFilePath); 
                  
          if (sourceFile.exists() && sourceFile.isFile()) {
                      
          if (!destFile.getParentFile().exists()) {
                          destFile.getParentFile().mkdirs();
                      }

                      destFile.createNewFile();
                      InputStream in 
          = new FileInputStream(sourceFile);
                      OutputStream out 
          = new FileOutputStream(destFile);
                      Key k 
          = toKey(Base64Utils.decode(key));
                      Cipher cipher 
          = Cipher.getInstance(ALGORITHM);
                      cipher.init(Cipher.ENCRYPT_MODE, k);
                      CipherInputStream cin 
          = new CipherInputStream(in, cipher);
                      
          byte[] cache = new byte[CACHE_SIZE];
                      
          int nRead = 0;
                      
          while ((nRead = cin.read(cache)) != -1{
                          out.write(cache, 
          0, nRead);
                          out.flush();
                      }

                      out.close();
                      cin.close();
                      in.close();
                  }

              }

              
              
          /**
               * <p>
               * 解密
               * </p>
               * 
               * 
          @param data
               * 
          @param key
               * 
          @return
               * 
          @throws Exception
               
          */

              
          public static byte[] decrypt(byte[] data, String key) throws Exception {
                  Key k 
          = toKey(Base64Utils.decode(key));
                  Cipher cipher 
          = Cipher.getInstance(ALGORITHM);
                  cipher.init(Cipher.DECRYPT_MODE, k);
                  
          return cipher.doFinal(data);
              }

              
              
          /**
               * <p>
               * 文件解密
               * </p>
               * 
               * 
          @param key
               * 
          @param sourceFilePath
               * 
          @param destFilePath
               * 
          @throws Exception
               
          */

              
          public static void decryptFile(String key, String sourceFilePath, String destFilePath) throws Exception {
                  File sourceFile 
          = new File(sourceFilePath);
                  File destFile 
          = new File(destFilePath); 
                  
          if (sourceFile.exists() && sourceFile.isFile()) {
                      
          if (!destFile.getParentFile().exists()) {
                          destFile.getParentFile().mkdirs();
                      }

                      destFile.createNewFile();
                      InputStream in 
          = new FileInputStream(sourceFile);
                      OutputStream out 
          = new FileOutputStream(destFile);
                      Key k 
          = toKey(Base64Utils.decode(key));
                      Cipher cipher 
          = Cipher.getInstance(ALGORITHM);
                      cipher.init(Cipher.DECRYPT_MODE, k);
                      CipherOutputStream cout 
          = new CipherOutputStream(out, cipher);
                      
          byte[] cache = new byte[CACHE_SIZE];
                      
          int nRead = 0;
                      
          while ((nRead = in.read(cache)) != -1{
                          cout.write(cache, 
          0, nRead);
                          cout.flush();
                      }

                      cout.close();
                      out.close();
                      in.close();
                  }

              }


              
          /**
               * <p>
               * 轉換密鑰
               * </p>
               * 
               * 
          @param key
               * 
          @return
               * 
          @throws Exception
               
          */

              
          private static Key toKey(byte[] key) throws Exception {
                  DESKeySpec dks 
          = new DESKeySpec(key);
                  SecretKeyFactory keyFactory 
          = SecretKeyFactory.getInstance(ALGORITHM);
                  SecretKey secretKey 
          = keyFactory.generateSecret(dks);
                  
          return secretKey;
              }

              
          }


          Base64Utils.java
          package demo.security;

          import java.io.ByteArrayInputStream;
          import java.io.ByteArrayOutputStream;
          import java.io.File;
          import java.io.FileInputStream;
          import java.io.FileOutputStream;
          import java.io.InputStream;
          import java.io.OutputStream;

          import it.sauronsoftware.base64.Base64;

          /**
          * <p>
          * BASE64編碼解碼工具包
          * </p>
          * <p>
          * 依賴javabase64-1.3.1.jar
          * </p>
          *
          *
          @author IceWee
          * @date 2012-5-19
          *
          @version 1.0
          */

          public class Base64Utils {

             
          /**
               * 文件讀取緩沖區大小
              
          */

             
          private static final int CACHE_SIZE = 1024;
             
             
          /**
               * <p>
               * BASE64字符串解碼為二進制數據
               * </p>
               *
               *
          @param base64
               *
          @return
               *
          @throws Exception
              
          */

             
          public static byte[] decode(String base64) throws Exception {
                 
          return Base64.decode(base64.getBytes());
              }

             
             
          /**
               * <p>
               * 二進制數據編碼為BASE64字符串
               * </p>
               *
               *
          @param bytes
               *
          @return
               *
          @throws Exception
              
          */

             
          public static String encode(byte[] bytes) throws Exception {
                 
          return new String(Base64.encode(bytes));
              }

             
             
          /**
               * <p>
               * 將文件編碼為BASE64字符串
               * </p>
               * <p>
               * 大文件慎用,可能會導致內存溢出
               * </p>
               *
               *
          @param filePath 文件絕對路徑
               *
          @return
               *
          @throws Exception
              
          */

             
          public static String encodeFile(String filePath) throws Exception {
                 
          byte[] bytes = fileToByte(filePath);
                 
          return encode(bytes);
              }

             
             
          /**
               * <p>
               * BASE64字符串轉回文件
               * </p>
               *
               *
          @param filePath 文件絕對路徑
               *
          @param base64 編碼字符串
               *
          @throws Exception
              
          */

             
          public static void decodeToFile(String filePath, String base64) throws Exception {
                 
          byte[] bytes = decode(base64);
                  byteArrayToFile(bytes, filePath);
              }

             
             
          /**
               * <p>
               * 文件轉換為二進制數組
               * </p>
               *
               *
          @param filePath 文件路徑
               *
          @return
               *
          @throws Exception
              
          */

             
          public static byte[] fileToByte(String filePath) throws Exception {
                 
          byte[] data = new byte[0];
                  File file
          = new File(filePath);
                 
          if (file.exists()) {
                      FileInputStream in
          = new FileInputStream(file);
                      ByteArrayOutputStream out
          = new ByteArrayOutputStream(2048);
                     
          byte[] cache = new byte[CACHE_SIZE];
                     
          int nRead = 0;
                     
          while ((nRead = in.read(cache)) != -1) {
                          out.write(cache,
          0, nRead);
                          out.flush();
                      }

                      out.close();
                      in.close();
                      data
          = out.toByteArray();
                   }

                 
          return data;
              }

             
             
          /**
               * <p>
               * 二進制數據寫文件
               * </p>
               *
               *
          @param bytes 二進制數據
               *
          @param filePath 文件生成目錄
              
          */

             
          public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
                  InputStream in
          = new ByteArrayInputStream(bytes);  
                  File destFile
          = new File(filePath);
                 
          if (!destFile.getParentFile().exists()) {
                      destFile.getParentFile().mkdirs();
                  }

                  destFile.createNewFile();
                  OutputStream out
          = new FileOutputStream(destFile);
                 
          byte[] cache = new byte[CACHE_SIZE];
                 
          int nRead = 0;
                 
          while ((nRead = in.read(cache)) != -1) {  
                      out.write(cache,
          0, nRead);
                      out.flush();
                  }

                  out.close();
                  in.close();
              }

             
             
          }

                                          

          DESTester.java
          package demo.security;

          public class DESTester {

             
          static String key;
             
             
          static {
                 
          try {
          key
          = DESUtils.getSecretKey();
                  }
          catch (Exception e) {
                      e.printStackTrace();
                  }

              }

             
             
          public static void main(String[] args) throws Exception {
                 
          long begin = System.currentTimeMillis();
                  encryptFile();
                  decryptFile();
                  test();
                 
          long end = System.currentTimeMillis();
                  System.err.println(
          "耗時:" + (end-begin)/1000 + "");
              }

             
             
          static void encryptFile() throws Exception {
                  String sourceFilePath
          = "D:/demo.mp4";
                  String destFilePath
          = "D:/demo_encrypted.mp4";
                  DESUtils.encryptFile(key, sourceFilePath, destFilePath);
              }

             
             
          static void decryptFile() throws Exception {
                  String sourceFilePath
          = "D:/demo_encrypted.mp4";
                  String destFilePath
          = "D:/demo_decrypted.mp4";
                  DESUtils.decryptFile(key, sourceFilePath, destFilePath);
              }

             
             
          static void test() throws Exception {
                  String source
          = "這是一行測試DES加密/解密的文字,你看完也等于沒看,是不是啊?!";
                  System.err.println(
          "原文:\t" + source);
                 
          byte[] inputData = source.getBytes();
                  inputData
          = DESUtils.encrypt(inputData, key);
                  System.err.println(
          "加密后:\t" + Base64Utils.encode(inputData));
                 
          byte[] outputData = DESUtils.decrypt(inputData, key);
                  String outputStr
          = new String(outputData);
                  System.err.println(
          "解密后:\t" + outputStr);
              }


          }


          Feedback

          # re: Java DES文件加密解密 javax.crypto.BadPaddingException: Given final block not properly padded  回復  更多評論   

          2012-09-04 22:09 by yaray
          str.getBytes();
          調用此方法時,凡是未指定具體字符編碼的程序,均依賴于JRE所在操作系統的默認編碼類型,因此類似的加解密程序均是不完全可靠的。解決辦法:調用此方法時指定為 UTF-8 編碼,即:str.getBytes("UTF-8");

          # re: Java DES文件加密解密 javax.crypto.BadPaddingException: Given final block not properly padded  回復  更多評論   

          2012-09-05 09:07 by IceWee
          @yaray
          感謝回復,可能我系統上的文字都用的UTF-8編碼吧,Eclipse的編碼也用的UTF-8,所以沒有測試到這個bug。

          # re: Java DES文件加密解密 javax.crypto.BadPaddingException: Given final block not properly padded  回復  更多評論   

          2013-01-10 20:34 by free4wp
          SecureRandom 實現完全隨操作系統本身的內部狀態,除非調用方在調用 getInstance 方法之后又調用了 setSeed 方法;該實現在 windows 上每次生成的 key 都相同,但是在 solaris 或部分 linux 系統上則不同。
          正確的解決方法:
          http://free4wp.com/%e8%a7%a3%e5%86%b3linux%e6%93%8d%e4%bd%9c%e7%b3%bb%e7%bb%9f%e4%b8%8baes%e8%a7%a3%e5%af%86%e5%a4%b1%e8%b4%a5%e7%9a%84%e9%97%ae%e9%a2%98.html
          主站蜘蛛池模板: 麻栗坡县| 张北县| 通山县| 余庆县| 吴江市| 万山特区| 大关县| 灵川县| 东源县| 三明市| 宁晋县| 临洮县| 孝感市| 龙江县| 五台县| 潼南县| 永定县| 普宁市| 西乌| 滕州市| 岑溪市| 晋中市| 云梦县| 武隆县| 格尔木市| 青岛市| 长沙市| 通江县| 蓝田县| 古蔺县| 日喀则市| 同仁县| 临夏县| 龙陵县| 长宁县| 临颍县| 博爱县| 大庆市| 泾川县| 吴堡县| 樟树市|