Android:AES 和BASE64的加密和解密

一、前言:

BASE64和AES一起介绍,有两个工具类,直接使用即可。

gitHub地址:https://gitee.com/luoyanyong/AESDemo/tree/master/app/src/main/java/com/sumansoul/aesdemo

注意:

  1. 解决AES加密报错:java.security.InvalidKeyException: Unsupported key size: 6 bytes。

原因:

AES秘钥字节就我们传入的解密的秘钥,
这是由于AES的秘钥写错了,规定是16位秘钥,写成了6位的秘钥。

解决:将AES秘钥改成规定的16位即可。

1. 基本使用:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //BASE64使用
        initBASE64();
        //AES使用
        initAES();
        //MD5使用
        initMD5();

       //最简单的AES使用(第二种使用方式)
        initAES2();


    }



    /**
     * BASE64使用
     */
    private void initBASE64() {
        String value = "1992090876";
        Log.d("LUO","BASE64原数据============"+value);
        String encryptionBASE64 = Base64Utils.getEncryptionBASE64(value);
        Log.d("LUO","BASE64加密数据============"+encryptionBASE64);

        String decryptFromBASE64 = Base64Utils.getDecryptFromBASE64(encryptionBASE64);
        Log.d("LUO","BASE64解密数据============"+decryptFromBASE64);

//        LUO: BASE64原数据============1992090876
//        LUO: BASE64加密数据============MTk5MjA5MDg3Ng==
//        LUO: BASE64解密数据============1992090876
    }

    /**
     * AES使用
     */
    private void initAES() {

        String aes = "123456789";
        //将AES秘钥改成规定的16位即可。
        String key = "0123456789123456";
        try {
            Log.d("LUO","AES原数据============"+aes);
            //加密
           String  encryption=  AESEncryptUtils.encryptAES(aes,key);
            Log.d("LUO","AES加密后============"+encryption);
           //解密
           String decrypt = AESEncryptUtils.decryptAES(encryption,key);
            Log.d("LUO","AES解密后============"+decrypt);

//           LUO: AES原数据============123456789
//           LUO: AES加密后============jvTvlQaeDHK77gai7Eb2Gg==
//           LUO: AES解密后============123456789


        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * MD5使用
     * MD5是不可逆,这里的加密解密,你可以看到是对MD5算法先加密后解密,而不是对MD5的解密
     */
    private void initMD5() {
        String value = "123456";
        Log.d("LUO","MD5原数据============"+value);
        //加密的MD5
        String md5Encode = MD5Utils.MD5Encode(value);
        Log.d("LUO","MD5加密后数据============"+md5Encode);

        //对解密的MD5,再加密
        String md5Encode_kl = MD5Utils.KL(MD5Utils.MD5Encode(value));
        Log.d("LUO","MD5_kl加密后数据============"+md5Encode_kl);
        //对解密的MD5,解加密
        String decrypt = MD5Utils.MD5Decrypt(md5Encode_kl);
        Log.d("LUO","MD5_kl解密后数据============"+decrypt);

//        LUO: MD5原数据============123456
//        LUO: MD5加密后数据============e10adc3949ba59abbe56e057f20f883e
//        LUO: MD5_kl加密后数据============�ED���GM@M��AM����AB�DAC�FD�LLG�
//        LUO: MD5_kl解密后数据============e10adc3949ba59abbe56e057f20f883e
    }
}

 /**
     * 最简单的AES使用(第二种使用方式)
     */
    private void initAES2() {
        try {
            String value = "123456789";
            Log.d("LUO","initAES2原数据============"+value);
            String encrypt = AESUtil.encrypt(value);
            Log.d("LUO","initAES2加密数据============"+encrypt);
            String decrypt = AESUtil.decrypt(encrypt);
            Log.d("LUO","initAES2解密数据============"+decrypt);

//            LUO: initAES2原数据============123456789
//            LUO: initAES2加密数据============OpuRX5DJc8lewuB7qQkpzw==
//            LUO: initAES2解密数据============123456789
        } catch (Exception e) {
            e.printStackTrace();
        }


    }


2. Base64Utils.java类

package com.sumansoul.aesdemo;

import com.sumansoul.aesdemo.utils.BASE64Decoder;
import com.sumansoul.aesdemo.utils.BASE64Encoder;


/**
 * Base64的加密和解密
 */
public class Base64Utils {


    /**
     * 将 value 进行 BASE64 编码
     *
     * @param value
     * @return
     */
    public static String getEncryptionBASE64(String value) {
        if (value == null) {
            return null;
        }
        return (new BASE64Encoder()).encode(value.getBytes());
    }

    /**
     * 将 BASE64 编码的字符串 value 进行解码
     *
     * @param value
     * @return
     */
    public static String getDecryptFromBASE64(String value) {
        if (value == null) {
            return null;
        }
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            byte[] b = decoder.decodeBuffer(value);
            return new String(b);
        } catch (Exception e) {
            return null;
        }
    }


}

3. AESEncryptUtils.java类

