AES LINUX加密结果不一致
来源:互联网 发布:网络布线施工室分 编辑:程序博客网 时间:2024/05/16 19:23
AES对称加解密, 相同key加密结果不一致,因为Linux的强随机数而导致,需要在 jvm 加如下启动参数
-Djava.security.egd=file:/dev/./urandom
如下测试类,在Linux javac Test.java 编译 ,运行 Java Test 每次加密结果不一致。
运行 java -Djava.security.egd=file:/dev/./urandom Test 则一致
import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.security.Key;import java.security.SecureRandom;import java.util.HashMap;import java.util.Map;import javax.crypto.Cipher;import javax.crypto.CipherInputStream;import javax.crypto.CipherOutputStream;import javax.crypto.KeyGenerator;import javax.crypto.spec.IvParameterSpec;//import org.apache.commons.lang3.StringUtils;public class Test { public static void main(String[] args) throws UnsupportedEncodingException, RuntimeException { // TODO Auto-generated method stub String xx = "62222222222222222222"; System.out.println("xx:["+ xx +"]"); String en1 = AESUtil.encrypt(xx); System.out.println("en1:["+ en1 +"]"); String en2 = AESUtil.encrypt(xx); System.out.println("en2:["+ en2 +"]"); String en3 = AESUtil.encrypt(xx); System.out.println("en3:["+ en3 +"]"); System.out.println(">>>"); String de1 = AESUtil.decrypt("CmrCvf3jdzPihcN75poIK+dereT2XxsbUe0LWvd7p3Q*"); System.out.println("de1:["+ de1 +"]"); /* String de2 = AESUtil.decrypt(en2); System.out.println("de2:["+ de2 +"]"); String de3 = AESUtil.decrypt(en3); System.out.println("de2:["+ de3 +"]");*/ } static class AESUtil extends AESEncrypter { public AESUtil(String aesKey) throws RuntimeException { super(aesKey); } // 因为美国对软件出口的控制,默认只支持128位;要使用256则需另下bcprov-jdk的jar包替换jre\lib\security下的jar private static final int KEY_SIZE = 128; private static final String aesKey = "8979d58a2a51e140a2088fb505218ce1"; /** * @title encrypt * @description 加密 * @author yy * @date 2017年5月2日 上午11:17:35 * @param text * @return * @throws RuntimeException * @return String */ public static String encrypt(String text) throws RuntimeException { if (StringUtils.isBlank(text)) return null; return getInstance(aesKey).encode(text.getBytes()); } /** * @title decrypt * @description 解密 * @author yy * @date 2017年5月2日 上午11:17:38 * @param encryptText * @return * @throws RuntimeException * @return String */ public static String decrypt(String encryptText) throws RuntimeException { if (StringUtils.isBlank(encryptText)) return null; return new String(getInstance(aesKey).decode(encryptText)); } @Override public Key generateKey() throws Exception { KeyGenerator kgen = KeyGenerator.getInstance(KEY_ALGORITHM); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); sr.setSeed(aesKey.getBytes()); kgen.init(KEY_SIZE,sr ); return kgen.generateKey(); } public static void main(String[] args) { System.out.println(); } } static class StringUtils { public static boolean isBlank(final CharSequence cs) { int strLen; if (cs == null || (strLen = cs.length()) == 0) { return true; } for (int i = 0; i < strLen; i++) { if (Character.isWhitespace(cs.charAt(i)) == false) { return false; } } return true; } public static String getLMTString(Object src, int limit, String supplement) { return getLMTString(src, limit, true, true, supplement); } public static String getLMTString(Object src, int limit, boolean frontBegin, boolean isBack, String supplement) { if (src == null) return null; String target = src.toString(); int diffValue = target.length() - limit; if (diffValue == 0) return target; else if (diffValue > 0) return frontBegin ? target.substring(0, limit) : target.substring(diffValue, target.length()); supplement = supplement == null ? "" : supplement; if (supplement.equals("")) return target; if (isBack) { do { target += supplement; } while (target.length() < limit); } else { do { target = supplement + target; } while (target.length() < limit); } return target.length() == limit ? target : target.substring(0, limit); } } public enum Charset { /** * ASCII(American Standard Code for Information * Interchange,美国信息互换标准代码)<br/> * 是基于罗马字母表的一套电脑编码系统,它主要用于显示现代英语和其他西欧语言<br/> * 它是现今最通用的单字节编码系统,并等同于国际标准ISO 646 */ ASCII("ascii"), /** * 通常叫做Latin-1,和ASCII编码相似<br/> * 属于单字节编码,最多能表示的字符范围是0-255,应用于英文系列 */ ISO8859_1("iso8859-1"), /** * GB2312又称为GB2312-80字符集,全称为<信息交换用汉字编码字符集·基本集>,由原中国国家标准总局发布,1981年5月1日实施, * 是中国国家标准的简体中文字符集。它所收录的汉字已经覆盖99.75%的使用频率,基本满足了汉字的计算机处理需要。在中国大陆和新加坡获广泛使用 * <br/> * GB2312收录简化汉字及一般符号、序号、数字、拉丁字母、日文假名、希腊字母、俄文字母、汉语拼音符号、汉语注音字母,共 7445 * 个图形字符。其中包括6763个汉字,其中一级汉字3755个,二级汉字3008个;包括拉丁字母、希腊字母、日文平假名及片假名字母、 * 俄语西里尔字母在内的682个全角字符。 */ GB2312("gb2312"), /** * GBK字符集是GB2312的扩展(K)<br/> * GBK1.0收录了21886个符号,它分为汉字区和图形符号区,汉字区包括21003个字符。GBK字符集主要扩展了繁体中文字的支持 */ GBK("gbk"), /** * GB18030的全称是GB18030-2000<信息交换用汉字编码字符集基本集的扩充>,是我国政府于2000年3月17日发布的新的汉字编码国家标准 * ,2001年8月31日后在中国市场上发布的软件必须符合本标准<br/> * GB 18030字符集标准的出台经过广泛参与和论证,来自国内外知名信息技术行业的公司,信息产业部和原国家质量技术监督局联合实施<br/> * GB * 18030字符集标准解决汉字、日文假名、朝鲜语和中国少数民族文字组成的大字符集计算机编码问题。该标准的字符总编码空间超过150万个编码位, * 收录了27484个汉字,覆盖中文、日文、朝鲜语和中国少数民族文字。 * 满足中国大陆、香港、台湾、日本和韩国等东亚地区信息交换多文种、大字量、多用途、统一编码格式的要求 * 并且与UNICODE3.0版本兼容,填补UNICODE扩展字符字汇“统一汉字扩展A”的内容。并且与以前的国家字符编码标准(GB2312, * GB13000.1)兼容 */ GB18030("gb18030"), /** * BIG5又称大五码或五大码<br/> * 1984年由台湾财团法人信息工业策进会和五间软件公司宏碁 (Acer)、神通 (MiTAC)、佳佳、零壹 (Zero * One)、大众(FIC)创立,故称大五码<br/> * Big5码的产生,是因为当时台湾不同厂商各自推出不同的编码,如倚天码、IBM * PS55、王安码等,彼此不能兼容;另一方面,台湾政府当时尚未推出官方的汉字编码,而中国大陆的GB2312编码亦未有收录繁体中文字<br/> * Big5字符集共收录13,053个中文字,该字符集在中国台湾使用 */ BIG5("big5"), /** * 这是最统一的编码,可以用来表示所有语言的字符,而且是定长双字节(也有四字节的)编码,包括英文字母在内。所以可以说它是不兼容iso8859-1编码的 * ,也不兼容任何编码<br/> * 不过,相对于iso8859-1编码来说,UNICODE编码只是在前面增加了一个0字节,比如字母a为"00 61"<br/> * 需要说明的是,定长编码便于计算机处理(注意GB2312/GBK不是定长编码),而UNICODE又可以用来表示所有字符, * 所以在很多软件内部是使用UNICODE编码来处理的,比如java */ UNICODE("unicode"), /** * UTF-8是UNICODE的其中一个使用方式<br/> * UTF-8便于不同的计算机之间使用网络传输不同语言和编码的文字,使得双字节的UNICODE能够在现存的处理单字节的系统上正确传输<br/> * UTF-8使用可变长度字节来储存UNICODE字符,例如ASCII字母继续使用1字节储存,重音文字、希腊字母或西里尔字母等使用2字节来储存, * 而常用的汉字就要使用3字节。辅助平面字符则使用4字节 */ UTF8("utf-8"), /** UTF-16 使用一个或两个未分配的 16 位代码单元的序列对 UNICODE 代码点进行编码 */ UTF16("utf-16"), /** UTF-32 即将每一个 UNICODE 代码点表示为相同值的 32 位整数 */ UTF32("utf-32"); public final String VALUE; private Charset(String VALUE) { this.VALUE = VALUE; } } /** * AES对称加解密 * * @author fuli * @version 1.0 * @date 2016-12-09 18:03 * @description 加密数据默认转换为Base64编码 */ static class AESEncrypter { // 因为美国对软件出口的控制,默认只支持128位;要使用256则需另下bcprov-jdk的jar包替换jre\lib\security下的jar private static final int KEY_SIZE = 128; protected static final String KEY_ALGORITHM = "AES"; private static Map<String, AESEncrypter> encryptMap = new HashMap<String, AESEncrypter>(); private int keySize = KEY_SIZE; private String workPattern = "ECB"; private String paddingPattern = "PKCS5Padding"; private Cipher enCipher = null; private Cipher deCipher = null; private B64Encrypter b64Encrypter = null; protected String aesKey; public AESEncrypter(String aesKey) throws RuntimeException { init(aesKey, B64Encrypter.DEFAULT_ALPHABET, workPattern, paddingPattern, aesKey); } public AESEncrypter(String aesKey, boolean useHex) throws RuntimeException { init(aesKey, useHex ? null : B64Encrypter.DEFAULT_ALPHABET, workPattern, paddingPattern, aesKey); } public AESEncrypter(String aesKey, String b64Key) throws RuntimeException { init(aesKey, b64Key, workPattern, paddingPattern, aesKey); } public AESEncrypter(String aesKey, String workPattern, String paddingPattern) throws RuntimeException { init(aesKey, null, workPattern, paddingPattern, aesKey); } public AESEncrypter(String aesKey, String b64Key, String workPattern, String paddingPattern, String ivParameter) throws RuntimeException { init(aesKey, b64Key, workPattern, paddingPattern, ivParameter); } private void init(String aesKey, String b64Key, String workPattern, String paddingPattern, String ivParameter) { this.aesKey = aesKey; try { Key key = generateKey(); StringBuilder pattern = new StringBuilder(KEY_ALGORITHM); pattern.append("/").append(workPattern); pattern.append("/").append(paddingPattern); enCipher = Cipher.getInstance(pattern.toString()); deCipher = Cipher.getInstance(pattern.toString()); // 使用CBC模式,需要一个向量iv,可增加加密算法的强度 if (workPattern.equals("CBC")) { ivParameter = StringUtils.getLMTString(ivParameter, 16, "x"); IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes("UTF-8")); enCipher.init(Cipher.ENCRYPT_MODE, key, iv); deCipher.init(Cipher.DECRYPT_MODE, key, iv); } else { enCipher.init(Cipher.ENCRYPT_MODE, key); deCipher.init(Cipher.DECRYPT_MODE, key); } if (!StringUtils.isBlank(b64Key)) b64Encrypter = B64Encrypter.getInstance(b64Key); } catch (Exception e) { throw new RuntimeException("Error initializing AESEncrypter class. Cause: " + e); } } // 覆盖此方法以改变Key的生成方式 public Key generateKey() throws Exception { if (keySize != 128 && keySize != 192 && keySize != 256) { throw new RuntimeException( "Error initializing AESEncrypter class. Cause: Unsupported keySize " + keySize); } KeyGenerator kgen = KeyGenerator.getInstance(KEY_ALGORITHM); kgen.init(keySize, new SecureRandom(aesKey.getBytes())); return kgen.generateKey(); // OR SecretKeySpec key = new SecretKeySpec(aesKey.getBytes(), // KEY_ALGORITHM); } public String encode(byte[] data) throws RuntimeException { try { byte[] b = enCipher.doFinal(data); return b64Encrypter == null ? Hex.bytes2Hex(b) : b64Encrypter.encode(b); } catch (Exception e) { throw new RuntimeException("AESEncrypter encode error. Cause: " + e); } } public byte[] decode(String encryptText) throws RuntimeException { try { return deCipher .doFinal(b64Encrypter == null ? Hex.hexToBytes(encryptText) : b64Encrypter.decode(encryptText)); } catch (Exception e) { throw new RuntimeException("AESEncrypter decode error. Cause: " + e); } } public void encodeFile(String file, String destFile) throws RuntimeException { InputStream is = null; OutputStream out = null; CipherInputStream cis = null; try { is = new FileInputStream(file); out = new FileOutputStream(destFile); cis = new CipherInputStream(is, enCipher); byte[] buffer = new byte[1024]; int r; while ((r = cis.read(buffer)) > 0) { out.write(buffer, 0, r); } } catch (Exception e) { throw new RuntimeException("AESEncrypt encodeFile error. Cause: " + e); } finally { StreamUtils.close(out, is, cis); } } // // public void encodeFileAsyn(String file, String destFile) throws // RuntimeException, FileNotFoundException { // InputStream is = new FileInputStream(file); // CipherInputStream cis = new CipherInputStream(is, enCipher); // OutputStream out = new FileOutputStream(destFile); // Observable<byte[]> writer = Observable.create((subscriber) -> { // byte[] buffer = new byte[1024]; // int r; // try { // while ((r = cis.read(buffer)) > 0) { // subscriber.onNext(Arrays.copyOfRange(buffer, 0, r)); // } // } catch (IOException ioe) { // throw new RuntimeException("AESEncrypt encodeFileAsyn error. Cause: " // + ioe); // } // subscriber.onComplete(); // }); // writer.subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).subscribe((data) // -> { // try { // out.write(data); // } catch (IOException ioe) { // throw new RuntimeException("AESEncrypt encodeFileAsyn error. Cause: " // + ioe); // } // }, (e) -> { // StreamUtils.close(out, is, cis); // throw new RuntimeException("AESEncrypt encodeFileAsyn error. Cause: " // + e); // }, () -> { // StreamUtils.close(out, is, cis); // }); // } public void decodeFile(String file, String destFile) throws RuntimeException { InputStream is = null; OutputStream out = null; CipherOutputStream cos = null; try { is = new FileInputStream(file); out = new FileOutputStream(destFile); cos = new CipherOutputStream(out, deCipher); byte[] buffer = new byte[1024]; int r; while ((r = is.read(buffer)) >= 0) { cos.write(buffer, 0, r); } } catch (Exception e) { throw new RuntimeException("AESEncrypt decodeFile error. Cause: " + e); } finally { StreamUtils.close(is, out, cos); } } // // public void decodeFileAsyn(String file, String destFile) throws // RuntimeException, FileNotFoundException { // InputStream is = new FileInputStream(file); // OutputStream out = new FileOutputStream(destFile); // CipherOutputStream cos = new CipherOutputStream(out, deCipher); // Observable<byte[]> writer = Observable.create((subscriber) -> { // byte[] buffer = new byte[1024]; // int r; // try { // while ((r = is.read(buffer)) > 0) { // subscriber.onNext(Arrays.copyOfRange(buffer, 0, r)); // } // } catch (IOException ioe) { // throw new RuntimeException("AESEncrypt decodeFileAsyn error. Cause: " // + ioe); // } // subscriber.onComplete(); // }); // writer.subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).subscribe((data) // -> { // try { // out.write(data); // } catch (IOException ioe) { // throw new RuntimeException("AESEncrypt decodeFileAsyn error. Cause: " // + ioe); // } // }, (e) -> { // StreamUtils.close(is, out, cos); // throw new RuntimeException("AESEncrypt decodeFileAsyn error. Cause: " // + e); // }, () -> { // StreamUtils.close(is, out, cos); // }); // } /********************* static method ************************/ public static AESEncrypter getInstance(String aesKey) { return getInstance(aesKey, B64Encrypter.DEFAULT_ALPHABET); } public static AESEncrypter getInstance(String aesKey, boolean useHex) { if (StringUtils.isBlank(aesKey)) { return null; } String key = aesKey; AESEncrypter aesEncrypt = encryptMap.get(key); if (aesEncrypt == null) { aesEncrypt = new AESEncrypter(aesKey, useHex); encryptMap.put(key, aesEncrypt); } return aesEncrypt; } public static AESEncrypter getInstance(String aesKey, String b64Key) { if (StringUtils.isBlank(aesKey) || !B64Encrypter.checkAlphabet(b64Key)) { return null; } String key = aesKey + b64Key; System.out.println("key:"+key); AESEncrypter aesEncrypt = encryptMap.get(key); if (aesEncrypt == null) { aesEncrypt = new AESEncrypter(aesKey, b64Key); encryptMap.put(key, aesEncrypt); } return aesEncrypt; } public static AESEncrypter newInstance(String aesKey) { return newInstance(aesKey, B64Encrypter.DEFAULT_ALPHABET); } public static AESEncrypter newInstance(String aesKey, boolean useHex) { if (StringUtils.isBlank(aesKey)) { return null; } return new AESEncrypter(aesKey, useHex); } public static AESEncrypter newInstance(String aesKey, String b64Key) { if (StringUtils.isBlank(aesKey) || !B64Encrypter.checkAlphabet(b64Key)) { return null; } return new AESEncrypter(aesKey, b64Key); } public static String encrypt(String aesKey, byte[] data) throws RuntimeException { if (StringUtils.isBlank(aesKey) || data == null) return null; return getInstance(aesKey).encode(data); } public static String encrypt(String aesKey, String b64Key, byte[] data) throws RuntimeException { if (StringUtils.isBlank(aesKey) || !B64Encrypter.checkAlphabet(b64Key) || data == null) return null; return getInstance(aesKey, b64Key).encode(data); } public static byte[] decrypt(String aesKey, String encryptText) throws RuntimeException { if (StringUtils.isBlank(aesKey) || StringUtils.isBlank(encryptText)) return null; return getInstance(aesKey).decode(encryptText); } public static byte[] decrypt(String aesKey, String b64Key, String encryptText) throws RuntimeException { if (StringUtils.isBlank(aesKey) || StringUtils.isBlank(encryptText) || !B64Encrypter.checkAlphabet(b64Key)) return null; return getInstance(aesKey, b64Key).decode(encryptText); } /*************** File encode **************/ public static void encryptFile(String aesKey, String file, String destFile) throws RuntimeException { if (!StringUtils.isBlank(aesKey)) { getInstance(aesKey).encodeFile(file, destFile); } } public static void encryptFile(String aesKey, String b64Key, String file, String destFile) throws RuntimeException { if (!StringUtils.isBlank(aesKey) && B64Encrypter.checkAlphabet(b64Key)) { getInstance(aesKey, b64Key).encodeFile(file, destFile); } } // public static void encryptFileAsyn(String aesKey, String file, String // destFile) // throws RuntimeException, FileNotFoundException { // if (!StringUtils.isBlank(aesKey)) { // getInstance(aesKey).encodeFileAsyn(file, destFile); // } // } // public static void encryptFileAsyn(String aesKey, String b64Key, // String file, String destFile) // throws RuntimeException, FileNotFoundException { // if (!StringUtils.isBlank(aesKey) && // B64Encrypter.checkAlphabet(b64Key)) { // getInstance(aesKey, b64Key).encodeFileAsyn(file, destFile); // } // } /*************** File decode **************/ public static void decryptFile(String aesKey, String file, String destFile) throws RuntimeException { if (!StringUtils.isBlank(aesKey)) { getInstance(aesKey).decodeFile(file, destFile); } } public static void decryptFile(String aesKey, String b64Key, String file, String destFile) throws RuntimeException { if (!StringUtils.isBlank(aesKey) && B64Encrypter.checkAlphabet(b64Key)) { getInstance(aesKey, b64Key).decodeFile(file, destFile); } } // public static void decryptFileAsyn(String aesKey, String file, String // destFile) // throws RuntimeException, FileNotFoundException { // if (!StringUtils.isBlank(aesKey)) { // getInstance(aesKey).decodeFileAsyn(file, destFile); // } // } // // public static void decryptFileAsyn(String aesKey, String b64Key, // String file, String destFile) // throws RuntimeException, FileNotFoundException { // if (!StringUtils.isBlank(aesKey) && // B64Encrypter.checkAlphabet(b64Key)) { // getInstance(aesKey, b64Key).decodeFileAsyn(file, destFile); // } // } } static class Hex { private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; /** * 将字节数组转换为十六进制字符数组 * * @param data * byte[] * @return 十六进制char[] */ public static char[] encodeHex(byte[] data) { return encodeHex(data, true); } /** * 将字节数组转换为十六进制字符数组 * * @param data * byte[] * @param toLowerCase * <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式 * @return 十六进制char[] */ public static char[] encodeHex(byte[] data, boolean toLowerCase) { return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); } /** * 将字节数组转换为十六进制字符数组 * * @param data * byte[] * @param toDigits * 用于控制输出的char[] * @return 十六进制char[] */ protected static char[] encodeHex(byte[] data, char[] toDigits) { int l = data.length; char[] out = new char[l << 1]; // two characters form the hex value. for (int i = 0, j = 0; i < l; i++) { out[j++] = toDigits[(0xF0 & data[i]) >>> 4]; out[j++] = toDigits[0x0F & data[i]]; } return out; } /** * 将字节数组转换为十六进制字符串 * * @param data * byte[] * @return 十六进制String */ public static String encodeHexStr(byte[] data) { return encodeHexStr(data, true); } /** * 将字节数组转换为十六进制字符串 * * @param data * byte[] * @param toLowerCase * <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式 * @return 十六进制String */ public static String encodeHexStr(byte[] data, boolean toLowerCase) { return encodeHexStr(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); } /** * 将字节数组转换为十六进制字符串 * * @param data * byte[] * @param toDigits * 用于控制输出的char[] * @return 十六进制String */ protected static String encodeHexStr(byte[] data, char[] toDigits) { return new String(encodeHex(data, toDigits)); } /** * 将十六进制字符数组转换为字节数组 * * @param data * 十六进制char[] * @return byte[] * @throws RuntimeException * 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常 */ public static byte[] decodeHex(char[] data) { int len = data.length; if ((len & 0x01) != 0) { throw new RuntimeException("Odd number of characters."); } byte[] out = new byte[len >> 1]; // two characters form the hex value. for (int i = 0, j = 0; j < len; i++) { int f = toDigit(data[j], j) << 4; j++; f = f | toDigit(data[j], j); j++; out[i] = (byte) (f & 0xFF); } return out; } /** * 将十六进制字符转换成一个整数 * * @param ch * 十六进制char * @param index * 十六进制字符在字符数组中的位置 * @return 一个整数 * @throws RuntimeException * 当ch不是一个合法的十六进制字符时,抛出运行时异常 */ private static int toDigit(char ch, int index) { int digit = Character.digit(ch, 16); if (digit == -1) { throw new RuntimeException("Illegal hexadecimal character " + ch + " at index " + index); } return digit; } public static String bytes2Hex(byte[] inbuf) { int i; String byteStr; StringBuffer strBuf = new StringBuffer(); for (i = 0; i < inbuf.length; i++) { byteStr = Integer.toHexString(inbuf[i] & 0x00ff); if (byteStr.length() != 2) { strBuf.append('0').append(byteStr); } else { strBuf.append(byteStr); } } return new String(strBuf); } public static byte[] hexToBytes(String inbuf) { int i; int len = inbuf.length() / 2; byte outbuf[] = new byte[len]; for (i = 0; i < len; i++) { String tmpbuf = inbuf.substring(i * 2, i * 2 + 2); outbuf[i] = (byte) Integer.parseInt(tmpbuf, 16); } return outbuf; } } static class StreamUtils { public static void close(InputStream inputStream) { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { } } } public static void close(InputStream... inputStreams) { if (inputStreams != null && inputStreams.length > 0) { for (InputStream is : inputStreams) { if (is != null) { try { is.close(); } catch (IOException e) { } } } } } public static void close(InputStream inputStream, OutputStream... outputStreams) { try { if (inputStream != null) inputStream.close(); } catch (IOException e) { } if (outputStreams != null && outputStreams.length > 0) { for (OutputStream os : outputStreams) { if (os != null) { try { os.close(); } catch (IOException e) { } } } } } public static void close(OutputStream outputStream) { if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { } } } public static void close(OutputStream... outputStreams) { if (outputStreams != null && outputStreams.length > 0) { for (OutputStream os : outputStreams) { if (os != null) { try { os.close(); } catch (IOException e) { } } } } } public static void close(OutputStream outputStream, InputStream... inputStreams) { if (inputStreams != null && inputStreams.length > 0) { for (InputStream is : inputStreams) { if (is != null) { try { is.close(); } catch (IOException e) { } } } } try { if (outputStream != null) outputStream.close(); } catch (IOException e) { } } public static void close(InputStream inputStream, OutputStream outputStream) { try { if (inputStream != null) inputStream.close(); if (outputStream != null) outputStream.close(); } catch (IOException e) { } } public static void close(AutoCloseable... closeables) { if (closeables != null && closeables.length > 0) { for (AutoCloseable ac : closeables) { if (ac != null) { try { ac.close(); } catch (Exception e) { } } } } } } static class B64Encrypter { static final String DEFAULT_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; private static Map<String, B64Encrypter> coderMap = new HashMap<String, B64Encrypter>(); private static char[] defaultEncodeChars = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; private static byte[] defaultDecodeChars = new byte[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 }; static { coderMap.put(DEFAULT_ALPHABET, new B64Encrypter(defaultEncodeChars, defaultDecodeChars)); } private char[] base64EncodeChars; private byte[] base64DecodeChars; private B64Encrypter(char[] base64EncodeChars, byte[] base64DecodeChars) { this.base64EncodeChars = base64EncodeChars; this.base64DecodeChars = base64DecodeChars; } public String encode(byte[] data) { StringBuffer sb = new StringBuffer(); int len = data.length; int i = 0; int b1, b2, b3; while (i < len) { b1 = data[i++] & 0xff; if (i == len) { sb.append(base64EncodeChars[b1 >>> 2]); sb.append(base64EncodeChars[(b1 & 0x3) << 4]); sb.append("**"); break; } b2 = data[i++] & 0xff; if (i == len) { sb.append(base64EncodeChars[b1 >>> 2]); sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]); sb.append(base64EncodeChars[(b2 & 0x0f) << 2]); sb.append("*"); break; } b3 = data[i++] & 0xff; sb.append(base64EncodeChars[b1 >>> 2]); sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]); sb.append(base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]); sb.append(base64EncodeChars[b3 & 0x3f]); } return sb.toString(); } public byte[] decode(String str) throws UnsupportedEncodingException { StringBuffer sb = new StringBuffer(); byte[] data = str.getBytes(Charset.ASCII.VALUE); int len = data.length; int i = 0; int b1, b2, b3, b4; while (i < len) { /* b1 */ do { b1 = base64DecodeChars[data[i++]]; } while (i < len && b1 == -1); if (b1 == -1) break; /* b2 */ do { b2 = base64DecodeChars[data[i++]]; } while (i < len && b2 == -1); if (b2 == -1) break; sb.append((char) ((b1 << 2) | ((b2 & 0x30) >>> 4))); /* b3 */ do { b3 = data[i++]; if (b3 == 61) return sb.toString().getBytes(Charset.ISO8859_1.VALUE); b3 = base64DecodeChars[b3]; } while (i < len && b3 == -1); if (b3 == -1) break; sb.append((char) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2))); /* b4 */ do { b4 = data[i++]; if (b4 == 61) return sb.toString().getBytes(Charset.ISO8859_1.VALUE); b4 = base64DecodeChars[b4]; } while (i < len && b4 == -1); if (b4 == -1) break; sb.append((char) (((b3 & 0x03) << 6) | b4)); } return sb.toString().getBytes(Charset.ISO8859_1.VALUE); } public static boolean checkAlphabet(String alphabet) { if (StringUtils.isBlank(alphabet) || alphabet.length() != 64) return false; byte[] temp = new byte[128]; for (int i = 0; i < 64; i++) { if (temp[alphabet.charAt(i)] > 0) { return false; } temp[alphabet.charAt(i)] = 1; } return true; } public static B64Encrypter getInstance() { return getInstance(DEFAULT_ALPHABET); } public static B64Encrypter getInstance(String alphabet) { if (!checkAlphabet(alphabet)) return null; B64Encrypter coder = coderMap.get(alphabet); if (coder == null) { char[] encodeChar = new char[64]; byte[] decodeChar = new byte[128]; for (int i = 0; i < 64; i++) { encodeChar[i] = alphabet.charAt(i); decodeChar[encodeChar[i]] = Integer.valueOf(i).byteValue(); } coder = new B64Encrypter(encodeChar, decodeChar); coderMap.put(alphabet, coder); } return coder; } public static String encrypt(byte[] plainText) { return plainText == null ? null : getInstance().encode(plainText); } public static byte[] decrypt(String ciphertext) throws UnsupportedEncodingException { return StringUtils.isBlank(ciphertext) ? null : getInstance().decode(ciphertext); } }}
0 0
- AES LINUX加密结果不一致
- Linux操作系统下每次AES加密结果不一致的原因
- AES加密算法在Linux下出现随机加密结果
- MD5加密中文结果不一致
- Java中中文MD5加密结果不一致
- AES加密算法在linux下相同输入每次加密结果都不同的问题
- AES加密解密Windows下跟linux下结果不同的解决方案
- AES加密解密Windows下跟linux下结果不同的解决方案
- 加密算法 AES Windows和linux 解密不一致问题
- MD5CryptoServiceProvider的MD5加密结果和百度不一致
- nodejs和java的AES加密结果保持一致
- java windows linux BASE64Encoder 加密汉字不一致
- JAVA aes加密在linux中的问题
- AES加密(兼容linux和windows)
- AES加密在linux上的问题
- 使用openssl 生成AES加密并且对加密结果进行base64加密
- AES加密
- AES加密
- linux下jps命令找不到的问题
- ZeroC Ice Ice Registry实现负载均衡
- 关于快速排序与归并排序
- Android关于安兔兔手机信息造假的问题。
- 项目管理和构建】十分钟教程,eclipse配置maven + 创建maven项目
- AES LINUX加密结果不一致
- Redis Cluster 源码分析
- (java office转pdf) MS Office2010、WPS2015、OpenOffice4用Java将Office文档转换为PDF,WIN7 64位系统
- 【leetcode】candy
- linux下安装mysql
- 8421码
- ZeroC Ice IceGrid Node和IceGrid
- node项目在服务器的部署
- webSocket与html区别,以及服务端与客户端消息通讯利用webSocket