Java tutorial
/* * Copyright 2015 dactiv * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.dactiv.fear.commons; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; /** * * Java Discuz! iv * * @author maurice */ public class AuthCoder { /** * ? */ public final static int DEFAULT_RANDOM_KEY_LENGTH = 4; /** * ? */ public final static String DEFAULT_VALUE_ENCODING = "UTF-8"; /** * ? */ public final static int DEFAULT_EXPIRY = 0; /** * * * @param value ? * @param key * @return ? * @throws UnsupportedEncodingException */ public static String decode(String value, String key) throws UnsupportedEncodingException { return decode(value, key, DEFAULT_RANDOM_KEY_LENGTH); } /** * * @param value ? * @param key * @param randomKeyLength ? ? 0-32???? * ???iv?? * ? = 16 randomKeyLength 0 ?? * @return ? * @throws UnsupportedEncodingException */ public static String decode(String value, String key, int randomKeyLength) throws UnsupportedEncodingException { return decode(value, key, randomKeyLength, DEFAULT_VALUE_ENCODING); } /** * * @param value ? * @param key * @param encoding ? * @return ? * @throws UnsupportedEncodingException */ public static String decode(String value, String key, String encoding) throws UnsupportedEncodingException { return decode(value, key, DEFAULT_RANDOM_KEY_LENGTH, encoding); } /** * * * @param value ? * @param key * @param randomKeyLength ? ? 0-32???? * ???iv?? * ? = 16 randomKeyLength 0 ?? * @param encoding ? * @return ? */ public static String decode(String value, String key, int randomKeyLength, String encoding) throws UnsupportedEncodingException { key = DigestUtils.md5Hex(key.getBytes()); String keya = DigestUtils.md5Hex(StringUtils.substring(key, 0, 16).getBytes()); String keyb = DigestUtils.md5Hex(StringUtils.substring(key, 16, 16 + 16).getBytes()); String keyc = randomKeyLength > 0 ? StringUtils.substring(value, 0, randomKeyLength) : ""; String cryptKey = keya + DigestUtils.md5Hex((keya + keyc).getBytes()); int cryptKeyLen = cryptKey.length(); value = new String(Base64.decodeBase64((StringUtils.substring(value, randomKeyLength))), encoding); int stringLen = value.length(); List<Integer> rndKey = new ArrayList<>(); StringBuilder result = new StringBuilder(); Integer[] box = new Integer[256]; for (int i = 0; i < box.length; i++) { box[i] = i; } for (int i = 0; i <= 255; i++) { rndKey.add((int) cryptKey.charAt(i % cryptKeyLen)); } for (int j = 0, i = 0; i < 256; i++) { j = (j + box[i] + rndKey.get(i)) % 256; int tmp = box[i]; box[i] = box[j]; box[j] = tmp; } for (int k = 0, j = 0, i = 0; i < stringLen; i++) { k = (k + 1) % 256; j = (j + box[k]) % 256; int tmp = box[k]; box[k] = box[j]; box[j] = tmp; int a = (int) value.charAt(i); int b = box[(box[k] + box[j]) % 256]; char r = (char) (a ^ b); result.append(r); } if ((NumberUtils.toInt(StringUtils.substring(result.toString(), 0, 10), -1) == 0 || NumberUtils.toInt(StringUtils.substring(result.toString(), 0, 10), 0) - System.currentTimeMillis() / 1000 > 0) && StringUtils.substring(result.toString(), 10, 10 + 16) .equals(StringUtils.substring( DigestUtils .md5Hex((StringUtils.substring(result.toString(), 26) + keyb).getBytes()), 0, 16))) { return StringUtils.substring(result.toString(), 26); } else { return ""; } } /** * * * @param value ? * @param key * @return ? * @throws UnsupportedEncodingException */ public static String encode(String value, String key) throws UnsupportedEncodingException { return encode(value, key, DEFAULT_EXPIRY); } /** * * * @param value ? * @param key * @param expiry * @return ? * @throws UnsupportedEncodingException */ public static String encode(String value, String key, int expiry) throws UnsupportedEncodingException { return encode(value, key, expiry, DEFAULT_RANDOM_KEY_LENGTH, DEFAULT_VALUE_ENCODING); } /** * * * @param value ? * @param key * @param expiry * @param randomKeyLength ? ? 0-32???? * ???iv?? * ? = 16 randomKeyLength 0 ?? * @return ? * @throws UnsupportedEncodingException */ public static String encode(String value, String key, int expiry, int randomKeyLength) throws UnsupportedEncodingException { return encode(value, key, expiry, randomKeyLength, DEFAULT_VALUE_ENCODING); } /** * * @param value ? * @param key * @param expiry * @param encoding ? * * @return ? * @throws UnsupportedEncodingException */ public static String encode(String value, String key, int expiry, String encoding) throws UnsupportedEncodingException { return encode(value, key, expiry, DEFAULT_RANDOM_KEY_LENGTH, encoding); } /** * * * @param value ? * @param key * @param expiry * @param randomKeyLength ? ? 0-32???? * ???iv?? * ? = 16 randomKeyLength 0 ?? * @param encoding ? * @return ? * @throws UnsupportedEncodingException */ public static String encode(String value, String key, int expiry, int randomKeyLength, String encoding) throws UnsupportedEncodingException { key = DigestUtils.md5Hex(key.getBytes()); String keya = DigestUtils.md5Hex(StringUtils.substring(key, 0, 16).getBytes()); String keyb = DigestUtils.md5Hex(StringUtils.substring(key, 16, 16 + 16).getBytes()); String keyc = randomKeyLength > 0 ? StringUtils.substring( DigestUtils.md5Hex(String.valueOf(System.currentTimeMillis() / 1000).getBytes()), -randomKeyLength) : ""; String cryptKey = keya + DigestUtils.md5Hex((keya + keyc).getBytes()); int cryptKeyLen = cryptKey.length(); value = String.format("%010d", expiry > 0 ? expiry + System.currentTimeMillis() / 1000 : 0) + StringUtils.substring(DigestUtils.md5Hex((value + keyb).getBytes()), 0, 16) + value; int stringLen = value.length(); List<Integer> rndKey = new ArrayList<>(); StringBuilder result = new StringBuilder(); Integer[] box = new Integer[256]; for (int i = 0; i < box.length; i++) { box[i] = i; } for (int i = 0; i <= 255; i++) { rndKey.add((int) cryptKey.charAt(i % cryptKeyLen)); } for (int j = 0, i = 0; i < 256; i++) { j = (j + box[i] + rndKey.get(i)) % 256; int tmp = box[i]; box[i] = box[j]; box[j] = tmp; } for (int k = 0, j = 0, i = 0; i < stringLen; i++) { k = (k + 1) % 256; j = (j + box[k]) % 256; int tmp = box[k]; box[k] = box[j]; box[j] = tmp; int a = (int) value.charAt(i); int b = box[(box[k] + box[j]) % 256]; char r = (char) (a ^ b); result.append(r); } return keyc + Base64.encodeBase64String(result.toString().getBytes(encoding)).replaceAll("=", ""); } }