package com.sumansoul.aesdemo.utils;
import android.text.TextUtils;
import java.math.BigInteger;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
 * 编码工具类
 * 1.将byte[]转为各种进制的字符串
 * 2.base 64 encode
 * 3.base 64 decode
 * 4.获取byte[]的md5值
 * 5.获取字符串md5值
 * 6.结合base64实现md5加密
 * 7.AES加密
 * 8.AES加密为base 64 code
 * 9.AES解密
 * 10.将base 64 code AES解密
 *
 * @author uikoo9
 * @version 0.0.7.20140601
 */
public class AESEncryptUtils {
    /**
     *  1.电码本模式(Electronic Codebook Book (ECB))不支持;
     *  2.密码分组链接模式(Cipher Block Chaining (CBC))默认的加密算法;
     *  3.计算器模式(Counter (CTR));
     *  4.密码反馈模式(Cipher FeedBack (CFB));
     *  5.输出反馈模式(Output FeedBack (OFB))。
     */
    // 指定加密的算法、工作模式和填充方式
    private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
    /**
     *  偏移量
     */
    private static final String IV_STRING = "1234561234567890";

    /**
     * 将byte[]转为各种进制的字符串
     *
     * @param bytes byte[]
     * @param radix 可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制
     * @return 转换后的字符串
     */
    public static String binary(byte[] bytes, int radix) {
        return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数
    }

    /**
     * base 64 encode
     *
     * @param bytes 待编码的byte[]
     * @return 编码后的base 64 code
     */
    public static String base64Encode(byte[] bytes) {
        return new BASE64Encoder().encode(bytes);
    }

    /**
     * base 64 decode
     *
     * @param base64Code 待解码的base 64 code
     * @return 解码后的byte[]
     * @throws Exception
     */
    public static byte[] base64Decode(String base64Code) throws Exception {
        return TextUtils.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);
    }

    /**
     * 获取byte[]的md5值
     *
     * @param bytes byte[]
     * @return md5
     * @throws Exception
     */
    public static byte[] md5(byte[] bytes) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(bytes);

        return md.digest();
    }

    /**
     * 获取字符串md5值
     *
     * @param msg
     * @return md5
     * @throws Exception
     */
    public static byte[] md5(String msg) throws Exception {
        return TextUtils.isEmpty(msg) ? null : md5(msg.getBytes());
    }

    /**
     * 结合base64实现md5加密
     *
     * @param msg 待加密字符串
     * @return 获取md5后转为base64
     * @throws Exception
     */
    public static String md5Encrypt(String msg) throws Exception {
        return TextUtils.isEmpty(msg) ? null : base64Encode(md5(msg));
    }

    /**
     * AES加密
     *
     * @param content    待加密的内容
     * @param encryptKey 加密密钥
     * @return 加密后的byte[]
     * @throws Exception
     */
    public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
//        KeyGenerator kgen = KeyGenerator.getInstance("AES");
//        kgen.init(128, new SecureRandom(encryptKey.getBytes()));
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(encryptKey.getBytes());
        kgen.init(128, random);
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));

        return cipher.doFinal(content.getBytes("utf-8"));
    }

    /**
     * AES加密为base 64 code
     *
     * @param content    待加密的内容
     * @param encryptKey 加密密钥
     * @return 加密后的base 64 code
     * @throws Exception
     */
    public static String aesEncrypt(String content, String encryptKey) throws Exception {
        return base64Encode(aesEncryptToBytes(content, encryptKey));
    }

    /**
     * AES解密
     *
     * @param encryptBytes 待解密的byte[]
     * @param decryptKey   解密密钥
     * @return 解密后的String
     * @throws Exception
     */
    public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws
            Exception {
//        KeyGenerator kgen = KeyGenerator.getInstance("AES");
//        kgen.init(128, new SecureRandom(decryptKey.getBytes()));
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(decryptKey.getBytes());
        kgen.init(128, random);
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));
        byte[] decryptBytes = cipher.doFinal(encryptBytes);

        return new String(decryptBytes);
    }

    /**
     * 将base 64 code AES解密
     *
     * @param encryptStr 待解密的base 64 code
     * @param decryptKey 解密密钥
     * @return 解密后的string
     */
    public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {
        return TextUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr),
                decryptKey);
    }

    /**
     * @param content
     * @param key     将AES秘钥改成规定的16位即可。
     * @return
     * @throws Exception 加密(使用这个)
     */
    public static String encryptAES(String content, String key)
            throws Exception {
        byte[] byteContent = content.getBytes("UTF-8");
        // 注意,为了能与 iOS 统一
        // 这里的 key 不可以使用 KeyGenerator、SecureRandom、SecretKey 生成
        byte[] enCodeFormat = key.getBytes();
        SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");
        byte[] initParam = IV_STRING.getBytes();
        IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
        // 指定加密的算法、工作模式和填充方式
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        byte[] encryptedBytes = cipher.doFinal(byteContent);
        // 同样对加密后数据进行 base64 编码
        return base64Encode(encryptedBytes);
    }

    /**
     * @param content
     * @param key     将AES秘钥改成规定的16位即可。
     * @return
     * @throws Exception 解密(使用这个)
     */
    public static String decryptAES(String content, String key)
            throws Exception {
        // base64 解码
        byte[] encryptedBytes = base64Decode(content);
        byte[] enCodeFormat = key.getBytes();
        SecretKeySpec secretKey = new SecretKeySpec(enCodeFormat, "AES");
        byte[] initParam = IV_STRING.getBytes();
        IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
        byte[] result = cipher.doFinal(encryptedBytes);
        return new String(result, "UTF-8");
    }

}

