Java AES 256位加解密

本文详细介绍了如何在Java中实现与Android端一致的AES 256位加解密过程,包括使用BouncyCastle组件支持PKCS7Padding填充方式,以及解决因密钥长度非法导致的异常问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java AES 加解密默认是支持128位的。现在APP端一般都是用256位进行加解密,这时候默认的128就不能匹配了,无法和APP端对应起来。
Android支持PKCS7Padding填充方式,而java默认支持是PKCS5Padding填充方式,这时解析就会报以下异常:
java.security.NoSuchAlgorithmException: Cannot find any provider supporting AES/CBC/PKCS7Padding
解决方法:
 通过BouncyCastle组件来让java里面支持PKCS7Padding填充,BouncyCastle组件下载链接:http://www.bouncycastle.org/
  1.  
    public static String decrypt(String content, String password) {
  2.  
    try {
  3.  
    SecretKey key = getKey(password);
  4.  
    // IMPORTANT TO GET SAME RESULTS ON iOS and ANDROID
  5.  
    final byte[] iv = new byte[16];
  6.  
    Arrays.fill(iv, ( byte) 0x00);
  7.  
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
  8.  
     
  9.  
    byte[] encrypedPwdBytes = Base64.decode(content, Base64.DEFAULT);
  10.  
    //below code must be added in java end ,这个地方调用BouncyCastleProvider , 让java支持PKCS7Padding
  11.  
    Security.addProvider( new org.bouncycastle.jce.provider.BouncyCastleProvider());
  12.  
    // cipher is not thread safe
  13.  
    Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
  14.  
    cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
  15.  
    byte[] decrypedValueBytes = (cipher.doFinal(encrypedPwdBytes));
  16.  
     
  17.  
    String decrypedValue = new String(decrypedValueBytes , "UTF-8");
  18.  
    return decrypedValue;
  19.  
    } catch (Exception ex) {
  20.  
    System.err.println( "Decrypt exception: " + ex.getMessage());
  21.  
    }
  22.  
    return null;
  23.  
    }
在解析Android端的数据还会报出另外一个错误
java.security.InvalidKeyException: Illegal key size
解决方案如下:
处理办法: 在官方网站下载JCE无限制权限策略文件
JDK7的下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
JDK8的下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html 
下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt
如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件
如果安装了JDK,还要将两个jar文件也放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件
 
