Base64的加密和解密

Base64加密的方法是:将字节(bytes)序列转换为字符(character)序列,每3个字节转换为4个字符(3 * 8 = 4 * 6),像这样:|11111122|22223333|33444444| >> |00111111|00222222|00333333|00444444|,不足三个字节的用'='填充,所以最后的字符序列数一定是4的倍数。解密就是加密的逆过程咯!

 

下面的Java代码有三种实现方式:

Simple:最简单直接的实现方法;

Grace:比较优雅的实现方法;

Official:JDK自带的实现方法;

 

首先定义接口:

 

package com.hp.it.mossad.algorithms.base64;

public interface IBase64 {
	String encode(byte[] code);

	String decode(char[] code);
}
 

然后是实现类:

 

package com.hp.it.mossad.algorithms.base64;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.InvalidParameterException;

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

public enum Base64Type {
	
	GRACE(new IBase64() {
		public String encode(byte[] data) {
			int length = (int)Math.ceil(data.length / 3.0) * 4;
			char[] out = new char[length];
			for (int i = 0, j = 0; i < data.length ; i += 3, j += 4) {
				boolean quad = false;
				boolean trip = false;
				int val = 0xff & data[i];
				val <<= 8;
				if (i + 1 < data.length) {
					val |= 0xff & data[i + 1];
					trip = true;
				}
				val <<= 8;
				if (i + 2 < data.length) {
					val |= 0xff & data[i + 2];
					quad = true;
				}
				out[j + 3] = alphabet[quad ? (0x3f & val) : 64];
				val >>= 6;
				out[j + 2] = alphabet[trip ? (0x3f & val) : 64];
				val >>= 6;
				out[j + 1] = alphabet[0x3f & val];
				val >>= 6;
				out[j] = alphabet[0x3f & val];
			}
			return new String(out);
		}
		
		public String decode(char[] data) {
			if (data.length % 4 != 0) throw new InvalidParameterException("Invalid length of array : " + data.length);
			int length = data.length / 4 * 3;
			if (data.length > 0 && data[data.length - 1] == '=') length--;
			if (data.length > 1 && data[data.length - 2] == '=') length--;
			byte[] out = new byte[length];
			int shift = 0;
			int valley = 0x00;
			int index = 0;
			for (int i = 0; i < data.length; i++) {
				int value = codes[data[i]];
				if (value >= 0) {
					valley <<= 6;
					valley |= value;
					shift += 6;
					if (shift >= 8) {
						shift -= 8;
						out[index++] = (byte)((valley >> shift) & 0xff);
					}
				}
			}
			return new String(out);
		}
	}),
	
	SIMPLE(new IBase64() {
		public String encode(byte[] bs) {
			int count = bs.length / 3;
			int rm = bs.length % 3;
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			for (int i = 0; i < count; i++) {
				int index = i * 3;
				baos.write(alphabet[(bs[index] & 0xfc) >> 2]);
				baos.write(alphabet[((bs[index] & 0x03) << 4 | (bs[index + 1] & 0xf0) >> 4)]);
				baos.write(alphabet[(bs[index + 1] & 0x0f) << 2 | (bs[index + 2] & 0xc0) >> 6]);
				baos.write(alphabet[bs[index + 2] & 0x3f]);
			}
			if (rm == 1) {
				baos.write(alphabet[(bs[bs.length - 1] & 0xfc) >> 2]);
				baos.write(alphabet[(bs[bs.length - 1] & 0x03) << 4]);
				baos.write('=');
				baos.write('=');
			} else if (rm == 2) {
				baos.write(alphabet[(bs[bs.length - 2] & 0xfc) >> 2]);
				baos.write(alphabet[(bs[bs.length - 2] & 0x03) << 4 | (bs[bs.length - 1] & 0xf0) >> 4]);
				baos.write(alphabet[(bs[bs.length - 1] & 0x0f) << 2]);
				baos.write('=');
			}
			return baos.toString();
		}
		
		public String decode(char[] data) {
			if (data.length % 4 != 0) throw new InvalidParameterException("The lengh is invalid!");
			int count = data.length / 4;
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			for (int i = 0; i < count - 1; i++) {
				int index = i * 4;
				baos.write((codes[data[index]] & 0x3f) << 2 | (codes[data[index + 1]] & 0x30) >> 4);
				baos.write((codes[data[index + 1]] & 0x0f) << 4 | (codes[data[index + 2]] & 0x3c) >> 2);
				baos.write((codes[data[index + 2]] & 0x03) << 6 | codes[data[index + 3]] & 0x3f);
			}
			if (data[data.length - 2] == '=') {
				baos.write((codes[data[data.length - 4]] & 0x3f) << 2 | ((codes[data[data.length - 3]] & 0x30) >> 4));
			} else if (data[data.length - 1] == '=') {
				baos.write((codes[data[data.length - 4]] & 0x3f) << 2 | ((codes[data[data.length - 3]] & 0x30) >> 4));
				baos.write((codes[data[data.length - 3]] & 0x0f) << 4 | ((codes[data[data.length - 2]] & 0x3c)) >> 2);
			}
			return baos.toString();
		}
	}),
	
	OFFICIAL(new IBase64() {

		@Override
		public String encode(byte[] code) {
			return encoder.encode(code);
		}

		@Override
		public String decode(char[] code) {
			try {
				return new String(decoder.decodeBuffer(new String(code)));
			} catch (IOException e) {
				e.printStackTrace();
			}
			return null;
		}
		
		private BASE64Encoder encoder = new BASE64Encoder();
		private BASE64Decoder decoder = new BASE64Decoder();
	});
	
	private Base64Type(IBase64 ib) {
		this.ib = ib;
	}
	
	private IBase64 ib;
	
	public String encode(byte[] code) {
		return this.ib.encode(code);
	}
	
	public String decode(char[] code) {
		return this.ib.decode(code);
	}
	
	private static char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray();
	private static byte[] codes = new byte[128];
	static {
		for (int i = 0; i < codes.length; i++) {
			codes[i] = -1;
		}
		for (int i = 'A'; i <= 'Z'; i++) {
			codes[i] = (byte)(i - 'A');
		}
		for (int i = 'a'; i <= 'z'; i++) {
			codes[i] = (byte)(26 + i - 'a');
		}
		for (int i = '0'; i <= '9'; i++) {
			codes[i] = (byte)(52 + i - '0');
		}
		codes['+'] = 62;
		codes['/'] = 63;
	}
}

  最后是测试类:

 

package com.hp.it.mossad.algorithms.base64;

import org.junit.Test;

public class Base64Test {
	
	@Test
	public void grace() {
		test(Base64Type.GRACE);
	}
	
	@Test
	public void simple() {
		test(Base64Type.SIMPLE);
	}
	
	@Test
	public void official() {
		test(Base64Type.OFFICIAL);
	}
	
	private void test(Base64Type type) {
		String s = "Keep calm and carry on.";
		String encode = type.encode(s.getBytes());
		String decode = type.decode(encode.toCharArray());
		System.out.println(type.name() + " : " + s.equals(decode));
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值