4. MD5Utils.java类

package com.sumansoul.aesdemo.utils;

import java.security.MessageDigest;

/**
 * @Author:LUO
 * @Description:
 * @Date:Created in 9:46 2018/4/13
 * Modified By:
 */
public class MD5Utils {

    private static final String hexDigIts[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

    /**
     * MD5加密数据
     */
    public static String MD5Encode(String value) {
        String resultString = null;
        try {
            resultString = new String(value);
            MessageDigest md = MessageDigest.getInstance("MD5");
            resultString = byteArrayToHexString(md.digest(resultString.getBytes("UTF-8")));
        } catch (Exception e) {
        }
        return resultString;
    }


    /**
     * MD5加密后解密(一定要KL()再用KL()解密)
     * MD5是不可逆,这里的加密解密,你可以看到是对MD5算法先加密后解密,而不是对MD5的解密
     *
     * @param value
     * @return
     */
    public static String MD5Decrypt(String value) {
        char[] a = value.toCharArray();
        for (int i = 0; i < a.length; i++) {
            a[i] = (char) (a[i] ^ 't');
        }
        String k = new String(a);
        return k;
    }


    // 可逆的加密算法
    public static String KL(String inStr) {
        // String s = new String(inStr);
        char[] a = inStr.toCharArray();
        for (int i = 0; i < a.length; i++) {
            a[i] = (char) (a[i] ^ 't');
        }
        String s = new String(a);
        return s;
    }


    public static String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            resultSb.append(byteToHexString(b[i]));
        }
        return resultSb.toString();
    }

    public static String byteToHexString(byte b) {
        int n = b;
        if (n < 0) {
            n += 256;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigIts[d1] + hexDigIts[d2];
    }


    // 测试主函数
//    public static void main(String args[]) {
//        String s = new String("sa");
//        System.out.println("原始:" + s);
//        System.out.println("MD5后:" + MD5Encode(s));
//        System.out.println("MD5后再加密:" + KL(MD5Encode(s)));
//        System.out.println("解密为MD5后的:" + MD5Decrypt(KL(MD5Encode(s))));
//    }


}

5. AESUtil.java类

package com.sumansoul.aesdemo.utils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
 * AES最简单的加密
 */
public class AESUtil {
    //算法
    private static final String ALGORITHM = "AES";
    /**
     *  1.电码本模式(Electronic Codebook Book (ECB))不支持;
     *  2.密码分组链接模式(Cipher Block Chaining (CBC))默认的加密算法;
     *  3.计算器模式(Counter (CTR));
     *  4.密码反馈模式(Cipher FeedBack (CFB));
     *  5.输出反馈模式(Output FeedBack (OFB))。
     */
    // 指定加密的算法、工作模式和填充方式
    private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
    // 编码
    private static final String ENCODING = "UTF-8";
    // 密匙
    private static final String KEY = "a70648d869329dab";
    // 偏移量
    private static final String OFFSET = "0102030405060708";

    /**
     * AES加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static String encrypt(String data) throws Exception {
        // 初始化cipher
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        //转化成JAVA的密钥格式
        SecretKeySpec skeySpec = new SecretKeySpec(KEY.getBytes("ASCII"), ALGORITHM);
        //使用CBC模式,需要一个向量iv,可增加加密算法的强度
        IvParameterSpec iv = new IvParameterSpec(OFFSET.getBytes());
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        byte[] encrypted = cipher.doFinal(data.getBytes(ENCODING));
        //此处使用BASE64做转码。
        String result = new BASE64Encoder().encode(encrypted);
        return result;
    }

    /**
     * AES解密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static String decrypt(String data) throws Exception {
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        SecretKeySpec skeySpec = new SecretKeySpec(KEY.getBytes("ASCII"), ALGORITHM);
        //使用CBC模式,需要一个向量iv,可增加加密算法的强度
        IvParameterSpec iv = new IvParameterSpec(OFFSET.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
        byte[] buffer = new BASE64Decoder().decodeBuffer(data);
        byte[] encrypted = cipher.doFinal(buffer);
        //此处使用BASE64做转码。
        String result = new String(encrypted, ENCODING);
        return result;
    }
}

二、其它基础类

1. BASE64Decoder.java类

package com.sumansoul.aesdemo.utils;

/*
  2    * Copyright (c) 1995, 2000, Oracle and/or its affiliates. All rights reserved.
  3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4    *
  5    * This code is free software; you can redistribute it and/or modify it
  6    * under the terms of the GNU General Public License version 2 only, as
  7    * published by the Free Software Foundation.  Oracle designates this
  8    * particular file as subject to the "Classpath" exception as provided
  9    * by Oracle in the LICENSE file that accompanied this code.
 10    *
 11    * This code is distributed in the hope that it will be useful, but WITHOUT
 12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14    * version 2 for more details (a copy is included in the LICENSE file that
 15    * accompanied this code).
 16    *
 17    * You should have received a copy of the GNU General Public License version
 18    * 2 along with this work; if not, write to the Free Software Foundation,
 19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20    *
 21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22    * or visit www.oracle.com if you need additional information or have any
 23    * questions.
 24    */

import java.io.OutputStream;
import java.io.PushbackInputStream;
import java.io.PrintStream;

/**
 * 32    * This class implements a BASE64 Character decoder as specified in RFC1521.
 * 33    *
 * 34    * This RFC is part of the MIME specification which is published by the
 * 35    * Internet Engineering Task Force (IETF). Unlike some other encoding
 * 36    * schemes there is nothing in this encoding that tells the decoder
 * 37    * where a buffer starts or stops, so to use it you will need to isolate
 * 38    * your encoded data into a single chunk and then feed them this decoder.
 * 39    * The simplest way to do that is to read all of the encoded data into a
 * 40    * string and then use:
 * 41    * <pre>
 * 42    *      byte    mydata[];
 * 43    *      BASE64Decoder base64 = new BASE64Decoder();
 * 44    *
 * 45    *      mydata = base64.decodeBuffer(bufferString);
 * 46    * </pre>
 * 47    * This will decode the String in <i>bufferString</i> and give you an array
 * 48    * of bytes in the array <i>myData</i>.
 * 49    *
 * 50    * On errors, this class throws a CEFormatException with the following detail
 * 51    * strings:
 * 52    * <pre>
 * 53    *    "BASE64Decoder: Not enough bytes for an atom."
 * 54    * </pre>
 * 55    *
 * 56    * @author      Chuck McManis
 * 57    * @see         CharacterEncoder
 * 58    * @see         BASE64Decoder
 * 59
 */

public class BASE64Decoder extends CharacterDecoder {