下面贴出正确认的代码
 
 
[java] view plain copy
 
 
print?
  1. <code class="language-java">import java.io.UnsupportedEncodingException;  
  2. import java.security.Security;  
  3. import java.util.Arrays;  
  4. import javax.crypto.Cipher;  
  5. import javax.crypto.SecretKey;  
  6. import javax.crypto.spec.IvParameterSpec;  
  7. import javax.crypto.spec.SecretKeySpec;  
  8. /** 
  9.  * http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html 
  10.  * http://blog.youkuaiyun.com/chaieven/article/details/70053477 
  11.  * @author E 
  12.  */  
  13. public class BaseAES {  
  14.   
  15.     private static final String DEFAULT_CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";//默认的加密算法  
  16.     /** 
  17.      * AES 加密操作 
  18.      * @param content 待加密内容 
  19.      * @param password 加密密码 
  20.      * @return 返回Base64转码后的加密数据 
  21.      */  
  22.     public static String encrypt(String content, String password) {  
  23.         try {  
  24.             SecretKeySpec skeySpec = getKey(password);  
  25.             byte[] clearText = content.getBytes("UTF8");  
  26.             // IMPORTANT TO GET SAME RESULTS ON iOS and ANDROID  
  27.             final byte[] iv = new byte[16];  
  28.             Arrays.fill(iv, (byte) 0x00);  
  29.             IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);  
  30.               
  31.             //below code must be added in java end  
  32.             Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());  
  33.             // Cipher is not thread safe  
  34.             Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");  
  35.             cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);  
  36.               
  37.             String encrypedValue = Base64.encodeToString(cipher.doFinal(clearText), Base64.DEFAULT);  
  38.             return encrypedValue;  
  39.         } catch (Exception ex) {  
  40.         }  
  41.         return null;  
  42.     }  
  43.   
  44.     /** 
  45.      * AES 解密操作 
  46.      * 
  47.      * @param content 
  48.      * @param password 
  49.      * @return 
  50.      */  
  51.     public static String decrypt(String content, String password) {  
  52.         try {  
  53.             SecretKey key = getKey(password);  
  54.             // IMPORTANT TO GET SAME RESULTS ON iOS and ANDROID  
  55.             final byte[] iv = new byte[16];  
  56.             Arrays.fill(iv, (byte) 0x00);  
  57.             IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);  
  58.               
  59.             byte[] encrypedPwdBytes = Base64.decode(content, Base64.DEFAULT);  
  60.             //below code must be added in java end  
  61.             Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());  
  62.             // cipher is not thread safe  
  63.             Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);  
  64.             cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);  
  65.             byte[] decrypedValueBytes = (cipher.doFinal(encrypedPwdBytes));  
  66.               
  67.             String decrypedValue = new String(decrypedValueBytes , "UTF-8");  
  68.             return decrypedValue;  
  69.         } catch (Exception ex) {  
  70.             System.err.println("Decrypt exception: " + ex.getMessage());  
  71.         }  
  72.         return null;  
  73.     }  
  74.       
  75.     private static SecretKeySpec getKey(String password) throws UnsupportedEncodingException {  
  76.         // You can change it to 128 if you wish  
  77.         int keyLength = 256;  
  78.         byte[] keyBytes = new byte[keyLength / 8];  
  79.         // explicitly fill with zeros  
  80.         Arrays.fill(keyBytes, (byte) 0x0);  
  81.           
  82.         // if password is shorter then key length, it will be zero-padded  
  83.         // to key length  
  84.         byte[] passwordBytes = password.getBytes("UTF-8");  
  85.         int length = passwordBytes.length < keyBytes.length ? passwordBytes.length : keyBytes.length;  
  86.         System.arraycopy(passwordBytes, 0, keyBytes, 0, length);  
  87.         SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");  
  88.         return key;  
  89.     }  
  90. }  
  91. </code>  
  1.  
    import java.io.UnsupportedEncodingException;
  2.  
    import java.security.Security;
  3.  
    import java.util.Arrays;
  4.  
    import javax.crypto.Cipher;
  5.  
    import javax.crypto.SecretKey;
  6.  
    import javax.crypto.spec.IvParameterSpec;
  7.  
    import javax.crypto.spec.SecretKeySpec;
  8.  
    /**
  9.  
    * http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
  10.  
    * http://blog.youkuaiyun.com/chaieven/article/details/70053477
  11.  
    * @author E
  12.  
    */
  13.  
    public class BaseAES {
  14.  
     
  15.  
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";//默认的加密算法
  16.  
    /**
  17.  
    * AES 加密操作
  18.  
    * @param content 待加密内容
  19.  
    * @param password 加密密码
  20.  
    * @return 返回Base64转码后的加密数据
  21.  
    */
  22.  
    public static String encrypt(String content, String password) {
  23.  
    try {
  24.  
    SecretKeySpec skeySpec = getKey(password);
  25.  
    byte[] clearText = content.getBytes("UTF8");
  26.  
    // IMPORTANT TO GET SAME RESULTS ON iOS and ANDROID
  27.  
    final byte[] iv = new byte[16];
  28.  
    Arrays.fill(iv, ( byte) 0x00);
  29.  
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
  30.  
     
  31.  
    //below code must be added in java end
  32.  
    Security.addProvider( new org.bouncycastle.jce.provider.BouncyCastleProvider());
  33.  
    // Cipher is not thread safe
  34.  
    Cipher cipher = Cipher.getInstance( "AES/CBC/PKCS7Padding");
  35.  
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);
  36.  
     
  37.  
    String encrypedValue = Base64.encodeToString(cipher.doFinal(clearText), Base64.DEFAULT);
  38.  
    return encrypedValue;
  39.  
    } catch (Exception ex) {
  40.  
    }
  41.  
    return null;
  42.  
    }
  43.  
     
  44.  
    /**
  45.  
    * AES 解密操作
  46.  
    *
  47.  
    * @param content
  48.  
    * @param password
  49.  
    * @return
  50.  
    */
  51.  
    public static String decrypt(String content, String password) {
  52.  
    try {
  53.  
    SecretKey key = getKey(password);
  54.  
    // IMPORTANT TO GET SAME RESULTS ON iOS and ANDROID
  55.  
    final byte[] iv = new byte[16];
  56.  
    Arrays.fill(iv, ( byte) 0x00);
  57.  
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
  58.  
     
  59.  
    byte[] encrypedPwdBytes = Base64.decode(content, Base64.DEFAULT);
  60.  
    //below code must be added in java end
  61.  
    Security.addProvider( new org.bouncycastle.jce.provider.BouncyCastleProvider());
  62.  
    // cipher is not thread safe
  63.  
    Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
  64.  
    cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
  65.  
    byte[] decrypedValueBytes = (cipher.doFinal(encrypedPwdBytes));
  66.  
     
  67.  
    String decrypedValue = new String(decrypedValueBytes , "UTF-8");
  68.  
    return decrypedValue;
  69.  
    } catch (Exception ex) {
  70.  
    System.err.println( "Decrypt exception: " + ex.getMessage());
  71.  
    }
  72.  
    return null;
  73.  
    }
  74.  
     
  75.  
    private static SecretKeySpec getKey(String password) throws UnsupportedEncodingException {
  76.  
    // You can change it to 128 if you wish
  77.  
    int keyLength = 256;
  78.  
    byte[] keyBytes = new byte[keyLength / 8];
  79.  
    // explicitly fill with zeros
  80.  
    Arrays.fill(keyBytes, ( byte) 0x0);
  81.  
     
  82.  
    // if password is shorter then key length, it will be zero-padded
  83.  
    // to key length
  84.  
    byte[] passwordBytes = password.getBytes("UTF-8");
  85.  
    int length = passwordBytes.length < keyBytes.length ? passwordBytes.length : keyBytes.length;
  86.  
    System.arraycopy(passwordBytes, 0, keyBytes, 0, length);
  87.  
    SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
  88.  
    return key;
  89.  
    }
  90.  
    }
