/**
?*
?*/
package com.newegg.lab.framework.security;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import com.newegg.lab.framework.exception.EncodingException;
import com.newegg.lab.framework.util.StringPoolConstant;
import com.newegg.lab.framework.util.Validator;
/**
?*
?* @Discription 字符串的(編碼/加密)與(解碼/解密)
?*
?* 規(guī)則:
?*
?* 在Base64中,碼表是由[A-Z,a-z,0-9,+,/,=(pad)]組成的。
?* 而在這里,碼表由[a-z,2-7] abcdefghijklmnopqrstuvwxyz234567 組成的:
?* -----------------------------------------------
?* a b c d e f g h i j k? l? m? n? o? p? q? r
?* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
?* -----------------------------------------------
?*? s? t? u? v? w? x? y? z? 2? 3? 4? 5? 6? 7
?* 18 19 20 21 22 23 24 25 26 27 28 29 30 31
?* ------------------------------------------------
?*
?* 在Base64中,是將二進(jìn)制連成一串,然后再按6位來分割,分割完后在前面補(bǔ)0,這個(gè)地球人都知道,不多說了。
?* 而在這里,在分割的那一步稍微有變動(dòng),是按5位來分割,如果剛好夠分,那就好了,如果不夠,那咋辦呢?
?*
?* 在Base64中,是用"="來解決的吧。
?* 而在這里,就是在前面補(bǔ)0,然后在后面再補(bǔ)零。
?*
?* 例如:字符串 "aaa",(編碼/加密)后是 "mfqwc"
?*
?* 二進(jìn)制:01100001 01100001 01100001
?* 轉(zhuǎn)換后:(000)01100 (000)00101 (000)10000 (000)10110 (000)0001(0)
?* 十進(jìn)制:??? 12????????? 5????????? 16???????? 22????????? 2
?* 碼表對(duì)應(yīng):?? m?????????? f????????? q????????? w?????????? c
?*
?* (解碼/解密)就更簡(jiǎn)單了:
?*
?* 碼表對(duì)應(yīng):??? m?????? f??????? q??????? w?????? c
?* 十進(jìn)制:???? 12?????? 5?????? 16?????? 22?????? 2
?* 二進(jìn)制: 00001100 00000101 00010000 00010110 00000010
?* 去前0后:01100 00101 10000 10110 00010
?* 合并后: 0110000101100001011000010
?*
?* 然后把合并后的串的長(zhǎng)度除一下8,發(fā)現(xiàn)多了個(gè)0:
?*
?* 二進(jìn)制:01100001 01100001 01100001 0
?*
?* 多了就算了,不要了(其實(shí)是在{編碼/加密}的分割時(shí)候,在分剩的余數(shù)的后面補(bǔ)的0)。
?* 然后再將 byte[] 轉(zhuǎn)回字符串,OK!又見"aaa"了。
?*
?* 有一點(diǎn)值得注意的,UTF-8、GBK、GB18030 一般都沒什么問題,
?* 但是 GB2312 可能字符集不夠豐富,繁體字在decrypt的時(shí)候成問號(hào)了
?*
?* @Company 新蛋信息技術(shù)(西安)有限公司
?*
?* @Author Terry.B.Li
?*
?* @CreateDate 2009-2-4 下午02:47:32
?*
?* @Version V0.5
?*
?*/
public class EncryptDecrypt {
?? ?/**
?? ? * 碼表 [a-n,q-z,0-4,6-7,9]
?? ? */
?? ?private static final String CODEC_TABLE = "abcdefghijklmnqrstuvwxyz01234679";
?? ?/**
?? ? * 表示5bit的字節(jié)
?? ? */
?? ?public final static int FIVE_BIT = 5;
?? ?/**
?? ? * 表示8bit的字節(jié)
?? ? */
?? ?public final static int EIGHT_BIT = 8;
?? ?/**
?? ? * 表示二進(jìn)制
?? ? */
?? ?public final static int BINARY = 2;
?? ?/**
?? ? * (編碼/加密)字符串,采用默認(rèn)語言環(huán)境的 character set
?? ? * @param str?? ?需要(編碼/加密)的字符串
?? ? * @return?? ??? ?(編碼/加密)后的字符串
?? ? * @throws EncodingException
?? ? */
?? ?public static String encrypt(String str) throws EncodingException{
?? ??? ?return encrypt(str,null);
?? ?}
?? ?/**
?? ? * (編碼/加密)字符串
?? ? * @param str?? ??? ??? ?需要(編碼/加密)的字符串
?? ? * @param characterSet?? ?字符集
?? ? * @return?? ??? ??? ??? ?(編碼/加密)后的字符串
?? ? * @throws EncodingException
?? ? */
?? ?public static String encrypt(String str,String characterSet) throws EncodingException{
?? ??? ?if (Validator.isNull(str)) {
?? ??? ??? ?return StringPoolConstant.BLANK;
?? ??? ?}
?? ??? ?byte[] keyBytes = null;
?? ??? ?try {
?? ??? ??? ?if (Validator.isNotNull(characterSet)) {
?? ??? ??? ??? ?keyBytes = str.getBytes(characterSet);
?? ??? ??? ?}else{
?? ??? ??? ??? ?keyBytes = str.getBytes();
?? ??? ??? ?}
?? ??? ?} catch (UnsupportedEncodingException e) {
?? ??? ??? ?throw new EncodingException(e);
?? ??? ?}
?? ??? ?return encrypt(keyBytes);
?? ?}
?? ?/**
?? ? * (編碼/加密)字節(jié)數(shù)組
?? ? * @param bytes?? ?需要(編碼/加密)的字節(jié)數(shù)組
?? ? * @return?? ??? ?(編碼/加密)后的字符串
?? ? */
?? ?private static String encrypt(byte[] keyBytes){
?? ??? ?if (Validator.isNull(keyBytes) || keyBytes.length < 1) {
?? ??? ??? ?return StringPoolConstant.BLANK;
?? ??? ?}
?? ??? ?/*
?? ??? ? * 合并二進(jìn)制碼,
?? ??? ? * 如:
?? ??? ? *???? 00101010 11010011 00101101 10100011
?? ??? ? *?? to
?? ??? ? *???? 00101010110100110010110110100011
?? ??? ? */
?? ??? ?StringBuilder mergrd = new StringBuilder();
?? ??? ?for (int i = 0; i < keyBytes.length; i++) {
?? ??? ??? ?FormatUtil.formatBinary(keyBytes[i], mergrd);
?? ??? ?}
?? ??? ?/*
?? ??? ? * 以5個(gè)bit為單位,計(jì)算能分多少組,
?? ??? ? * 如:
???????? *???? 00101010110100110010110110100011
?? ??? ? *?? to
?? ??? ? *???? 00101 01011 01001 10010 11011 01000 11
?? ??? ? *????????????????????????????????????????? |
?? ??? ? *?????????????????????????????????? (這個(gè)11為余下的位)
?? ??? ? */
?? ??? ?int groupCount = mergrd.length() / FIVE_BIT;
?? ??? ?// 計(jì)算余下的位數(shù)
?? ??? ?int lastCount = mergrd.length() % FIVE_BIT;
?? ??? ?// 類似數(shù)據(jù)分頁的算法,有余數(shù)的情況下需要加 1。
?? ??? ?if (lastCount > 0) {
?? ??? ??? ?groupCount += 1;
?? ??? ?}
?? ??? ?/*
?? ??? ? * (編碼/加密)
?? ??? ? */
?? ??? ?StringBuilder sbencryptd = new StringBuilder();
?? ??? ?// 循環(huán)所需的條件
?? ??? ?int forMax = groupCount * FIVE_BIT;
?? ??? ?// 每次遞增5位來截取
?? ??? ?for (int i = 0; i < forMax; i += FIVE_BIT) {
?? ??? ??? ?// 結(jié)束點(diǎn)
?? ??? ??? ?int end = i + FIVE_BIT;
?? ??? ??? ?/*
?? ??? ??? ? * 如果結(jié)束點(diǎn)比已合并的二進(jìn)制碼串的長(zhǎng)度要大,
?? ??? ??? ? * 相當(dāng)于有余數(shù),
???????????? * 并且表示當(dāng)前循環(huán)到了(已合并的二進(jìn)制碼串的長(zhǎng)度 % FIVE_BIT)的那一截。
?? ??? ??? ? */
?? ??? ??? ?// 標(biāo)記是否到了余數(shù)的那一截
?? ??? ??? ?boolean flag = false;
?? ??? ??? ?if (end > mergrd.length()) {
?? ??? ??? ??? ?/*
?? ??? ??? ??? ? * 如果結(jié)束點(diǎn)比已合并的二進(jìn)制碼串的長(zhǎng)度要大,
?? ??? ??? ??? ? * 結(jié)束點(diǎn)需要被重設(shè)為:
?? ??? ??? ??? ? * 已合并的二進(jìn)制碼串的長(zhǎng)度,等價(jià)于(i + lastCount). 并且重設(shè)標(biāo)記。
?? ??? ??? ??? ? */
?? ??? ??? ??? ?end = (i + lastCount);
?? ??? ??? ??? ?flag = true;
?? ??? ??? ?}
?? ??? ??? ?// 截取
?? ??? ??? ?String strFiveBit = mergrd.substring(i, end);
?? ??? ??? ?// 截取后從二進(jìn)制轉(zhuǎn)為十進(jìn)制
?? ??? ??? ?int intFiveBit = Integer.parseInt(strFiveBit, BINARY);
?? ??? ??? ?if (flag) {
?? ??? ??? ??? ?/*
?? ??? ??? ??? ? * 如果結(jié)束點(diǎn)比已合并的二進(jìn)制碼串的長(zhǎng)度要大,
?? ??? ??? ??? ? * 或者是到了余數(shù)的那一截:
?? ??? ??? ??? ? * 需要左移操作,假設(shè)余下的二進(jìn)制位為:11,
?? ??? ??? ??? ? * 那么需要從后面補(bǔ)0,左移操作后為 (000)11(000)
?? ??? ??? ??? ? */
?? ??? ??? ??? ?intFiveBit <<= (FIVE_BIT - lastCount);
?? ??? ??? ?}
?? ??? ??? ?// 利用該十進(jìn)制數(shù)作為碼表的索引獲取對(duì)應(yīng)的字符,并追加到sbencryptd
?? ??? ??? ?sbencryptd.append(CODEC_TABLE.charAt(intFiveBit));
?? ??? ?}
?? ??? ?return sbencryptd.toString();
?? ?}
?? ?/**
?? ? * (解碼/解密)字符串,采用默認(rèn)語言環(huán)境的 character set。
?? ? *
?? ? * @param code
?? ? *??????????? 需要(解碼/解密)的字符串
?? ? *
?? ? * @return (解碼/解密)后的字符串
?? ? */
?? ?public static String decrypt(String code) {
?? ??? ?return decrypt(code, null);
?? ?}
?? ?/**
?? ? * (解碼/解密)字符串
?? ? *
?? ? * @param code
?? ? *??????????? 需要(解碼/解密)的字符串
?? ? * @param characterSet
?? ? *??????????? 字符集
?? ? *
?? ? * @return (解碼/解密)后的字符串
?? ? */
?? ?public static String decrypt(String code, String characterSet) {
?? ??? ?if (code == null || code.length() < 1) {
?? ??? ??? ?return "";
?? ??? ?}
?? ??? ?/*
?? ??? ? * 拆除每一個(gè)字符,從碼表里獲取相應(yīng)的索引。
?? ??? ? */
?? ??? ?StringBuilder sbBinarys = new StringBuilder();
?? ??? ?for (int i = 0; i < code.length(); i++) {
?? ??? ??? ?// 從碼表里獲取相應(yīng)的索引
?? ??? ??? ?int index = getCodecTableIndex(code.charAt(i));
?? ??? ??? ?// 將十進(jìn)制的索引轉(zhuǎn)換為二進(jìn)制串
?? ??? ??? ?String indexBinary = Integer.toBinaryString(index);
?? ??? ??? ?// 去掉前3個(gè)0,并且追加到sbBinarys
?? ??? ??? ?FormatUtil.formatBinary(indexBinary, sbBinarys, FIVE_BIT);
?? ??? ?}
?? ??? ?/*
?? ??? ? * 按8個(gè)bit拆分,剩下的余數(shù)扔掉。
?? ??? ? * 扔掉的余數(shù)是在(編碼/加密)的分割時(shí)候,在分剩的余數(shù)的后面補(bǔ)的0
?? ??? ? */
?? ??? ?byte[] binarys = new byte[sbBinarys.length() / EIGHT_BIT];
?? ??? ?for (int i = 0, j = 0; i < binarys.length; i++) {
?? ??? ??? ?// 每8個(gè)bit截取一份
?? ??? ??? ?String sub = sbBinarys.substring(j, j += EIGHT_BIT);
?? ??? ??? ?// 將截取下來的二進(jìn)制串轉(zhuǎn)換為十進(jìn)制
?? ??? ??? ?Integer intBinary = Integer.valueOf(sub, BINARY);
?? ??? ??? ?binarys[i] = intBinary.byteValue();
?? ??? ?}
?? ??? ?String decryptd = null;
?? ??? ?if (characterSet == null || characterSet.length() < 1) {
?? ??? ??? ?// 采用默認(rèn)語言環(huán)境的 character set。
?? ??? ??? ?decryptd = new String(binarys);
?? ??? ?} else {
?? ??? ??? ?try {
?? ??? ??? ??? ?// 采用指定的 character set。
?? ??? ??? ??? ?return new String(binarys, characterSet);
?? ??? ??? ?} catch (UnsupportedEncodingException e) {
?? ??? ??? ??? ?// ignore...
?? ??? ??? ?}
?? ??? ?}
?? ??? ?return decryptd;
?? ?}
?? ?/**
?? ? * 根據(jù)所給出的字符,遍歷CODEC_TABLE,返回對(duì)應(yīng)的下標(biāo)。
?? ? * 如果沒找到,則返回 -1。
?? ? *
?? ? * @param code
?? ? *??????????? 在CODEC_TABLE范圍內(nèi)的字符。
?? ? *
?? ? * @return 字符在CODEC_TABLE里對(duì)應(yīng)的下標(biāo),如果沒找到,則返回 -1。
?? ? */
?? ?private static int getCodecTableIndex(char code) {
?? ??? ?for (int i = 0; i < CODEC_TABLE.length(); i++) {
?? ??? ??? ?if (CODEC_TABLE.charAt(i) == code) {
?? ??? ??? ??? ?return i;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?return -1;
?? ?}
?? ?/**
?? ? * 測(cè)試
?? ? * @param args
?? ? */
?? ?public static void main(String[] args) {
?? ??? ?try {
?? ??? ??? ?BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
?? ??? ??? ?while (true) {
?? ??? ??? ??? ?System.out.print("輸入字符號(hào)串:");
?? ??? ??? ??? ?String in = br.readLine();
?? ??? ??? ??? ?if ("exit".equalsIgnoreCase(in)) {
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?}
//?? ??? ??? ??? ?String encrypt = EncryptDecrypt.encrypt(in);
//
//?? ??? ??? ??? ?String decrypt = EncryptDecrypt.decrypt(encrypt);
//?? ??? ??? ??? ?System.out.println();
//?? ??? ??? ??? ?System.out.println("------------------------------test");
//?? ??? ??? ??? ?System.out.println("original: " + in);
//?? ??? ??? ??? ?System.out.println("encrypt: " + encrypt);
//?? ??? ??? ??? ?System.out.println("decrypt: " + decrypt);
//?? ??? ??? ??? ?System.out.println("------------------------------test");
?? ??? ??? ??? ?System.out.println();
?? ??? ??? ??? ?//gizdcojwhlalvr7s2cwa
?? ??? ??? ??? ?System.out.println("-------------------------------------------");
?? ??? ??? ??? ?System.out.println("編碼:"+EncryptDecrypt.encrypt("requirementDetailsVo.var_requirement.requirement_id=8a906aa71f347aa2011f347aa25f0003"));
?? ??? ??? ??? ?System.out.println("jie:"+EncryptDecrypt.decrypt(EncryptDecrypt.encrypt("requirementDetailsVo.var_requirement.requirement_id=8a906aa71f347aa2011f347aa25f0003")));
?? ??? ??? ??? ?System.out.println("解碼:"+EncryptDecrypt.decrypt(in));
//?? ??? ??? ??? ?System.out.println("解碼:"+EncryptDecrypt.decrypt(EncryptDecrypt.encrypt(in)));
?? ??? ??? ??? ?System.out.println("-------------------------------------------");
?? ??? ??? ??? ?System.out.println();
?? ??? ??? ?}
?? ??? ?} catch (IOException e) {
?? ??? ??? ?e.printStackTrace();
?? ??? ?} catch (EncodingException e) {
?? ??? ??? ?// TODO Auto-generated catch block
?? ??? ??? ?e.printStackTrace();
?? ??? ?}
?? ?}
}
/**
?*
?*/
package com.newegg.lab.framework.security;
/**
?*
?* @Discription
?*
?* @Company 新蛋信息技術(shù)(西安)有限公司
?*
?* @Author Terry.B.Li
?*
?* @CreateDate 2009-2-4 下午04:32:29
?*
?* @Version V0.5
?*
?*/
public class FormatUtil {
??? /**
??? ?* 格式化二進(jìn)制。默認(rèn)取8位,超過則截取,不足則補(bǔ)零。
??? ?* 格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:06
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?*
??? ?* @return 格式化后的字符串。
??? ?*/
??? public static String formatBinary(byte binary) {
??? ??? return formatBinary(binary, null).toString();
??? }
??? /**
??? ?* 格式化二進(jìn)制,超過則截取,不足則補(bǔ)零。格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:09
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?* @param bitCount
??? ?*??????????? 需要格式化的位數(shù)。
??? ?*
??? ?* @return 格式化后的字符串。
??? ?*/
??? public static String formatBinary(byte binary, int bitCount) {
??? ??? return formatBinary(binary, null, bitCount).toString();
??? }
??? /**
??? ?* 格式化二進(jìn)制,超過則截取,不足則補(bǔ)零。格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:12
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?* @param toAppendTo
??? ?*??????????? 追加到的Builder。
??? ?*
??? ?* @return 格式化后的StringBuilder。
??? ?*/
??? public static StringBuilder formatBinary(byte binary,
??? ??? ??? StringBuilder toAppendTo) {
??? ??? return formatBinary(binary, toAppendTo, EncryptDecrypt.EIGHT_BIT);
??? }
??? /**
??? ?* 格式化二進(jìn)制,超過則截取,不足則補(bǔ)零。格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:16
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?* @param toAppendTo
??? ?*??????????? 追加到的Builder。
??? ?* @param bitCount
??? ?*??????????? 需要格式化的位數(shù)。
??? ?*
??? ?* @return 格式化后的StringBuilder。
??? ?*/
??? public static StringBuilder formatBinary(byte binary,
??? ??? ??? StringBuilder toAppendTo, int bitCount) {
??? ??? String strBinary = Integer.toBinaryString(binary);
??? ??? return formatBinary(strBinary, toAppendTo, bitCount);
??? }
??? /**
??? ?* 格式化二進(jìn)制,超過則截取,不足則補(bǔ)零。格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:20
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?*
??? ?* @return 格式化后的字符串。
??? ?*/
??? public static String formatBinary(String binary) {
??? ??? return formatBinary(binary, null).toString();
??? }
??? /**
??? ?* 格式化二進(jìn)制,超過則截取,不足則補(bǔ)零。格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:24
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?* @param bitCount
??? ?*??????????? 需要格式化的位數(shù)。
??? ?*
??? ?* @return 格式化后的字符串。
??? ?*/
??? public static String formatBinary(String binary, int bitCount) {
??? ??? return formatBinary(binary, null, bitCount).toString();
??? }
??? /**
??? ?* 格式化二進(jìn)制,超過則截取,不足則補(bǔ)零。格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:27
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?* @param toAppendTo
??? ?*??????????? 追加到的Builder。
??? ?*
??? ?* @return 格式化后的StringBuilder。
??? ?*/
??? public static StringBuilder formatBinary(String binary,
??? ??? ??? StringBuilder toAppendTo) {
??? ??? return formatBinary(binary, toAppendTo, EncryptDecrypt.EIGHT_BIT);
??? }
??? /**
??? ?* 格式化二進(jìn)制,超過則截取,不足則補(bǔ)零。格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:31
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?* @param toAppendTo
??? ?*??????????? 追加到的Builder。
??? ?* @param bitCount
??? ?*??????????? 追加到的Builder。
??? ?*
??? ?* @return 格式化后的StringBuilder。
??? ?*/
??? public static StringBuilder formatBinary(String binary,
??? ??? ??? StringBuilder toAppendTo, int bitCount) {
??? ??? if (binary == null || binary.length() < 1) {
??? ??? ??? return toAppendTo;
??? ??? }
??? ??? if (toAppendTo == null) {
??? ??? ??? toAppendTo = new StringBuilder();
??? ??? }
??? ??? if (binary.length() == bitCount) {
??? ??? ??? toAppendTo.append(binary);
??? ??? ??? return toAppendTo;
??? ??? }
??? ??? /*
??? ??? ?* 前補(bǔ)0, 如: "100011" to "00100011"
??? ??? ?*/
??? ??? if (binary.length() < bitCount) {
??? ??? ??? StringBuilder formatted = new StringBuilder();
??? ??? ??? formatted.append(binary);
??? ??? ??? do {
??? ??? ??? ??? formatted.insert(0, "0");
??? ??? ??? } while (formatted.length() < bitCount);
??? ??? ??? toAppendTo.append(formatted);
??? ??? ??? return toAppendTo;
??? ??? }
??? ??? /*
??? ??? ?* 截取, 如: "11111111111111111111111110100011" to "10100011"
??? ??? ?*/
??? ??? if (binary.length() > bitCount) {
??? ??? ??? String intercepted = binary.substring(binary.length() - bitCount);
??? ??? ??? toAppendTo.append(intercepted);
??? ??? ??? return toAppendTo;
??? ??? }
??? ??? return toAppendTo;
??? }
}
?*
?*/
package com.newegg.lab.framework.security;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import com.newegg.lab.framework.exception.EncodingException;
import com.newegg.lab.framework.util.StringPoolConstant;
import com.newegg.lab.framework.util.Validator;
/**
?*
?* @Discription 字符串的(編碼/加密)與(解碼/解密)
?*
?* 規(guī)則:
?*
?* 在Base64中,碼表是由[A-Z,a-z,0-9,+,/,=(pad)]組成的。
?* 而在這里,碼表由[a-z,2-7] abcdefghijklmnopqrstuvwxyz234567 組成的:
?* -----------------------------------------------
?* a b c d e f g h i j k? l? m? n? o? p? q? r
?* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
?* -----------------------------------------------
?*? s? t? u? v? w? x? y? z? 2? 3? 4? 5? 6? 7
?* 18 19 20 21 22 23 24 25 26 27 28 29 30 31
?* ------------------------------------------------
?*
?* 在Base64中,是將二進(jìn)制連成一串,然后再按6位來分割,分割完后在前面補(bǔ)0,這個(gè)地球人都知道,不多說了。
?* 而在這里,在分割的那一步稍微有變動(dòng),是按5位來分割,如果剛好夠分,那就好了,如果不夠,那咋辦呢?
?*
?* 在Base64中,是用"="來解決的吧。
?* 而在這里,就是在前面補(bǔ)0,然后在后面再補(bǔ)零。
?*
?* 例如:字符串 "aaa",(編碼/加密)后是 "mfqwc"
?*
?* 二進(jìn)制:01100001 01100001 01100001
?* 轉(zhuǎn)換后:(000)01100 (000)00101 (000)10000 (000)10110 (000)0001(0)
?* 十進(jìn)制:??? 12????????? 5????????? 16???????? 22????????? 2
?* 碼表對(duì)應(yīng):?? m?????????? f????????? q????????? w?????????? c
?*
?* (解碼/解密)就更簡(jiǎn)單了:
?*
?* 碼表對(duì)應(yīng):??? m?????? f??????? q??????? w?????? c
?* 十進(jìn)制:???? 12?????? 5?????? 16?????? 22?????? 2
?* 二進(jìn)制: 00001100 00000101 00010000 00010110 00000010
?* 去前0后:01100 00101 10000 10110 00010
?* 合并后: 0110000101100001011000010
?*
?* 然后把合并后的串的長(zhǎng)度除一下8,發(fā)現(xiàn)多了個(gè)0:
?*
?* 二進(jìn)制:01100001 01100001 01100001 0
?*
?* 多了就算了,不要了(其實(shí)是在{編碼/加密}的分割時(shí)候,在分剩的余數(shù)的后面補(bǔ)的0)。
?* 然后再將 byte[] 轉(zhuǎn)回字符串,OK!又見"aaa"了。
?*
?* 有一點(diǎn)值得注意的,UTF-8、GBK、GB18030 一般都沒什么問題,
?* 但是 GB2312 可能字符集不夠豐富,繁體字在decrypt的時(shí)候成問號(hào)了
?*
?* @Company 新蛋信息技術(shù)(西安)有限公司
?*
?* @Author Terry.B.Li
?*
?* @CreateDate 2009-2-4 下午02:47:32
?*
?* @Version V0.5
?*
?*/
public class EncryptDecrypt {
?? ?/**
?? ? * 碼表 [a-n,q-z,0-4,6-7,9]
?? ? */
?? ?private static final String CODEC_TABLE = "abcdefghijklmnqrstuvwxyz01234679";
?? ?/**
?? ? * 表示5bit的字節(jié)
?? ? */
?? ?public final static int FIVE_BIT = 5;
?? ?/**
?? ? * 表示8bit的字節(jié)
?? ? */
?? ?public final static int EIGHT_BIT = 8;
?? ?/**
?? ? * 表示二進(jìn)制
?? ? */
?? ?public final static int BINARY = 2;
?? ?/**
?? ? * (編碼/加密)字符串,采用默認(rèn)語言環(huán)境的 character set
?? ? * @param str?? ?需要(編碼/加密)的字符串
?? ? * @return?? ??? ?(編碼/加密)后的字符串
?? ? * @throws EncodingException
?? ? */
?? ?public static String encrypt(String str) throws EncodingException{
?? ??? ?return encrypt(str,null);
?? ?}
?? ?/**
?? ? * (編碼/加密)字符串
?? ? * @param str?? ??? ??? ?需要(編碼/加密)的字符串
?? ? * @param characterSet?? ?字符集
?? ? * @return?? ??? ??? ??? ?(編碼/加密)后的字符串
?? ? * @throws EncodingException
?? ? */
?? ?public static String encrypt(String str,String characterSet) throws EncodingException{
?? ??? ?if (Validator.isNull(str)) {
?? ??? ??? ?return StringPoolConstant.BLANK;
?? ??? ?}
?? ??? ?byte[] keyBytes = null;
?? ??? ?try {
?? ??? ??? ?if (Validator.isNotNull(characterSet)) {
?? ??? ??? ??? ?keyBytes = str.getBytes(characterSet);
?? ??? ??? ?}else{
?? ??? ??? ??? ?keyBytes = str.getBytes();
?? ??? ??? ?}
?? ??? ?} catch (UnsupportedEncodingException e) {
?? ??? ??? ?throw new EncodingException(e);
?? ??? ?}
?? ??? ?return encrypt(keyBytes);
?? ?}
?? ?/**
?? ? * (編碼/加密)字節(jié)數(shù)組
?? ? * @param bytes?? ?需要(編碼/加密)的字節(jié)數(shù)組
?? ? * @return?? ??? ?(編碼/加密)后的字符串
?? ? */
?? ?private static String encrypt(byte[] keyBytes){
?? ??? ?if (Validator.isNull(keyBytes) || keyBytes.length < 1) {
?? ??? ??? ?return StringPoolConstant.BLANK;
?? ??? ?}
?? ??? ?/*
?? ??? ? * 合并二進(jìn)制碼,
?? ??? ? * 如:
?? ??? ? *???? 00101010 11010011 00101101 10100011
?? ??? ? *?? to
?? ??? ? *???? 00101010110100110010110110100011
?? ??? ? */
?? ??? ?StringBuilder mergrd = new StringBuilder();
?? ??? ?for (int i = 0; i < keyBytes.length; i++) {
?? ??? ??? ?FormatUtil.formatBinary(keyBytes[i], mergrd);
?? ??? ?}
?? ??? ?/*
?? ??? ? * 以5個(gè)bit為單位,計(jì)算能分多少組,
?? ??? ? * 如:
???????? *???? 00101010110100110010110110100011
?? ??? ? *?? to
?? ??? ? *???? 00101 01011 01001 10010 11011 01000 11
?? ??? ? *????????????????????????????????????????? |
?? ??? ? *?????????????????????????????????? (這個(gè)11為余下的位)
?? ??? ? */
?? ??? ?int groupCount = mergrd.length() / FIVE_BIT;
?? ??? ?// 計(jì)算余下的位數(shù)
?? ??? ?int lastCount = mergrd.length() % FIVE_BIT;
?? ??? ?// 類似數(shù)據(jù)分頁的算法,有余數(shù)的情況下需要加 1。
?? ??? ?if (lastCount > 0) {
?? ??? ??? ?groupCount += 1;
?? ??? ?}
?? ??? ?/*
?? ??? ? * (編碼/加密)
?? ??? ? */
?? ??? ?StringBuilder sbencryptd = new StringBuilder();
?? ??? ?// 循環(huán)所需的條件
?? ??? ?int forMax = groupCount * FIVE_BIT;
?? ??? ?// 每次遞增5位來截取
?? ??? ?for (int i = 0; i < forMax; i += FIVE_BIT) {
?? ??? ??? ?// 結(jié)束點(diǎn)
?? ??? ??? ?int end = i + FIVE_BIT;
?? ??? ??? ?/*
?? ??? ??? ? * 如果結(jié)束點(diǎn)比已合并的二進(jìn)制碼串的長(zhǎng)度要大,
?? ??? ??? ? * 相當(dāng)于有余數(shù),
???????????? * 并且表示當(dāng)前循環(huán)到了(已合并的二進(jìn)制碼串的長(zhǎng)度 % FIVE_BIT)的那一截。
?? ??? ??? ? */
?? ??? ??? ?// 標(biāo)記是否到了余數(shù)的那一截
?? ??? ??? ?boolean flag = false;
?? ??? ??? ?if (end > mergrd.length()) {
?? ??? ??? ??? ?/*
?? ??? ??? ??? ? * 如果結(jié)束點(diǎn)比已合并的二進(jìn)制碼串的長(zhǎng)度要大,
?? ??? ??? ??? ? * 結(jié)束點(diǎn)需要被重設(shè)為:
?? ??? ??? ??? ? * 已合并的二進(jìn)制碼串的長(zhǎng)度,等價(jià)于(i + lastCount). 并且重設(shè)標(biāo)記。
?? ??? ??? ??? ? */
?? ??? ??? ??? ?end = (i + lastCount);
?? ??? ??? ??? ?flag = true;
?? ??? ??? ?}
?? ??? ??? ?// 截取
?? ??? ??? ?String strFiveBit = mergrd.substring(i, end);
?? ??? ??? ?// 截取后從二進(jìn)制轉(zhuǎn)為十進(jìn)制
?? ??? ??? ?int intFiveBit = Integer.parseInt(strFiveBit, BINARY);
?? ??? ??? ?if (flag) {
?? ??? ??? ??? ?/*
?? ??? ??? ??? ? * 如果結(jié)束點(diǎn)比已合并的二進(jìn)制碼串的長(zhǎng)度要大,
?? ??? ??? ??? ? * 或者是到了余數(shù)的那一截:
?? ??? ??? ??? ? * 需要左移操作,假設(shè)余下的二進(jìn)制位為:11,
?? ??? ??? ??? ? * 那么需要從后面補(bǔ)0,左移操作后為 (000)11(000)
?? ??? ??? ??? ? */
?? ??? ??? ??? ?intFiveBit <<= (FIVE_BIT - lastCount);
?? ??? ??? ?}
?? ??? ??? ?// 利用該十進(jìn)制數(shù)作為碼表的索引獲取對(duì)應(yīng)的字符,并追加到sbencryptd
?? ??? ??? ?sbencryptd.append(CODEC_TABLE.charAt(intFiveBit));
?? ??? ?}
?? ??? ?return sbencryptd.toString();
?? ?}
?? ?/**
?? ? * (解碼/解密)字符串,采用默認(rèn)語言環(huán)境的 character set。
?? ? *
?? ? * @param code
?? ? *??????????? 需要(解碼/解密)的字符串
?? ? *
?? ? * @return (解碼/解密)后的字符串
?? ? */
?? ?public static String decrypt(String code) {
?? ??? ?return decrypt(code, null);
?? ?}
?? ?/**
?? ? * (解碼/解密)字符串
?? ? *
?? ? * @param code
?? ? *??????????? 需要(解碼/解密)的字符串
?? ? * @param characterSet
?? ? *??????????? 字符集
?? ? *
?? ? * @return (解碼/解密)后的字符串
?? ? */
?? ?public static String decrypt(String code, String characterSet) {
?? ??? ?if (code == null || code.length() < 1) {
?? ??? ??? ?return "";
?? ??? ?}
?? ??? ?/*
?? ??? ? * 拆除每一個(gè)字符,從碼表里獲取相應(yīng)的索引。
?? ??? ? */
?? ??? ?StringBuilder sbBinarys = new StringBuilder();
?? ??? ?for (int i = 0; i < code.length(); i++) {
?? ??? ??? ?// 從碼表里獲取相應(yīng)的索引
?? ??? ??? ?int index = getCodecTableIndex(code.charAt(i));
?? ??? ??? ?// 將十進(jìn)制的索引轉(zhuǎn)換為二進(jìn)制串
?? ??? ??? ?String indexBinary = Integer.toBinaryString(index);
?? ??? ??? ?// 去掉前3個(gè)0,并且追加到sbBinarys
?? ??? ??? ?FormatUtil.formatBinary(indexBinary, sbBinarys, FIVE_BIT);
?? ??? ?}
?? ??? ?/*
?? ??? ? * 按8個(gè)bit拆分,剩下的余數(shù)扔掉。
?? ??? ? * 扔掉的余數(shù)是在(編碼/加密)的分割時(shí)候,在分剩的余數(shù)的后面補(bǔ)的0
?? ??? ? */
?? ??? ?byte[] binarys = new byte[sbBinarys.length() / EIGHT_BIT];
?? ??? ?for (int i = 0, j = 0; i < binarys.length; i++) {
?? ??? ??? ?// 每8個(gè)bit截取一份
?? ??? ??? ?String sub = sbBinarys.substring(j, j += EIGHT_BIT);
?? ??? ??? ?// 將截取下來的二進(jìn)制串轉(zhuǎn)換為十進(jìn)制
?? ??? ??? ?Integer intBinary = Integer.valueOf(sub, BINARY);
?? ??? ??? ?binarys[i] = intBinary.byteValue();
?? ??? ?}
?? ??? ?String decryptd = null;
?? ??? ?if (characterSet == null || characterSet.length() < 1) {
?? ??? ??? ?// 采用默認(rèn)語言環(huán)境的 character set。
?? ??? ??? ?decryptd = new String(binarys);
?? ??? ?} else {
?? ??? ??? ?try {
?? ??? ??? ??? ?// 采用指定的 character set。
?? ??? ??? ??? ?return new String(binarys, characterSet);
?? ??? ??? ?} catch (UnsupportedEncodingException e) {
?? ??? ??? ??? ?// ignore...
?? ??? ??? ?}
?? ??? ?}
?? ??? ?return decryptd;
?? ?}
?? ?/**
?? ? * 根據(jù)所給出的字符,遍歷CODEC_TABLE,返回對(duì)應(yīng)的下標(biāo)。
?? ? * 如果沒找到,則返回 -1。
?? ? *
?? ? * @param code
?? ? *??????????? 在CODEC_TABLE范圍內(nèi)的字符。
?? ? *
?? ? * @return 字符在CODEC_TABLE里對(duì)應(yīng)的下標(biāo),如果沒找到,則返回 -1。
?? ? */
?? ?private static int getCodecTableIndex(char code) {
?? ??? ?for (int i = 0; i < CODEC_TABLE.length(); i++) {
?? ??? ??? ?if (CODEC_TABLE.charAt(i) == code) {
?? ??? ??? ??? ?return i;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?return -1;
?? ?}
?? ?/**
?? ? * 測(cè)試
?? ? * @param args
?? ? */
?? ?public static void main(String[] args) {
?? ??? ?try {
?? ??? ??? ?BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
?? ??? ??? ?while (true) {
?? ??? ??? ??? ?System.out.print("輸入字符號(hào)串:");
?? ??? ??? ??? ?String in = br.readLine();
?? ??? ??? ??? ?if ("exit".equalsIgnoreCase(in)) {
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?}
//?? ??? ??? ??? ?String encrypt = EncryptDecrypt.encrypt(in);
//
//?? ??? ??? ??? ?String decrypt = EncryptDecrypt.decrypt(encrypt);
//?? ??? ??? ??? ?System.out.println();
//?? ??? ??? ??? ?System.out.println("------------------------------test");
//?? ??? ??? ??? ?System.out.println("original: " + in);
//?? ??? ??? ??? ?System.out.println("encrypt: " + encrypt);
//?? ??? ??? ??? ?System.out.println("decrypt: " + decrypt);
//?? ??? ??? ??? ?System.out.println("------------------------------test");
?? ??? ??? ??? ?System.out.println();
?? ??? ??? ??? ?//gizdcojwhlalvr7s2cwa
?? ??? ??? ??? ?System.out.println("-------------------------------------------");
?? ??? ??? ??? ?System.out.println("編碼:"+EncryptDecrypt.encrypt("requirementDetailsVo.var_requirement.requirement_id=8a906aa71f347aa2011f347aa25f0003"));
?? ??? ??? ??? ?System.out.println("jie:"+EncryptDecrypt.decrypt(EncryptDecrypt.encrypt("requirementDetailsVo.var_requirement.requirement_id=8a906aa71f347aa2011f347aa25f0003")));
?? ??? ??? ??? ?System.out.println("解碼:"+EncryptDecrypt.decrypt(in));
//?? ??? ??? ??? ?System.out.println("解碼:"+EncryptDecrypt.decrypt(EncryptDecrypt.encrypt(in)));
?? ??? ??? ??? ?System.out.println("-------------------------------------------");
?? ??? ??? ??? ?System.out.println();
?? ??? ??? ?}
?? ??? ?} catch (IOException e) {
?? ??? ??? ?e.printStackTrace();
?? ??? ?} catch (EncodingException e) {
?? ??? ??? ?// TODO Auto-generated catch block
?? ??? ??? ?e.printStackTrace();
?? ??? ?}
?? ?}
}
/**
?*
?*/
package com.newegg.lab.framework.security;
/**
?*
?* @Discription
?*
?* @Company 新蛋信息技術(shù)(西安)有限公司
?*
?* @Author Terry.B.Li
?*
?* @CreateDate 2009-2-4 下午04:32:29
?*
?* @Version V0.5
?*
?*/
public class FormatUtil {
??? /**
??? ?* 格式化二進(jìn)制。默認(rèn)取8位,超過則截取,不足則補(bǔ)零。
??? ?* 格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:06
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?*
??? ?* @return 格式化后的字符串。
??? ?*/
??? public static String formatBinary(byte binary) {
??? ??? return formatBinary(binary, null).toString();
??? }
??? /**
??? ?* 格式化二進(jìn)制,超過則截取,不足則補(bǔ)零。格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:09
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?* @param bitCount
??? ?*??????????? 需要格式化的位數(shù)。
??? ?*
??? ?* @return 格式化后的字符串。
??? ?*/
??? public static String formatBinary(byte binary, int bitCount) {
??? ??? return formatBinary(binary, null, bitCount).toString();
??? }
??? /**
??? ?* 格式化二進(jìn)制,超過則截取,不足則補(bǔ)零。格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:12
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?* @param toAppendTo
??? ?*??????????? 追加到的Builder。
??? ?*
??? ?* @return 格式化后的StringBuilder。
??? ?*/
??? public static StringBuilder formatBinary(byte binary,
??? ??? ??? StringBuilder toAppendTo) {
??? ??? return formatBinary(binary, toAppendTo, EncryptDecrypt.EIGHT_BIT);
??? }
??? /**
??? ?* 格式化二進(jìn)制,超過則截取,不足則補(bǔ)零。格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:16
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?* @param toAppendTo
??? ?*??????????? 追加到的Builder。
??? ?* @param bitCount
??? ?*??????????? 需要格式化的位數(shù)。
??? ?*
??? ?* @return 格式化后的StringBuilder。
??? ?*/
??? public static StringBuilder formatBinary(byte binary,
??? ??? ??? StringBuilder toAppendTo, int bitCount) {
??? ??? String strBinary = Integer.toBinaryString(binary);
??? ??? return formatBinary(strBinary, toAppendTo, bitCount);
??? }
??? /**
??? ?* 格式化二進(jìn)制,超過則截取,不足則補(bǔ)零。格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:20
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?*
??? ?* @return 格式化后的字符串。
??? ?*/
??? public static String formatBinary(String binary) {
??? ??? return formatBinary(binary, null).toString();
??? }
??? /**
??? ?* 格式化二進(jìn)制,超過則截取,不足則補(bǔ)零。格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:24
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?* @param bitCount
??? ?*??????????? 需要格式化的位數(shù)。
??? ?*
??? ?* @return 格式化后的字符串。
??? ?*/
??? public static String formatBinary(String binary, int bitCount) {
??? ??? return formatBinary(binary, null, bitCount).toString();
??? }
??? /**
??? ?* 格式化二進(jìn)制,超過則截取,不足則補(bǔ)零。格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:27
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?* @param toAppendTo
??? ?*??????????? 追加到的Builder。
??? ?*
??? ?* @return 格式化后的StringBuilder。
??? ?*/
??? public static StringBuilder formatBinary(String binary,
??? ??? ??? StringBuilder toAppendTo) {
??? ??? return formatBinary(binary, toAppendTo, EncryptDecrypt.EIGHT_BIT);
??? }
??? /**
??? ?* 格式化二進(jìn)制,超過則截取,不足則補(bǔ)零。格式:“00000000”,與NumberFormat的pattern:“########”類似。
??? ?*
??? ?* @author terry
??? ?* @version 2008-12-3 下午03:15:31
??? ?*
??? ?* @param binary
??? ?*??????????? 需要格式化的字節(jié)。
??? ?* @param toAppendTo
??? ?*??????????? 追加到的Builder。
??? ?* @param bitCount
??? ?*??????????? 追加到的Builder。
??? ?*
??? ?* @return 格式化后的StringBuilder。
??? ?*/
??? public static StringBuilder formatBinary(String binary,
??? ??? ??? StringBuilder toAppendTo, int bitCount) {
??? ??? if (binary == null || binary.length() < 1) {
??? ??? ??? return toAppendTo;
??? ??? }
??? ??? if (toAppendTo == null) {
??? ??? ??? toAppendTo = new StringBuilder();
??? ??? }
??? ??? if (binary.length() == bitCount) {
??? ??? ??? toAppendTo.append(binary);
??? ??? ??? return toAppendTo;
??? ??? }
??? ??? /*
??? ??? ?* 前補(bǔ)0, 如: "100011" to "00100011"
??? ??? ?*/
??? ??? if (binary.length() < bitCount) {
??? ??? ??? StringBuilder formatted = new StringBuilder();
??? ??? ??? formatted.append(binary);
??? ??? ??? do {
??? ??? ??? ??? formatted.insert(0, "0");
??? ??? ??? } while (formatted.length() < bitCount);
??? ??? ??? toAppendTo.append(formatted);
??? ??? ??? return toAppendTo;
??? ??? }
??? ??? /*
??? ??? ?* 截取, 如: "11111111111111111111111110100011" to "10100011"
??? ??? ?*/
??? ??? if (binary.length() > bitCount) {
??? ??? ??? String intercepted = binary.substring(binary.length() - bitCount);
??? ??? ??? toAppendTo.append(intercepted);
??? ??? ??? return toAppendTo;
??? ??? }
??? ??? return toAppendTo;
??? }
}