    /**
     * This class has 4 bytes per atom
     */
    protected int bytesPerAtom() {
        return (4);
    }

    /**
     * Any multiple of 4 will do, 72 might be common
     */
    protected int bytesPerLine() {
        return (72);
    }

    /**
     * 74        * This character array provides the character to value map
     * 75        * based on RFC1521.
     * 76
     */
    private final static char pem_array[] = {
            //       0   1   2   3   4   5   6   7
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0
            'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 1
            'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 2
            'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 3
            'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 4
            'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 5
            'w', 'x', 'y', 'z', '0', '1', '2', '3', // 6
            '4', '5', '6', '7', '8', '9', '+', '/'  // 7
    };

    private final static byte pem_convert_array[] = new byte[256];

    static {
        for (int i = 0; i < 255; i++) {
            pem_convert_array[i] = -1;
        }
        for (int i = 0; i < pem_array.length; i++) {
            pem_convert_array[pem_array[i]] = (byte) i;
        }
    }

    byte decode_buffer[] = new byte[4];

    /**
     * 103        * Decode one BASE64 atom into 1, 2, or 3 bytes of data.
     * 104
     */
    protected void decodeAtom(PushbackInputStream inStream, OutputStream outStream, int rem)
            throws java.io.IOException {
        int i;
        byte a = -1, b = -1, c = -1, d = -1;

        if (rem < 2) {
            throw new CEFormatException("BASE64Decoder: Not enough bytes for an atom.");
        }
        do {
            i = inStream.read();
            if (i == -1) {
                throw new CEStreamExhausted();
            }
        } while (i == '\n' || i == '\r');
        decode_buffer[0] = (byte) i;

        i = readFully(inStream, decode_buffer, 1, rem - 1);
        if (i == -1) {
            throw new CEStreamExhausted();
        }

        if (rem > 3 && decode_buffer[3] == '=') {
            rem = 3;
        }
        if (rem > 2 && decode_buffer[2] == '=') {
            rem = 2;
        }
        switch (rem) {
            case 4:
                d = pem_convert_array[decode_buffer[3] & 0xff];
                // NOBREAK
            case 3:
                c = pem_convert_array[decode_buffer[2] & 0xff];
                // NOBREAK
            case 2:
                b = pem_convert_array[decode_buffer[1] & 0xff];
                a = pem_convert_array[decode_buffer[0] & 0xff];
                break;
        }

        switch (rem) {
            case 2:
                outStream.write((byte) (((a << 2) & 0xfc) | ((b >>> 4) & 3)));
                break;
            case 3:
                outStream.write((byte) (((a << 2) & 0xfc) | ((b >>> 4) & 3)));
                outStream.write((byte) (((b << 4) & 0xf0) | ((c >>> 2) & 0xf)));
                break;
            case 4:
                outStream.write((byte) (((a << 2) & 0xfc) | ((b >>> 4) & 3)));
                outStream.write((byte) (((b << 4) & 0xf0) | ((c >>> 2) & 0xf)));
                outStream.write((byte) (((c << 6) & 0xc0) | (d & 0x3f)));
                break;
        }
        return;
    }
}

2. BASE64Encoder.java类

package com.sumansoul.aesdemo.utils;

/*
   2    * Copyright (c) 1995, 1997, Oracle and/or its affiliates. All rights reserved.
   3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4    *
   5    * This code is free software; you can redistribute it and/or modify it
   6    * under the terms of the GNU General Public License version 2 only, as
   7    * published by the Free Software Foundation.  Oracle designates this
   8    * particular file as subject to the "Classpath" exception as provided
   9    * by Oracle in the LICENSE file that accompanied this code.
  10    *
  11    * This code is distributed in the hope that it will be useful, but WITHOUT
  12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14    * version 2 for more details (a copy is included in the LICENSE file that
  15    * accompanied this code).
  16    *
  17    * You should have received a copy of the GNU General Public License version
  18    * 2 along with this work; if not, write to the Free Software Foundation,
  19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20    *
  21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22    * or visit www.oracle.com if you need additional information or have any
  23    * questions.
  24    */

import java.io.OutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.IOException;

/**
 * This class implements a BASE64 Character encoder as specified in RFC1521.
 * This RFC is part of the MIME specification as published by the Internet
 * Engineering Task Force (IETF). Unlike some other encoding schemes there is
 * nothing in this encoding that indicates where a buffer starts or ends.
 * <p>
 * This means that the encoded text will simply start with the first line of
 * encoded text and end with the last line of encoded text.
 *
 * @author Chuck McManis
 * @see CharacterEncoder
 * @see BASE64Decoder
 */
public class BASE64Encoder extends CharacterEncoder {