下面是Base64,这是Android里的源码。也是用apache的Base64 
 
 
  1.  
    import java.io.UnsupportedEncodingException;
  2.  
     
  3.  
    public class Base64 {
  4.  
    /**
  5.  
    * Default values for encoder/decoder flags.
  6.  
    */
  7.  
    public static final int DEFAULT = 0;
  8.  
     
  9.  
    /**
  10.  
    * Encoder flag bit to omit the padding '=' characters at the end
  11.  
    * of the output (if any).
  12.  
    */
  13.  
    public static final int NO_PADDING = 1;
  14.  
     
  15.  
    /**
  16.  
    * Encoder flag bit to omit all line terminators (i.e., the output
  17.  
    * will be on one long line).
  18.  
    */
  19.  
    public static final int NO_WRAP = 2;
  20.  
     
  21.  
    /**
  22.  
    * Encoder flag bit to indicate lines should be terminated with a
  23.  
    * CRLF pair instead of just an LF. Has no effect if {@code
  24.  
    * NO_WRAP} is specified as well.
  25.  
    */
  26.  
    public static final int CRLF = 4;
  27.  
     
  28.  
    /**
  29.  
    * Encoder/decoder flag bit to indicate using the "URL and
  30.  
    * filename safe" variant of Base64 (see RFC 3548 section 4) where
  31.  
    * {@code -} and {@code _} are used in place of {@code +} and
  32.  
    * {@code /}.
  33.  
    */
  34.  
    public static final int URL_SAFE = 8;
  35.  
     
  36.  
    /**
  37.  
    * Flag to pass to {@link Base64OutputStream} to indicate that it
  38.  
    * should not close the output stream it is wrapping when it
  39.  
    * itself is closed.
  40.  
    */
  41.  
    public static final int NO_CLOSE = 16;
  42.  
     
  43.  
    // --------------------------------------------------------
  44.  
    // shared code
  45.  
    // --------------------------------------------------------
  46.  
     
  47.  
    /* package */ static abstract class Coder {
  48.  
    public byte[] output;
  49.  
    public int op;
  50.  
     
  51.  
    /**
  52.  
    * Encode/decode another block of input data. this.output is
  53.  
    * provided by the caller, and must be big enough to hold all
  54.  
    * the coded data. On exit, this.opwill be set to the length
  55.  
    * of the coded data.
  56.  
    *
  57.  
    * @param finish true if this is the final call to process for
  58.  
    * this object. Will finalize the coder state and
  59.  
    * include any final bytes in the output.
  60.  
    *
  61.  
    * @return true if the input so far is good; false if some
  62.  
    * error has been detected in the input stream..
  63.  
    */
  64.  
    public abstract boolean process(byte[] input, int offset, int len, boolean finish);
  65.  
     
  66.  
    /**
  67.  
    * @return the maximum number of bytes a call to process()
  68.  
    * could produce for the given number of input bytes. This may
  69.  
    * be an overestimate.
  70.  
    */
  71.  
    public abstract int maxOutputSize(int len);
  72.  
    }
  73.  
     
  74.  
    // --------------------------------------------------------
  75.  
    // decoding
  76.  
    // --------------------------------------------------------
  77.  
     
  78.  
    /**
  79.  
    * Decode the Base64-encoded data in input and return the data in
  80.  
    * a new byte array.
  81.  
    *
  82.  
    * <p>The padding '=' characters at the end are considered optional, but
  83.  
    * if any are present, there must be the correct number of them.
  84.  
    *
  85.  
    * @param str the input String to decode, which is converted to
  86.  
    * bytes using the default charset
  87.  
    * @param flags controls certain features of the decoded output.
  88.  
    * Pass {@code DEFAULT} to decode standard Base64.
  89.  
    *
  90.  
    * @throws IllegalArgumentException if the input contains
  91.  
    * incorrect padding
  92.  
    */
  93.  
    public static byte[] decode(String str, int flags) {
  94.  
    return decode(str.getBytes(), flags);
  95.  
    }
  96.  
     
  97.  
    /**
  98.  
    * Decode the Base64-encoded data in input and return the data in
  99.  
    * a new byte array.
  100.  
    *
  101.  
    * <p>The padding '=' characters at the end are considered optional, but
  102.  
    * if any are present, there must be the correct number of them.
  103.  
    *
  104.  
    * @param input the input array to decode
  105.  
    * @param flags controls certain features of the decoded output.
  106.  
    * Pass {@code DEFAULT} to decode standard Base64.
  107.  
    *
  108.  
    * @throws IllegalArgumentException if the input contains
  109.  
    * incorrect padding
  110.  
    */
  111.  
    public static byte[] decode(byte[] input, int flags) {
  112.  
    return decode(input, 0, input.length, flags);
  113.  
    }
  114.  
     
  115.  
    /**
  116.  
    * Decode the Base64-encoded data in input and return the data in
  117.  
    * a new byte array.
  118.  
    *
  119.  
    * <p>The padding '=' characters at the end are considered optional, but
  120.  
    * if any are present, there must be the correct number of them.
  121.  
    *
  122.  
    * @param input the data to decode
  123.  
    * @param offset the position within the input array at which to start
  124.  
    * @param len the number of bytes of input to decode
  125.  
    * @param flags controls certain features of the decoded output.
  126.  
    * Pass {@code DEFAULT} to decode standard Base64.
  127.  
    *
  128.  
    * @throws IllegalArgumentException if the input contains
  129.  
    * incorrect padding
  130.  
    */
  131.  
    public static byte[] decode(byte[] input, int offset, int len, int flags) {
  132.  
    // Allocate space for the most data the input could represent.
  133.  
    // (It could contain less if it contains whitespace, etc.)
  134.  
    Decoder decoder = new Decoder(flags, new byte[len*3/4]);
  135.  
     
  136.  
    if (!decoder.process(input, offset, len, true)) {
  137.  
    throw new IllegalArgumentException("bad base-64");
  138.  
    }
  139.  
     
  140.  
    // Maybe we got lucky and allocated exactly enough output space.
  141.  
    if (decoder.op == decoder.output.length) {
  142.  
    return decoder.output;
  143.  
    }
  144.  
     
  145.  
    // Need to shorten the array, so allocate a new one of the
  146.  
    // right size and copy.
  147.  
    byte[] temp = new byte[decoder.op];
  148.  
    System.arraycopy(decoder.output, 0, temp, 0, decoder.op);
  149.  
    return temp;
  150.  
    }
  151.  
     
  152.  
    /* package */ static class Decoder extends Coder {
  153.  
    /**
  154.  
    * Lookup table for turning bytes into their position in the
  155.  
    * Base64 alphabet.
  156.  
    */
  157.  
    private static final int DECODE[] = {
  158.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  159.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  160.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
  161.  
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
  162.  
    - 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
  163.  
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
  164.  
    - 1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
  165.  
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
  166.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  167.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  168.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  169.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  170.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  171.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  172.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  173.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  174.  
    };
  175.  
     
  176.  
    /**
  177.  
    * Decode lookup table for the "web safe" variant (RFC 3548
  178.  
    * sec. 4) where - and _ replace + and /.
  179.  
    */
  180.  
    private static final int DECODE_WEBSAFE[] = {
  181.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  182.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  183.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1,
  184.  
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
  185.  
    - 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
  186.  
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
  187.  
    - 1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
  188.  
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
  189.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  190.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  191.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  192.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  193.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  194.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  195.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  196.  
    - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  197.  
    };
  198.  
     
  199.  
    /** Non-data values in the DECODE arrays. */
  200.  
    private static final int SKIP = -1;
  201.  
    private static final int EQUALS = -2;
  202.  
     
  203.  
    /**
  204.  
    * States 0-3 are reading through the next input tuple.
  205.  
    * State 4 is having read one '=' and expecting exactly
  206.  
    * one more.
  207.  
    * State 5 is expecting no more data or padding characters
  208.  
    * in the input.
  209.  
    * State 6 is the error state; an error has been detected
  210.  
    * in the input and no future input can "fix" it.
  211.  
    */
  212.  
    private int state; // state number (0 to 6)
  213.  
    private int value;
  214.  
     
  215.  
    final private int[] alphabet;
  216.  
     
  217.  
    public Decoder(int flags, byte[] output) {
  218.  
    this.output = output;
  219.  
     
  220.  
    alphabet = ((flags & URL_SAFE) == 0) ? DECODE : DECODE_WEBSAFE;
  221.  
    state = 0;
  222.  
    value = 0;
  223.  
    }
  224.  
     
  225.  
    /**
  226.  
    * @return an overestimate for the number of bytes {@code
  227.  
    * len} bytes could decode to.
  228.  
    */
  229.  
    public int maxOutputSize(int len) {
  230.  
    return len * 3/4 + 10;
  231.  
    }
  232.  
     
  233.  
    /**
  234.  
    * Decode another block of input data.
  235.  
    *
  236.  
    * @return true if the state machine is still healthy. false if
  237.  
    * bad base-64 data has been detected in the input stream.
  238.  
    */
  239.  
    public boolean process(byte[] input, int offset, int len, boolean finish) {
  240.  
    if (this.state == 6) return false;
  241.  
     
  242.  
    int p = offset;
  243.  
    len += offset;
  244.  
     
  245.  
    // Using local variables makes the decoder about 12%
  246.  
    // faster than if we manipulate the member variables in
  247.  
    // the loop. (Even alphabet makes a measurable
  248.  
    // difference, which is somewhat surprising to me since
  249.  
    // the member variable is final.)
  250.  
    int state = this.state;
  251.  
    int value = this.value;
  252.  
    int op = 0;
  253.  
    final byte[] output = this.output;
  254.  
    final int[] alphabet = this.alphabet;
  255.  
     
  256.  
    while (p < len) {
  257.  
    // Try the fast path: we're starting a new tuple and the
  258.  
    // next four bytes of the input stream are all data
  259.  
    // bytes. This corresponds to going through states
  260.  
    // 0-1-2-3-0. We expect to use this method for most of
  261.  
    // the data.
  262.  
    //
  263.  
    // If any of the next four bytes of input are non-data
  264.  
    // (whitespace, etc.), value will end up negative. (All
  265.  
    // the non-data values in decode are small negative
  266.  
    // numbers, so shifting any of them up and or'ing them
  267.  
    // together will result in a value with its top bit set.)
  268.  
    //
  269.  
    // You can remove this whole block and the output should
  270.  
    // be the same, just slower.
  271.  
    if (state == 0) {
  272.  
    while (p+4 <= len &&
  273.  
    (value = ((alphabet[input[p] & 0xff] << 18) |
  274.  
    (alphabet[input[p+ 1] & 0xff] << 12) |
  275.  
    (alphabet[input[p+ 2] & 0xff] << 6) |
  276.  
    (alphabet[input[p+ 3] & 0xff]))) >= 0) {
  277.  
    output[op+ 2] = (byte) value;
  278.  
    output[op+ 1] = (byte) (value >> 8);
  279.  
    output[op] = ( byte) (value >> 16);
  280.  
    op += 3;
  281.  
    p += 4;
  282.  
    }
  283.  
    if (p >= len) break;
  284.  
    }
  285.  
     
  286.  
    // The fast path isn't available -- either we've read a
  287.  
    // partial tuple, or the next four input bytes aren't all
  288.  
    // data, or whatever. Fall back to the slower state
  289.  
    // machine implementation.
  290.  
     
  291.  
    int d = alphabet[input[p++] & 0xff];
  292.  
     
  293.  
    switch (state) {
  294.  
    case 0:
  295.  
    if (d >= 0) {
  296.  
    value = d;
  297.  
    ++state;
  298.  
    } else if (d != SKIP) {
  299.  
    this.state = 6;
  300.  
    return false;
  301.  
    }
  302.  
    break;
  303.  
     
  304.  
    case 1:
  305.  
    if (d >= 0) {
  306.  
    value = (value << 6) | d;
  307.  
    ++state;
  308.  
    } else if (d != SKIP) {
  309.  
    this.state = 6;
  310.  
    return false;
  311.  
    }
  312.  
    break;
  313.  
     
  314.  
    case 2:
  315.  
    if (d >= 0) {
  316.  
    value = (value << 6) | d;
  317.  
    ++state;
  318.  
    } else if (d == EQUALS) {
  319.  
    // Emit the last (partial) output tuple;
  320.  
    // expect exactly one more padding character.
  321.  
    output[op++] = ( byte) (value >> 4);
  322.  
    state = 4;
  323.  
    } else if (d != SKIP) {
  324.  
    this.state = 6;
  325.  
    return false;
  326.  
    }
  327.  
    break;
  328.  
     
  329.  
    case 3:
  330.  
    if (d >= 0) {
  331.  
    // Emit the output triple and return to state 0.
  332.  
    value = (value << 6) | d;
  333.  
    output[op+ 2] = (byte) value;
  334.  
    output[op+ 1] = (byte) (value >> 8);
  335.  
    output[op] = ( byte) (value >> 16);
  336.  
    op += 3;
  337.  
    state = 0;
  338.  
    } else if (d == EQUALS) {
  339.  
    // Emit the last (partial) output tuple;
  340.  
    // expect no further data or padding characters.
  341.  
    output[op+ 1] = (byte) (value >> 2);
  342.  
    output[op] = ( byte) (value >> 10);
  343.  
    op += 2;
  344.  
    state = 5;
  345.  
    } else if (d != SKIP) {
  346.  
    this.state = 6;
  347.  
    return false;
  348.  
    }
  349.  
    break;
  350.  
     
  351.  
    case 4:
  352.  
    if (d == EQUALS) {
  353.  
    ++state;
  354.  
    } else if (d != SKIP) {
  355.  
    this.state = 6;
  356.  
    return false;
  357.  
    }
  358.  
    break;
  359.  
     
  360.  
    case 5:
  361.  
    if (d != SKIP) {
  362.  
    this.state = 6;
  363.  
    return false;
  364.  
    }
  365.  
    break;
  366.  
    }
  367.  
    }
  368.  
     
  369.  
    if (!finish) {
  370.  
    // We're out of input, but a future call could provide
  371.  
    // more.
  372.  
    this.state = state;
  373.  
    this.value = value;
  374.  
    this.op = op;
  375.  
    return true;
  376.  
    }
  377.  
     
  378.  
    // Done reading input. Now figure out where we are left in
  379.  
    // the state machine and finish up.
  380.  
     
  381.  
    switch (state) {
  382.  
    case 0:
  383.  
    // Output length is a multiple of three. Fine.
  384.  
    break;
  385.  
    case 1:
  386.  
    // Read one extra input byte, which isn't enough to
  387.  
    // make another output byte. Illegal.
  388.  
    this.state = 6;
  389.  
    return false;
  390.  
    case 2:
  391.  
    // Read two extra input bytes, enough to emit 1 more
  392.  
    // output byte. Fine.
  393.  
    output[op++] = ( byte) (value >> 4);
  394.  
    break;
  395.  
    case 3:
  396.  
    // Read three extra input bytes, enough to emit 2 more
  397.  
    // output bytes. Fine.
  398.  
    output[op++] = ( byte) (value >> 10);
  399.  
    output[op++] = ( byte) (value >> 2);
  400.  
    break;
  401.  
    case 4:
  402.  
    // Read one padding '=' when we expected 2. Illegal.
  403.  
    this.state = 6;
  404.  
    return false;
  405.  
    case 5:
  406.  
    // Read all the padding '='s we expected and no more.
  407.  
    // Fine.
  408.  
    break;
  409.  
    }
  410.  
     
  411.  
    this.state = state;
  412.  
    this.op = op;
  413.  
    return true;
  414.  
    }
  415.  
    }
  416.  
     
  417.  
    // --------------------------------------------------------
  418.  
    // encoding
  419.  
    // --------------------------------------------------------
  420.  
     
  421.  
    /**
  422.  
    * Base64-encode the given data and return a newly allocated
  423.  
    * String with the result.
  424.  
    *
  425.  
    * @param input the data to encode
  426.  
    * @param flags controls certain features of the encoded output.
  427.  
    * Passing {@code DEFAULT} results in output that
  428.  
    * adheres to RFC 2045.
  429.  
    */
  430.  
    public static String encodeToString(byte[] input, int flags) {
  431.  
    try {
  432.  
    return new String(encode(input, flags), "US-ASCII");
  433.  
    } catch (UnsupportedEncodingException e) {
  434.  
    // US-ASCII is guaranteed to be available.
  435.  
    throw new AssertionError(e);
  436.  
    }
  437.  
    }
  438.  
     
  439.  
    /**
  440.  
    * Base64-encode the given data and return a newly allocated
  441.  
    * String with the result.
  442.  
    *
  443.  
    * @param input the data to encode
  444.  
    * @param offset the position within the input array at which to
  445.  
    * start
  446.  
    * @param len the number of bytes of input to encode
  447.  
    * @param flags controls certain features of the encoded output.
  448.  
    * Passing {@code DEFAULT} results in output that
  449.  
    * adheres to RFC 2045.
  450.  
    */
  451.  
    public static String encodeToString(byte[] input, int offset, int len, int flags) {
  452.  
    try {
  453.  
    return new String(encode(input, offset, len, flags), "US-ASCII");
  454.  
    } catch (UnsupportedEncodingException e) {
  455.  
    // US-ASCII is guaranteed to be available.
  456.  
    throw new AssertionError(e);
  457.  
    }
  458.  
    }
  459.  
     
  460.  
    /**
  461.  
    * Base64-encode the given data and return a newly allocated
  462.  
    * byte[] with the result.
  463.  
    *
  464.  
    * @param input the data to encode
  465.  
    * @param flags controls certain features of the encoded output.
  466.  
    * Passing {@code DEFAULT} results in output that
  467.  
    * adheres to RFC 2045.
  468.  
    */
  469.  
    public static byte[] encode(byte[] input, int flags) {
  470.  
    return encode(input, 0, input.length, flags);
  471.  
    }
  472.  
     
  473.  
    /**
  474.  
    * Base64-encode the given data and return a newly allocated
  475.  
    * byte[] with the result.
  476.  
    *
  477.  
    * @param input the data to encode
  478.  
    * @param offset the position within the input array at which to
  479.  
    * start
  480.  
    * @param len the number of bytes of input to encode
  481.  
    * @param flags controls certain features of the encoded output.
  482.  
    * Passing {@code DEFAULT} results in output that
  483.  
    * adheres to RFC 2045.
  484.  
    */
  485.  
    public static byte[] encode(byte[] input, int offset, int len, int flags) {
  486.  
    Encoder encoder = new Encoder(flags, null);
  487.  
     
  488.  
    // Compute the exact length of the array we will produce.
  489.  
    int output_len = len / 3 * 4;
  490.  
     
  491.  
    // Account for the tail of the data and the padding bytes, if any.
  492.  
    if (encoder.do_padding) {
  493.  
    if (len % 3 > 0) {
  494.  
    output_len += 4;
  495.  
    }
  496.  
    } else {
  497.  
    switch (len % 3) {
  498.  
    case 0: break;
  499.  
    case 1: output_len += 2; break;
  500.  
    case 2: output_len += 3; break;
  501.  
    }
  502.  
    }
  503.  
     
  504.  
    // Account for the newlines, if any.
  505.  
    if (encoder.do_newline && len > 0) {
  506.  
    output_len += (((len- 1) / (3 * Encoder.LINE_GROUPS)) + 1) *
  507.  
    (encoder.do_cr ? 2 : 1);
  508.  
    }
  509.  
     
  510.  
    encoder.output = new byte[output_len];
  511.  
    encoder.process(input, offset, len, true);
  512.  
     
  513.  
    assert encoder.op == output_len;
  514.  
     
  515.  
    return encoder.output;
  516.  
    }
  517.  
     
  518.  
    /* package */ static class Encoder extends Coder {
  519.  
    /**
  520.  
    * Emit a new line every this many output tuples. Corresponds to
  521.  
    * a 76-character line length (the maximum allowable according to
  522.  
    * <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>).
  523.  
    */
  524.  
    public static final int LINE_GROUPS = 19;
  525.  
     
  526.  
    /**
  527.  
    * Lookup table for turning Base64 alphabet positions (6 bits)
  528.  
    * into output bytes.
  529.  
    */
  530.  
    private static final byte ENCODE[] = {
  531.  
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
  532.  
    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
  533.  
    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
  534.  
    'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
  535.  
    };
  536.  
     
  537.  
    /**
  538.  
    * Lookup table for turning Base64 alphabet positions (6 bits)
  539.  
    * into output bytes.
  540.  
    */
  541.  
    private static final byte ENCODE_WEBSAFE[] = {
  542.  
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
  543.  
    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
  544.  
    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
  545.  
    'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_',
  546.  
    };
  547.  
     
  548.  
    final private byte[] tail;
  549.  
    /* package */ int tailLen;
  550.  
    private int count;
  551.  
     
  552.  
    final public boolean do_padding;
  553.  
    final public boolean do_newline;
  554.  
    final public boolean do_cr;
  555.  
    final private byte[] alphabet;
  556.  
     
  557.  
    public Encoder(int flags, byte[] output) {
  558.  
    this.output = output;
  559.  
     
  560.  
    do_padding = (flags & NO_PADDING) == 0;
  561.  
    do_newline = (flags & NO_WRAP) == 0;
  562.  
    do_cr = (flags & CRLF) != 0;
  563.  
    alphabet = ((flags & URL_SAFE) == 0) ? ENCODE : ENCODE_WEBSAFE;
  564.  
     
  565.  
    tail = new byte[2];
  566.  
    tailLen = 0;
  567.  
     
  568.  
    count = do_newline ? LINE_GROUPS : - 1;
  569.  
    }
  570.  
     
  571.  
    /**
  572.  
    * @return an overestimate for the number of bytes {@code
  573.  
    * len} bytes could encode to.
  574.  
    */
  575.  
    public int maxOutputSize(int len) {
  576.  
    return len * 8/5 + 10;
  577.  
    }
  578.  
     
  579.  
    public boolean process(byte[] input, int offset, int len, boolean finish) {
  580.  
    // Using local variables makes the encoder about 9% faster.
  581.  
    final byte[] alphabet = this.alphabet;
  582.  
    final byte[] output = this.output;
  583.  
    int op = 0;
  584.  
    int count = this.count;
  585.  
     
  586.  
    int p = offset;
  587.  
    len += offset;
  588.  
    int v = -1;
  589.  
     
  590.  
    // First we need to concatenate the tail of the previous call
  591.  
    // with any input bytes available now and see if we can empty
  592.  
    // the tail.
  593.  
     
  594.  
    switch (tailLen) {
  595.  
    case 0:
  596.  
    // There was no tail.
  597.  
    break;
  598.  
     
  599.  
    case 1:
  600.  
    if (p+2 <= len) {
  601.  
    // A 1-byte tail with at least 2 bytes of
  602.  
    // input available now.
  603.  
    v = ((tail[ 0] & 0xff) << 16) |
  604.  
    ((input[p++] & 0xff) << 8) |
  605.  
    (input[p++] & 0xff);
  606.  
    tailLen = 0;
  607.  
    };
  608.  
    break;
  609.  
     
  610.  
    case 2:
  611.  
    if (p+1 <= len) {
  612.  
    // A 2-byte tail with at least 1 byte of input.
  613.  
    v = ((tail[ 0] & 0xff) << 16) |
  614.  
    ((tail[ 1] & 0xff) << 8) |
  615.  
    (input[p++] & 0xff);
  616.  
    tailLen = 0;
  617.  
    }
  618.  
    break;
  619.  
    }
  620.  
     
  621.  
    if (v != -1) {
  622.  
    output[op++] = alphabet[(v >> 18) & 0x3f];
  623.  
    output[op++] = alphabet[(v >> 12) & 0x3f];
  624.  
    output[op++] = alphabet[(v >> 6) & 0x3f];
  625.  
    output[op++] = alphabet[v & 0x3f];
  626.  
    if (--count == 0) {
  627.  
    if (do_cr) output[op++] = '\r';
  628.  
    output[op++] = '\n';
  629.  
    count = LINE_GROUPS;
  630.  
    }
  631.  
    }
  632.  
     
  633.  
    // At this point either there is no tail, or there are fewer
  634.  
    // than 3 bytes of input available.
  635.  
     
  636.  
    // The main loop, turning 3 input bytes into 4 output bytes on
  637.  
    // each iteration.
  638.  
    while (p+3 <= len) {
  639.  
    v = ((input[p] & 0xff) << 16) |
  640.  
    ((input[p+ 1] & 0xff) << 8) |
  641.  
    (input[p+ 2] & 0xff);
  642.  
    output[op] = alphabet[(v >> 18) & 0x3f];
  643.  
    output[op+ 1] = alphabet[(v >> 12) & 0x3f];
  644.  
    output[op+ 2] = alphabet[(v >> 6) & 0x3f];
  645.  
    output[op+ 3] = alphabet[v & 0x3f];
  646.  
    p += 3;
  647.  
    op += 4;
  648.  
    if (--count == 0) {
  649.  
    if (do_cr) output[op++] = '\r';
  650.  
    output[op++] = '\n';
  651.  
    count = LINE_GROUPS;
  652.  
    }
  653.  
    }
  654.  
     
  655.  
    if (finish) {
  656.  
    // Finish up the tail of the input. Note that we need to
  657.  
    // consume any bytes in tail before any bytes
  658.  
    // remaining in input; there should be at most two bytes
  659.  
    // total.
  660.  
     
  661.  
    if (p-tailLen == len-1) {
  662.  
    int t = 0;
  663.  
    v = ((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 4;
  664.  
    tailLen -= t;
  665.  
    output[op++] = alphabet[(v >> 6) & 0x3f];
  666.  
    output[op++] = alphabet[v & 0x3f];
  667.  
    if (do_padding) {
  668.  
    output[op++] = '=';
  669.  
    output[op++] = '=';
  670.  
    }
  671.  
    if (do_newline) {
  672.  
    if (do_cr) output[op++] = '\r';
  673.  
    output[op++] = '\n';
  674.  
    }
  675.  
    } else if (p-tailLen == len-2) {
  676.  
    int t = 0;
  677.  
    v = (((tailLen > 1 ? tail[t++] : input[p++]) & 0xff) << 10) |
  678.  
    (((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 2);
  679.  
    tailLen -= t;
  680.  
    output[op++] = alphabet[(v >> 12) & 0x3f];
  681.  
    output[op++] = alphabet[(v >> 6) & 0x3f];
  682.  
    output[op++] = alphabet[v & 0x3f];
  683.  
    if (do_padding) {
  684.  
    output[op++] = '=';
  685.  
    }
  686.  
    if (do_newline) {
  687.  
    if (do_cr) output[op++] = '\r';
  688.  
    output[op++] = '\n';
  689.  
    }
  690.  
    } else if (do_newline && op > 0 && count != LINE_GROUPS) {
  691.  
    if (do_cr) output[op++] = '\r';
  692.  
    output[op++] = '\n';
  693.  
    }
  694.  
     
  695.  
    assert tailLen == 0;
  696.  
    assert p == len;
  697.  
    } else {
  698.  
    // Save the leftovers in tail to be consumed on the next
  699.  
    // call to encodeInternal.
  700.  
     
  701.  
    if (p == len-1) {
  702.  
    tail[tailLen++] = input[p];
  703.  
    } else if (p == len-2) {
  704.  
    tail[tailLen++] = input[p];
  705.  
    tail[tailLen++] = input[p+ 1];
  706.  
    }
  707.  
    }
  708.  
     
  709.  
    this.op = op;
  710.  
    this.count = count;
  711.  
     
  712.  
    return true;
  713.  
    }
  714.  
    }
  715.  
     
  716.  
    private Base64() { } // don't instantiate
  717.  
    }
这个问题的解决要感谢@ 柴可夫老司机 ,他的文章出处http://blog.youkuaiyun.com/chaieven/article/details/70053477

--------------------- 本文来自 LoveLife 的优快云 博客 ,全文地址请点击:https://blog.youkuaiyun.com/eastman520/article/details/79657367?utm_source=copy 

转载于:https://www.cnblogs.com/t0000/articles/9716842.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值