    /**
     * this class encodes three bytes per atom.
     */
    protected int bytesPerAtom() {
        return (3);
    }

    /**
     * this class encodes 57 bytes per line. This results in a maximum of 57/3 *
     * 4 or 76 characters per output line. Not counting the line termination.
     */
    protected int bytesPerLine() {
        return (57);
    }

    /**
     * This array maps the characters to their 6 bit values
     */
    private final static char pem_array[] =
            {
                    // 0 1 2 3 4 5 6 7
                    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0
                    'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 1
                    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 2
                    'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 3
                    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 4
                    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 5
                    'w', 'x', 'y', 'z', '0', '1', '2', '3', // 6
                    '4', '5', '6', '7', '8', '9', '+', '/' // 7
            };

    /**
     * encodeAtom - Take three bytes of input and encode it as 4 printable
     * characters. Note that if the length in len is less than three is encodes
     * either one or two '=' signs to indicate padding characters.
     */
    protected void encodeAtom(OutputStream outStream, byte data[], int offset,
                              int len) throws IOException {
        byte a, b, c;
        if (len == 1) {
            a = data[offset];
            b = 0;
            c = 0;
            outStream.write(pem_array[(a >>> 2) & 0x3F]);
            outStream.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
            outStream.write('=');
            outStream.write('=');
        } else if (len == 2) {
            a = data[offset];
            b = data[offset + 1];
            c = 0;
            outStream.write(pem_array[(a >>> 2) & 0x3F]);
            outStream.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
            outStream.write(pem_array[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]);
            outStream.write('=');
        } else {
            a = data[offset];
            b = data[offset + 1];
            c = data[offset + 2];
            outStream.write(pem_array[(a >>> 2) & 0x3F]);
            outStream.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
            outStream.write(pem_array[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]);
            outStream.write(pem_array[c & 0x3F]);
        }
    }
}

3. CEFormatException.java类

package com.sumansoul.aesdemo.utils;

import java.io.IOException;

public class CEFormatException extends IOException
{
    public CEFormatException(String s)
    {
        super(s);
    }
}

4. CEStreamExhausted.java类

package com.sumansoul.aesdemo.utils;

import java.io.IOException;

public class CEStreamExhausted extends IOException
{

}

5. CharacterDecoder.java类

package com.sumansoul.aesdemo.utils;

/*
    2    * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */


import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * 37 * This class defines the decoding half of character encoders. 38 * A
 * character decoder is an algorithim for transforming 8 bit 39 * binary data
 * that has been encoded into text by a character 40 * encoder, back into
 * original binary form. 41 * 42 * The character encoders, in general, have been
 * structured 43 * around a central theme that binary data can be encoded into
 * 44 * text that has the form: 45 * 46 *
 *
 * <pre>
 *    47    *      [Buffer Prefix]
 *    48    *      [Line Prefix][encoded data atoms][Line Suffix]
 *    49    *      [Buffer Suffix]
 *    50    *
 * </pre>
 * <p>
 * 51 * 52 * Of course in the simplest encoding schemes, the buffer has no 53 *
 * distinct prefix of suffix, however all have some fixed relationship 54 *
 * between the text in an 'atom' and the binary data itself. 55 * 56 * In the
 * CharacterEncoder and CharacterDecoder classes, one complete 57 * chunk of
 * data is referred to as a <i>buffer</i>. Encoded buffers 58 * are all text,
 * and decoded buffers (sometimes just referred to as 59 * buffers) are binary
 * octets. 60 * 61 * To create a custom decoder, you must, at a minimum, overide
 * three 62 * abstract methods in this class. 63 *
 * <DL>
 * 64 *
 * <DD>bytesPerAtom which tells the decoder how many bytes to 65 * expect from
 * decodeAtom 66 *
 * <DD>decodeAtom which decodes the bytes sent to it as text. 67 *
 * <DD>bytesPerLine which tells the encoder the maximum number of 68 * bytes per
 * line. 69 *
 * </DL>
 * 70 * 71 * In general, the character decoders return error in the form of a 72
 * * CEFormatException. The syntax of the detail string is 73 *
 *
 * <pre>
 *    74    *      DecoderClassName: Error message.
 *    75    *
 * </pre>
 * <p>
 * 76 * 77 * Several useful decoders have already been written and are 78 *
 * referenced in the See Also list below. 79 * 80 * @author Chuck McManis 81 * @see
 * CEFormatException 82 * @see CharacterEncoder 83 * @see UCDecoder 84 * @see
 * UUDecoder 85 * @see BASE64Decoder 86
 */

public abstract class CharacterDecoder {

    /**
     * Return the number of bytes per atom of decoding
     */
    abstract protected int bytesPerAtom();

    /**
     * Return the maximum number of bytes that can be encoded per line
     */
    abstract protected int bytesPerLine();

    /**
     * decode the beginning of the buffer, by default this is a NOP.
     */
    protected void decodeBufferPrefix(PushbackInputStream aStream,
                                      OutputStream bStream) throws IOException {
    }

    /**
     * decode the buffer suffix, again by default it is a NOP.
     */
    protected void decodeBufferSuffix(PushbackInputStream aStream,
                                      OutputStream bStream) throws IOException {
    }

    /**
     * 103 * This method should return, if it knows, the number of bytes 104 *
     * that will be decoded. Many formats such as uuencoding provide 105 * this
     * information. By default we return the maximum bytes that 106 * could have
     * been encoded on the line. 107
     */
    protected int decodeLinePrefix(PushbackInputStream aStream,
                                   OutputStream bStream) throws IOException {
        return (bytesPerLine());
    }

    /**
     * 113 * This method post processes the line, if there are error detection
     * 114 * or correction codes in a line, they are generally processed by 115
     * * this method. The simplest version of this method looks for the 116 *
     * (newline) character. 117
     */
    protected void decodeLineSuffix(PushbackInputStream aStream,
                                    OutputStream bStream) throws IOException {
    }

    /**
     * 121 * This method does an actual decode. It takes the decoded bytes and
     * 122 * writes them to the OutputStream. The integer <i>l</i> tells the 123
     * * method how many bytes are required. This is always <= bytesPerAtom().
     * 124
     */
    protected void decodeAtom(PushbackInputStream aStream,
                              OutputStream bStream, int l) throws IOException {
        throw new CEStreamExhausted();
    }

    /**
     * 130 * This method works around the bizarre semantics of
     * BufferedInputStream's 131 * read method. 132
     */
    protected int readFully(InputStream in, byte buffer[], int offset, int len)
            throws IOException {
        for (int i = 0; i < len; i++) {
            int q = in.read();
            if (q == -1)
                return ((i == 0) ? -1 : i);
            buffer[i + offset] = (byte) q;
        }
        return len;
    }

    /**
     * 145 * Decode the text from the InputStream and write the decoded 146 *
     * octets to the OutputStream. This method runs until the stream 147 * is
     * exhausted. 148 * @exception CEFormatException An error has occured while
     * decoding 149 * @exception CEStreamExhausted The input stream is
     * unexpectedly out of data 150
     */
    public void decodeBuffer(InputStream aStream, OutputStream bStream)
            throws IOException {
        int i;
        int totalBytes = 0;

        PushbackInputStream ps = new PushbackInputStream(aStream);
        decodeBufferPrefix(ps, bStream);
        while (true) {
            int length;

            try {
                length = decodeLinePrefix(ps, bStream);
                for (i = 0; (i + bytesPerAtom()) < length; i += bytesPerAtom()) {
                    decodeAtom(ps, bStream, bytesPerAtom());
                    totalBytes += bytesPerAtom();
                }
                if ((i + bytesPerAtom()) == length) {
                    decodeAtom(ps, bStream, bytesPerAtom());
                    totalBytes += bytesPerAtom();
                } else {
                    decodeAtom(ps, bStream, length - i);
                    totalBytes += (length - i);
                }
                decodeLineSuffix(ps, bStream);
            } catch (CEStreamExhausted e) {
                break;
            }
        }
        decodeBufferSuffix(ps, bStream);
    }

    /**
     * 182 * Alternate decode interface that takes a String containing the
     * encoded 183 * buffer and returns a byte array containing the data. 184 * @exception
     * CEFormatException An error has occured while decoding 185
     */
    public byte decodeBuffer(String inputString)[]throws IOException {
        byte inputBuffer[] = new byte[inputString.length()];
        ByteArrayInputStream inStream;
        ByteArrayOutputStream outStream;

        inputString.getBytes(0, inputString.length(), inputBuffer, 0);
        inStream = new ByteArrayInputStream(inputBuffer);
        outStream = new ByteArrayOutputStream();
        decodeBuffer(inStream, outStream);
        return (outStream.toByteArray());
    }

    /**
     * 199 * Decode the contents of the inputstream into a buffer. 200
     */
    public byte decodeBuffer(InputStream in)[]throws IOException {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        decodeBuffer(in, outStream);
        return (outStream.toByteArray());
    }

    /**
     * 208 * Decode the contents of the String into a ByteBuffer. 209
     */
    public ByteBuffer decodeBufferToByteBuffer(String inputString)
            throws IOException {
        return ByteBuffer.wrap(decodeBuffer(inputString));
    }

    /**
     * 216 * Decode the contents of the inputStream into a ByteBuffer. 217
     */
    public ByteBuffer decodeBufferToByteBuffer(InputStream in)
            throws IOException {
        return ByteBuffer.wrap(decodeBuffer(in));
    }
}

6. CharacterEncoder.java类

package com.sumansoul.aesdemo.utils;

/*
    2    * Copyright (c) 1995, 2005, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */

import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * 38 * This class defines the encoding half of character encoders. 39 * A
 * character encoder is an algorithim for transforming 8 bit binary 40 * data
 * into text (generally 7 bit ASCII or 8 bit ISO-Latin-1 text) 41 * for
 * transmition over text channels such as e-mail and network news. 42 * 43 * The
 * character encoders have been structured around a central theme 44 * that, in
 * general, the encoded text has the form: 45 * 46 *
 *
 * <pre>
 *    47    *      [Buffer Prefix]
 *    48    *      [Line Prefix][encoded data atoms][Line Suffix]
 *    49    *      [Buffer Suffix]
 *    50    *
 * </pre>
 * <p>
 * 51 * 52 * In the CharacterEncoder and CharacterDecoder classes, one complete
 * 53 * chunk of data is referred to as a <i>buffer</i>. Encoded buffers 54 *
 * are all text, and decoded buffers (sometimes just referred to as 55 *
 * buffers) are binary octets. 56 * 57 * To create a custom encoder, you must,
 * at a minimum, overide three 58 * abstract methods in this class. 59 *
 * <DL>
 * 60 *
 * <DD>bytesPerAtom which tells the encoder how many bytes to 61 * send to
 * encodeAtom 62 *
 * <DD>encodeAtom which encodes the bytes sent to it as text. 63 *
 * <DD>bytesPerLine which tells the encoder the maximum number of 64 * bytes per
 * line. 65 *
 * </DL>
 * 66 * 67 * Several useful encoders have already been written and are 68 *
 * referenced in the See Also list below. 69 * 70 * @author Chuck McManis 71 * @see
 * CharacterDecoder; 72 * @see UCEncoder 73 * @see UUEncoder 74 * @see
 * BASE64Encoder 75
 */
public abstract class CharacterEncoder {
    /**
     * Stream that understands "printing"
     */
    protected PrintStream pStream;

    /**
     * Return the number of bytes per atom of encoding
     */
    abstract protected int bytesPerAtom();

    /**
     * Return the number of bytes that can be encoded per line
     */
    abstract protected int bytesPerLine();

    /**
     * 88 * Encode the prefix for the entire buffer. By default is simply 89 *
     * opens the PrintStream for use by the other functions. 90
     */
    protected void encodeBufferPrefix(OutputStream aStream) throws IOException {
        pStream = new PrintStream(aStream);
    }

    /**
     * 96 * Encode the suffix for the entire buffer. 97
     */
    protected void encodeBufferSuffix(OutputStream aStream) throws IOException {
    }

    /**
     * 102 * Encode the prefix that starts every output line. 103
     */
    protected void encodeLinePrefix(OutputStream aStream, int aLength)
            throws IOException {
    }

    /**
     * 109 * Encode the suffix that ends every output line. By default 110 *
     * this method just prints a <newline> into the output stream. 111
     */
    protected void encodeLineSuffix(OutputStream aStream) throws IOException {
        pStream.println();
    }

    /**
     * Encode one "atom" of information into characters.
     */
    abstract protected void encodeAtom(OutputStream aStream, byte someBytes[],
                                       int anOffset, int aLength) throws IOException;

    /**
     * 121 * This method works around the bizarre semantics of
     * BufferedInputStream's 122 * read method. 123
     */
    protected int readFully(InputStream in, byte buffer[])
            throws IOException {
        for (int i = 0; i < buffer.length; i++) {
            int q = in.read();
            if (q == -1)
                return i;
            buffer[i] = (byte) q;
        }
        return buffer.length;
    }

    /**
     * 136 * Encode bytes from the input stream, and write them as text
     * characters 137 * to the output stream. This method will run until it
     * exhausts the 138 * input stream, but does not print the line suffix for a
     * final 139 * line that is shorter than bytesPerLine(). 140
     */
    public void encode(InputStream inStream, OutputStream outStream)
            throws IOException {
        int j;
        int numBytes;
        byte tmpbuffer[] = new byte[bytesPerLine()];

        encodeBufferPrefix(outStream);

        while (true) {
            numBytes = readFully(inStream, tmpbuffer);
            if (numBytes == 0) {
                break;
            }
            encodeLinePrefix(outStream, numBytes);
            for (j = 0; j < numBytes; j += bytesPerAtom()) {

                if ((j + bytesPerAtom()) <= numBytes) {
                    encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
                } else {
                    encodeAtom(outStream, tmpbuffer, j, (numBytes) - j);
                }
            }
            if (numBytes < bytesPerLine()) {
                break;
            } else {
                encodeLineSuffix(outStream);
            }
        }
        encodeBufferSuffix(outStream);
    }

    /**
     * 173 * Encode the buffer in <i>aBuffer</i> and write the encoded 174 *
     * result to the OutputStream <i>aStream</i>. 175
     */
    public void encode(byte aBuffer[], OutputStream aStream) throws IOException {
        ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
        encode(inStream, aStream);
    }

    /**
     * 183 * A 'streamless' version of encode that simply takes a buffer of 184
     * * bytes and returns a string containing the encoded buffer. 185
     */
    public String encode(byte aBuffer[]) {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
        String retVal = null;
        try {
            encode(inStream, outStream);
            // explicit ascii->unicode conversion
            retVal = outStream.toString("8859_1");
        } catch (Exception IOException) {
            // This should never happen.
            throw new Error("CharacterEncoder.encode internal error");
        }
        return (retVal);
    }

    /**
     * 202 * Return a byte array from the remaining bytes in this ByteBuffer.
     * 203 *
     * <p>
     * 204 * The ByteBuffer's position will be advanced to ByteBuffer's limit.
     * 205 *
     * <p>
     * 206 * To avoid an extra copy, the implementation will attempt to return
     * the 207 * byte array backing the ByteBuffer. If this is not possible, a
     * 208 * new byte array will be created. 209
     */
    private byte[] getBytes(ByteBuffer bb) {
        /*
         * This should never return a BufferOverflowException, as we're 213 *
         * careful to allocate just the right amount. 214
         */
        byte[] buf = null;

        /*
         * 218 * If it has a usable backing byte buffer, use it. Use only 219 *
         * if the array exactly represents the current ByteBuffer. 220
         */
        if (bb.hasArray()) {
            byte[] tmp = bb.array();
            if ((tmp.length == bb.capacity()) && (tmp.length == bb.remaining())) {
                buf = tmp;
                bb.position(bb.limit());
            }
        }

        if (buf == null) {
            /*
             * 232 * This class doesn't have a concept of encode(buf, len, off),
             * 233 * so if we have a partial buffer, we must reallocate 234 *
             * space. 235
             */
            buf = new byte[bb.remaining()];

            /*
             * 239 * position() automatically updated 240
             */
            bb.get(buf);
        }

        return buf;
    }

    /**
     * 248 * Encode the <i>aBuffer</i> ByteBuffer and write the encoded 249 *
     * result to the OutputStream <i>aStream</i>. 250 *
     * <p>
     * 251 * The ByteBuffer's position will be advanced to ByteBuffer's limit.
     * 252
     */
    public void encode(ByteBuffer aBuffer, OutputStream aStream)
            throws IOException {
        byte[] buf = getBytes(aBuffer);
        encode(buf, aStream);
    }

    /**
     * 260 * A 'streamless' version of encode that simply takes a ByteBuffer 261
     * * and returns a string containing the encoded buffer. 262 *
     * <p>
     * 263 * The ByteBuffer's position will be advanced to ByteBuffer's limit.
     * 264
     */
    public String encode(ByteBuffer aBuffer) {
        byte[] buf = getBytes(aBuffer);
        return encode(buf);
    }

    /**
     * 271 * Encode bytes from the input stream, and write them as text
     * characters 272 * to the output stream. This method will run until it
     * exhausts the 273 * input stream. It differs from encode in that it will
     * add the 274 * line at the end of a final line that is shorter than
     * bytesPerLine(). 275
     */
    public void encodeBuffer(InputStream inStream, OutputStream outStream)
            throws IOException {
        int j;
        int numBytes;
        byte tmpbuffer[] = new byte[bytesPerLine()];

        encodeBufferPrefix(outStream);

        while (true) {
            numBytes = readFully(inStream, tmpbuffer);
            if (numBytes == 0) {
                break;
            }
            encodeLinePrefix(outStream, numBytes);
            for (j = 0; j < numBytes; j += bytesPerAtom()) {
                if ((j + bytesPerAtom()) <= numBytes) {
                    encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
                } else {
                    encodeAtom(outStream, tmpbuffer, j, (numBytes) - j);
                }
            }
            encodeLineSuffix(outStream);
            if (numBytes < bytesPerLine()) {
                break;
            }
        }
        encodeBufferSuffix(outStream);
    }

    /**
     * 306 * Encode the buffer in <i>aBuffer</i> and write the encoded 307 *
     * result to the OutputStream <i>aStream</i>. 308
     */
    public void encodeBuffer(byte aBuffer[], OutputStream aStream)
            throws IOException {
        ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
        encodeBuffer(inStream, aStream);
    }

    /**
     * 316 * A 'streamless' version of encode that simply takes a buffer of 317
     * * bytes and returns a string containing the encoded buffer. 318
     */
    public String encodeBuffer(byte aBuffer[]) {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
        try {
            encodeBuffer(inStream, outStream);
        } catch (Exception IOException) {
            // This should never happen.
            throw new Error("CharacterEncoder.encodeBuffer internal error");
        }
        return (outStream.toString());
    }

    /**
     * 332 * Encode the <i>aBuffer</i> ByteBuffer and write the encoded 333 *
     * result to the OutputStream <i>aStream</i>. 334 *
     * <p>
     * 335 * The ByteBuffer's position will be advanced to ByteBuffer's limit.
     * 336
     */
    public void encodeBuffer(ByteBuffer aBuffer, OutputStream aStream)
            throws IOException {
        byte[] buf = getBytes(aBuffer);
        encodeBuffer(buf, aStream);
    }

    /**
     * 344 * A 'streamless' version of encode that simply takes a ByteBuffer 345
     * * and returns a string containing the encoded buffer. 346 *
     * <p>
     * 347 * The ByteBuffer's position will be advanced to ByteBuffer's limit.
     * 348
     */
    public String encodeBuffer(ByteBuffer aBuffer) {
        byte[] buf = getBytes(aBuffer);
        return encodeBuffer(buf);
    }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343