diff --git a/README.md b/README.md index 6e68812..7a9c04d 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,12 @@ - [ ] 登录, 上传, 下载, 分享 - [x] 直链解析 - UC网盘 (uc) - - [ ] 登录, 上传, 下载, 分享 - - [x] 直链解析 + - [ ] 登录, 上传, 下载, 分享 + - [x] 直链解析 +- 小飞机网盘 (fj) + - [ ] 登录, 上传, 下载, 分享 + - [x] 直链解析 +- 文叔叔 (ws) - 夸克网盘 (qk) - TODO @@ -30,7 +34,7 @@ API接口 http(s)://you_host/网盘标识/分享id(#分享密码) 2. 获取解析后的直链--JSON格式 http(s)://you_host/json/网盘标识/分享id(#分享密码) - +3. 有些网盘的加密分享的密码可以忽略: 如移动云空间,小飞机网盘 ``` @@ -63,11 +67,12 @@ TODO: # 网盘对比 -| 网盘名称 | 可直接下载分享 | 加密分享 | 初始网盘空间 | 单文件大小限制 | 登录接口 | -|-------|-------------|----------|----------|----------------|------| -| 蓝奏云 | √ | √ | 不限空间 | 100M | TODO | -| 奶牛快传 | √ | X | 10G | 不限大小 | TODO | -| 移动云空间 | √ | √(密码可忽略) | 5G(个人) | 不限大小 | TODO | -| UC网盘 | √ | √ | 10G | 不限大小 | TODO | -| 夸克网盘 | √(>10M需要登录) | √ | 10G(20G) | 不限大小(>10M需要登录) | X | +| 网盘名称 | 可直接下载分享 | 加密分享 | 初始网盘空间 | 单文件大小限制 | 登录接口 | +|------------|---------|----------|----------|---------|------| +| 蓝奏云 | √ | √ | 不限空间 | 100M | TODO | +| 奶牛快传 | √ | X | 10G | 不限大小 | TODO | +| 移动云空间 | √ | √(密码可忽略) | 5G(个人) | 不限大小 | TODO | +| UC网盘 | √ | √ | 10G | 不限大小 | TODO | +| 小飞机网盘 | √ | √(密码可忽略) | 10G | 不限大小 | TODO | +| 夸克网盘(TODO) | 需要登录 | √ | 10G(20G) | 不限大小 | TODO | diff --git a/web-service/src/main/java/cn/qaiu/lz/common/util/AESUtils.java b/web-service/src/main/java/cn/qaiu/lz/common/util/AESUtils.java new file mode 100644 index 0000000..630e7e2 --- /dev/null +++ b/web-service/src/main/java/cn/qaiu/lz/common/util/AESUtils.java @@ -0,0 +1,239 @@ +package cn.qaiu.lz.common.util; + +import org.apache.commons.lang3.StringUtils; + +import javax.crypto.*; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.HexFormat; + +/** + * AES加解密工具类 + * + * @author qaiu + **/ +public class AESUtils { + + /** + * AES密钥标识 + */ + public static final String SIGN_AES = "AES"; + + /** + * 密码器AES模式 + */ + public static final String CIPHER_AES = "AES/ECB/PKCS5Padding"; + + public static final String CIPHER_AES2 = "YbQHZqK/PdQql2+7ATcPQHREAxt0Hn0Ob9v317QirZM="; + + public static final String CIPHER_AES0; + + /** + * 秘钥长度 + */ + public static final int KEY_LENGTH = 16; + + /** + * 密钥长度128 + */ + public static final int KEY_SIZE_128_LENGTH = 128; + + /** + * 密钥长度192 + */ + public static final int KEY_SIZE_192_LENGTH = 192; + + /** + * 密钥长度256 + */ + public static final int KEY_SIZE_256_LENGTH = 256; + + static { + try { + CIPHER_AES0 = decryptByBase64AES(CIPHER_AES2, CIPHER_AES); + } catch (IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException | NoSuchAlgorithmException | + InvalidKeyException e) { + throw new RuntimeException(e); + } + } + + /** + * 随机生成密钥,请使用合适的长度128 192 256 + */ + public static Key createKeyString(int keySize) throws NoSuchAlgorithmException { + KeyGenerator keyGenerator = KeyGenerator.getInstance(SIGN_AES); + keyGenerator.init(keySize); + SecretKey secretKey = keyGenerator.generateKey(); + return new SecretKeySpec(secretKey.getEncoded(), SIGN_AES); + } + + /** + * 生成Key对象 + */ + public static Key generateKey(String keyString) { + if (keyString.length() > KEY_LENGTH) { + keyString = keyString.substring(0, KEY_LENGTH); + } else if (keyString.length() < KEY_LENGTH) { + keyString = StringUtils.rightPad(keyString, 16, 'L'); + } + return new SecretKeySpec(keyString.getBytes(), SIGN_AES); + } + + /** + * AES加密 + * + * @param source 原文 + * @param keyString 秘钥 + * @return byte arrays + */ + public static byte[] encryptByAES(String source, String keyString) throws NoSuchPaddingException, + NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { + Cipher cipher = Cipher.getInstance(CIPHER_AES); + cipher.init(Cipher.ENCRYPT_MODE, generateKey(keyString)); + return cipher.doFinal(source.getBytes(StandardCharsets.UTF_8)); + } + + public static byte[] encryptByAES(String source, Key key) throws NoSuchPaddingException, + NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { + Cipher cipher = Cipher.getInstance(CIPHER_AES); + cipher.init(Cipher.ENCRYPT_MODE, key); + return cipher.doFinal(source.getBytes(StandardCharsets.UTF_8)); + } + + /** + * AES加密Base64 + * + * @param source 原文 + * @param keyString 秘钥 + * @return BASE64 + */ + public static String encryptBase64ByAES(String source, String keyString) throws NoSuchPaddingException, + NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { + byte[] encrypted = encryptByAES(source, keyString); + return Base64.getEncoder().encodeToString(encrypted); + } + + public static String encryptBase64ByAES(String source, Key key) throws NoSuchPaddingException, + NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { + byte[] encrypted = encryptByAES(source, key); + return Base64.getEncoder().encodeToString(encrypted); + } + + /** + * AES加密Hex + * + * @param source 原文 + * @param keyString 秘钥 + */ + public static String encryptHexByAES(String source, String keyString) throws NoSuchPaddingException, + NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { + byte[] encrypted = encryptByAES(source, keyString); + return HexFormat.of().formatHex(encrypted); + } + + public static String encryptHexByAES(String source, Key key) throws NoSuchPaddingException, + NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { + byte[] encrypted = encryptByAES(source, key); + return HexFormat.of().formatHex(encrypted); + } + + public static String encrypt2Hex(String source) { + try { + return encryptHexByAES(source, CIPHER_AES0); + } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | + BadPaddingException e) { + throw new RuntimeException("加密失败: "+ e.getMessage()); + } + } + + /** + * AES解密 + * + * @param encrypted 密文 byte + * @param keyString 秘钥 + */ + public static String decryptByAES(byte[] encrypted, String keyString) throws IllegalBlockSizeException, + BadPaddingException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException { + return decryptByAES(encrypted, generateKey(keyString)); + } + + public static String decryptByAES(byte[] encrypted, Key key) throws IllegalBlockSizeException, + BadPaddingException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException { + Cipher cipher = Cipher.getInstance(CIPHER_AES); + cipher.init(Cipher.DECRYPT_MODE, key); + byte[] decrypted = cipher.doFinal(encrypted); + return new String(decrypted, StandardCharsets.UTF_8); + } + + /** + * AES解密 + * + * @param encrypted 密文 Hex + * @param keyString 秘钥 + */ + public static String decryptByHexAES(String encrypted, String keyString) throws IllegalBlockSizeException, + BadPaddingException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException { + return decryptByAES(HexFormat.of().parseHex(encrypted), keyString); + } + + public static String decryptByHexAES(String encrypted, Key key) throws IllegalBlockSizeException, + BadPaddingException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException { + return decryptByAES(HexFormat.of().parseHex(encrypted), key); + } + + /** + * AES解密 + * + * @param encrypted 密文 Base64 + * @param keyString 秘钥 + */ + public static String decryptByBase64AES(String encrypted, String keyString) throws IllegalBlockSizeException, + BadPaddingException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException { + return decryptByAES(Base64.getDecoder().decode(encrypted), keyString); + } + + public static String decryptByBase64AES(String encrypted, Key key) throws IllegalBlockSizeException, + BadPaddingException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException { + return decryptByAES(Base64.getDecoder().decode(encrypted), key); + } + + // ================================飞机盘Id解密========================================== // + private static final char[] array = { + 'T', 'U', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + '0', 'M', 'N', 'O', 'P', 'X', 'Y', 'Z', 'V', 'W', + 'Q', '1', '2', '3', '4', 'a', 'b', 'c', 'd', 'e', + '5', '6', '7', '8', '9', 'v', 'w', 'x', 'y', 'z', + 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'L', 'R', 'S', 'I', + 'J', 'K'}; + + private static int decodeChar(char c) { + for (int i = 0; i < array.length; i++) { + if (c == array[i]) { + return i; + } + } + return -1; + } + + // id解密 + public static int idEncrypt(String str) { + // 倍数 + int multiple = 1; + int result = 0; + if (StringUtils.isNotEmpty(str) && str.length() > 4) { + str = str.substring(2, str.length() - 2); + char c; + for (int i = 0; i < str.length(); i++) { + c = str.charAt(str.length() - i - 1); + result += decodeChar(c) * multiple; + multiple = multiple * 62; + } + } + return result; + } +} diff --git a/web-service/src/main/java/cn/qaiu/lz/common/util/CommonUtils.java b/web-service/src/main/java/cn/qaiu/lz/common/util/CommonUtils.java new file mode 100644 index 0000000..78f5f46 --- /dev/null +++ b/web-service/src/main/java/cn/qaiu/lz/common/util/CommonUtils.java @@ -0,0 +1,11 @@ +package cn.qaiu.lz.common.util; + +public class CommonUtils { + + public static String parseURL(String urlPrefix, String url) { + if (!url.startsWith(urlPrefix)) { + url = urlPrefix + url; + } + return url.substring(urlPrefix.length()); + } +} diff --git a/web-service/src/main/java/cn/qaiu/lz/common/util/ConnectUtil.java b/web-service/src/main/java/cn/qaiu/lz/common/util/ConnectUtil.java deleted file mode 100644 index 0ea396a..0000000 --- a/web-service/src/main/java/cn/qaiu/lz/common/util/ConnectUtil.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.qaiu.lz.common.util; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * 获取连接 - * - * @author QAIU - */ -public enum ConnectUtil { - - // 实现枚举单例 - INSTANCE; - - private static final Logger LOGGER = LoggerFactory.getLogger(ConnectUtil.class); - - -} diff --git a/web-service/src/main/java/cn/qaiu/lz/common/util/EcTool.java b/web-service/src/main/java/cn/qaiu/lz/common/util/EcTool.java index 8697146..b9df23a 100644 --- a/web-service/src/main/java/cn/qaiu/lz/common/util/EcTool.java +++ b/web-service/src/main/java/cn/qaiu/lz/common/util/EcTool.java @@ -14,7 +14,7 @@ import lombok.extern.slf4j.Slf4j; */ @Slf4j public class EcTool { - private static final String FULL_URL_PREFIX = "https://www.ecpan.cn/drive/fileextoverrid" + + private static final String SHARE_URL_PREFIX = "https://www.ecpan.cn/drive/fileextoverrid" + ".do?chainUrlTemplate=https:%2F%2Fwww.ecpan" + ".cn%2Fweb%2F%23%2FyunpanProxy%3Fpath%3D%252F%2523%252Fdrive%252Foutside&parentId=-1&data={dataKey}"; @@ -26,7 +26,7 @@ public class EcTool { Promise promise = Promise.promise(); WebClient client = WebClient.create(VertxHolder.getVertxInstance()); // 第一次请求 获取文件信息 - client.getAbs(UriTemplate.of(FULL_URL_PREFIX)).setTemplateParam("dataKey", dataKey).send().onSuccess(res -> { + client.getAbs(UriTemplate.of(SHARE_URL_PREFIX)).setTemplateParam("dataKey", dataKey).send().onSuccess(res -> { JsonObject jsonObject = res.bodyAsJsonObject(); log.debug("ecPan get file info -> {}", jsonObject); JsonObject fileInfo = jsonObject diff --git a/web-service/src/main/java/cn/qaiu/lz/common/util/FjTool.java b/web-service/src/main/java/cn/qaiu/lz/common/util/FjTool.java new file mode 100644 index 0000000..34b00f6 --- /dev/null +++ b/web-service/src/main/java/cn/qaiu/lz/common/util/FjTool.java @@ -0,0 +1,75 @@ +package cn.qaiu.lz.common.util; + +import cn.qaiu.vx.core.util.VertxHolder; +import io.vertx.core.Future; +import io.vertx.core.MultiMap; +import io.vertx.core.Promise; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.client.WebClient; +import io.vertx.ext.web.client.WebClientOptions; +import io.vertx.uritemplate.UriTemplate; + +import java.util.UUID; + +/** + * 小飞机网盘 + * + * @version V016_230609 + */ +public class FjTool { + + public static final String SHARE_URL_PREFIX = "https://www.feijix.com/s/"; + private static final String API_URL_PREFIX = "https://api.feijipan.com/ws/"; + + private static final String FIRST_REQUEST_URL = API_URL_PREFIX + "recommend/list?devType=6&devModel=Chrome&extra" + + "=2&shareId={shareId}&type=0&offset=1&limit=60"; + + private static final String SECOND_REQUEST_URL = API_URL_PREFIX + "file/redirect?downloadId={fidEncode}&enable=1" + + "&devType=6&uuid={uuid}×tamp={ts}&auth={auth}"; + + public static Future parse(String data) { + String dataKey = CommonUtils.parseURL(SHARE_URL_PREFIX, data); + + Promise promise = Promise.promise(); + WebClient client = WebClient.create(VertxHolder.getVertxInstance(), + new WebClientOptions().setFollowRedirects(false)); + String shareId = String.valueOf(AESUtils.idEncrypt(dataKey)); + + // 第一次请求 获取文件信息 + // POST https://api.feijipan.com/ws/recommend/list?devType=6&devModel=Chrome&extra=2&shareId=146731&type=0&offset=1&limit=60 + client.postAbs(UriTemplate.of(FIRST_REQUEST_URL)).setTemplateParam("shareId", shareId).send().onSuccess(res -> { + JsonObject resJson = res.bodyAsJsonObject(); + if (resJson.getInteger("code") != 200) { + promise.fail(FIRST_REQUEST_URL + " 返回异常: " + resJson); + return; + } + if (resJson.getJsonArray("list").size() == 0) { + promise.fail(FIRST_REQUEST_URL + " 解析文件列表为空: " + resJson); + return; + } + // 文件Id + String fileId = resJson.getJsonArray("list").getJsonObject(0).getString("fileIds"); + // 其他参数 + long nowTs = System.currentTimeMillis(); + String tsEncode = AESUtils.encrypt2Hex(Long.toString(nowTs)); + String uuid = UUID.randomUUID().toString(); + String fidEncode = AESUtils.encrypt2Hex(fileId + "|"); + String auth = AESUtils.encrypt2Hex(fileId + "|" + nowTs); + // 第二次请求 + client.getAbs(UriTemplate.of(SECOND_REQUEST_URL)) + .setTemplateParam("fidEncode", fidEncode) + .setTemplateParam("uuid", uuid) + .setTemplateParam("ts", tsEncode) + .setTemplateParam("auth", auth).send().onSuccess(res2 -> { + MultiMap headers = res2.headers(); + if (!headers.contains("Location")) { + promise.fail(SECOND_REQUEST_URL + " 未找到重定向URL: \n" + res.headers()); + return; + } + promise.complete(headers.get("Location")); + }); + }); + + return promise.future(); + } +} diff --git a/web-service/src/main/java/cn/qaiu/lz/common/util/UcTool.java b/web-service/src/main/java/cn/qaiu/lz/common/util/UcTool.java index 4a7f688..d49bcb3 100644 --- a/web-service/src/main/java/cn/qaiu/lz/common/util/UcTool.java +++ b/web-service/src/main/java/cn/qaiu/lz/common/util/UcTool.java @@ -16,7 +16,7 @@ import lombok.extern.slf4j.Slf4j; public class UcTool { private static final String API_URL_PREFIX = "https://pc-api.uc.cn/1/clouddrive/"; - public static final String FULL_URL_PREFIX = "https://fast.uc.cn/s/"; + public static final String SHARE_URL_PREFIX = "https://fast.uc.cn/s/"; private static final String FIRST_REQUEST_URL = API_URL_PREFIX + "share/sharepage/token?entry=ft&fr=pc&pr" + "=UCBrowser"; @@ -27,11 +27,8 @@ public class UcTool { private static final String THIRD_REQUEST_URL = API_URL_PREFIX + "file/download?entry=ft&fr=pc&pr=UCBrowser"; public static Future parse(String data, String code) { - if (!data.startsWith(FULL_URL_PREFIX)) { - data = FULL_URL_PREFIX + data; - } + var dataKey = CommonUtils.parseURL(SHARE_URL_PREFIX, data); var passcode = (code == null) ? "" : code; - var dataKey = data.substring(FULL_URL_PREFIX.length()); Promise promise = Promise.promise(); var client = WebClient.create(VertxHolder.getVertxInstance()); var jsonObject = JsonObject.of("share_for_transfer", true); diff --git a/web-service/src/main/java/cn/qaiu/lz/common/util/WoTools.java b/web-service/src/main/java/cn/qaiu/lz/common/util/WoTools.java deleted file mode 100644 index 6fcef6c..0000000 --- a/web-service/src/main/java/cn/qaiu/lz/common/util/WoTools.java +++ /dev/null @@ -1,6 +0,0 @@ -package cn.qaiu.lz.common.util; - -public class WoTools { - - -} diff --git a/web-service/src/main/java/cn/qaiu/lz/web/http/ServerApi.java b/web-service/src/main/java/cn/qaiu/lz/web/http/ServerApi.java index 9bd0b6b..9d39128 100644 --- a/web-service/src/main/java/cn/qaiu/lz/web/http/ServerApi.java +++ b/web-service/src/main/java/cn/qaiu/lz/web/http/ServerApi.java @@ -1,9 +1,6 @@ package cn.qaiu.lz.web.http; -import cn.qaiu.lz.common.util.CowTool; -import cn.qaiu.lz.common.util.EcTool; -import cn.qaiu.lz.common.util.LzTool; -import cn.qaiu.lz.common.util.UcTool; +import cn.qaiu.lz.common.util.*; import cn.qaiu.lz.web.model.SysUser; import cn.qaiu.lz.web.service.UserService; import cn.qaiu.vx.core.annotaions.RouteHandler; @@ -74,13 +71,20 @@ public class ServerApi { }).onFailure(t -> { promise.fail(t.fillInStackTrace()); }); - } else if (url.contains(UcTool.FULL_URL_PREFIX)) { + } else if (url.contains(UcTool.SHARE_URL_PREFIX)) { UcTool.parse(url, pwd).onSuccess(resUrl -> { response.putHeader("location", resUrl).setStatusCode(302).end(); promise.complete(); }).onFailure(t -> { promise.fail(t.fillInStackTrace()); }); + } else if (url.contains(FjTool.SHARE_URL_PREFIX)) { + FjTool.parse(url).onSuccess(resUrl -> { + response.putHeader("location", resUrl).setStatusCode(302).end(); + promise.complete(); + }).onFailure(t -> { + promise.fail(t.fillInStackTrace()); + }); } return promise.future(); } @@ -155,4 +159,19 @@ public class ServerApi { } return UcTool.parse(id, code); } + + @RouteMapping(value = "/fj/:id", method = RouteMethod.GET) + public void fjParse(HttpServerResponse response, String id) { + FjTool.parse(id).onSuccess(resUrl -> { + response.putHeader("location", resUrl).setStatusCode(302).end(); + }).onFailure(t -> { + response.putHeader(CONTENT_TYPE, "text/html;charset=utf-8"); + response.end(t.getMessage()); + }); + } + + @RouteMapping(value = "/json/fj/:id", method = RouteMethod.GET) + public Future fjParseJson(HttpServerResponse response, String id) { + return FjTool.parse(id); + } } diff --git a/web-service/src/main/resources/http-tools/curl.sh b/web-service/src/main/resources/http-tools/curl.sh index 12c98d7..6a966ec 100644 --- a/web-service/src/main/resources/http-tools/curl.sh +++ b/web-service/src/main/resources/http-tools/curl.sh @@ -1,3 +1,3 @@ -curl -F "file=@C:\Users\qaiu\Desktop\real\lz-web\web\src\main\resources\logback.xml" -i -XPOST 127.0.0.1:8088/demo/basePointApi/importTags +curl -F "file=@C:\Users\qaiu\Desktop\real\lz-web\web\src\main\resources\logback.xml" -i -XPOST 127.0.0.1:6400/demo/XXX/XXX -curl -F "file=@C:\Users\qaiu\Desktop\3.csv" -i -XPOST 127.0.0.1:8088/demo/basePointApi/importTags +curl -F "file=@C:\Users\qaiu\Desktop\3.csv" -i -XPOST 127.0.0.1:6400/demo/XXX/XXX diff --git a/web-service/src/main/resources/http-tools/ecpan.http b/web-service/src/main/resources/http-tools/pan-ec.http similarity index 100% rename from web-service/src/main/resources/http-tools/ecpan.http rename to web-service/src/main/resources/http-tools/pan-ec.http diff --git a/web-service/src/main/resources/http-tools/lz.http b/web-service/src/main/resources/http-tools/pan-lz.http similarity index 100% rename from web-service/src/main/resources/http-tools/lz.http rename to web-service/src/main/resources/http-tools/pan-lz.http diff --git a/web-service/src/main/resources/http-tools/test.http b/web-service/src/main/resources/http-tools/test.http index c371799..c2dc270 100644 --- a/web-service/src/main/resources/http-tools/test.http +++ b/web-service/src/main/resources/http-tools/test.http @@ -93,9 +93,9 @@ Content-Type: application/json < ./request-form-data.json --WebAppBoundary-- -### +### https://www.ecpan.cn/web/#/yunpanProxy?path=%2F%23%2Fdrive%2Foutside&data=81027a5c99af5b11ca004966c945cce6W9Bf2&isShare=1 # @no-redirect -GET http://127.0.0.1:6400/parser?url=https://www.ecpan.cn/web/#/yunpanProxy?path=%2F%23%2Fdrive%2Foutside&data=81027a5c99af5b11ca004966c945cce6W9Bf2&isShare= +GET http://127.0.0.1:6400/parser?url=https://www.ecpan.cn/web/#/yunpanProxy?path=%2F%23%2Fdrive%2Foutside&data=81027a5c99af5b11ca004966c945cce6W9Bf2&isShare=1 # https://www.ecpan.cn/drive/fileextoverrid.do?chainUrlTemplate=https://www.ecpan.cn/web/#/yunpanProxy?path=%2F%23%2Fdrive%2Foutside&data=aa0cae0164d8885e6d35826b5b2901eckbWJBalM&parentId=-1 ### @@ -127,3 +127,15 @@ action=downprocess&sign=AGYHOQk4BjdTWgQ7BzcGOlU_bATVSNQMxBDFQZgZoBj4HMFEgWnMOZ1I https://developer.lanzoug.com/file/?VDJbZVxtADFSWwY+U2YHa1FuU2tTYgBnBnUGZFNmWylSOVMpCTJQZQQhBSdQKQFkBjMOfAMyA21VPVs8V28BLVRkWyJcMAB6UjcGfVNlB29RZVN4U3YAawZxBiZTaVszUj5TYQkLUG0ENgVuUDUBMQZkDjsDbgMxVWBbZFc8ASZUMlt/XDwAZVIyBmFTNwc3UTtTYFM8ACQGcQZwUzJbaFJiUzYJZ1ArBGIFZlArATIGaQ4kAz8DMlVnWz9XMwE1VGZbOFw3AG1SPQY0UzcHMVFqUzdTbwBmBjEGMVNsW2NSM1MzCWxQNwRkBWVQNwEwBmQOPwNyA3tVO1stVy0BdVQnW2lccwA9UmAGbVM2BzZRPlNvUzgAOwY5BiZTe1szUj9TYQkyUDkEYwVjUDQBMAZsDiUDcgMnVTRbMVd8AT1UZVs6XDkAYVI0BmBTNQc/UTlTZVMqAHcGcQZ3UzJba1JkUzwJYVA0BGIFYVA0ATAGaw4tAykDaFUiW2BXOgExVGZbIlwzAGdSNgZ%2BUzYHMlE9U3hTOwA6 ### https://developer.lanzoug.com/file/?VTNVa1tqAjMFDAM7BDEAbAE+U2tfbgZhBnVbOQUwVCYEb1IoAToCNwQhVnRXLlcyVWAEdl9uVzkEbFYxVm5VeVVlVSxbNwJ4BWADeAQyAGgBNVN4X3oGbQZxW3sFP1Q8BGhSYAEDAj8ENlY9VzJXZ1U3BDFfMldlBDFWaVY9VXJVM1VxWzsCZwVlA2QEYAAwAWtTYF8wBiIGcVstBWRUZwQ0UjcBbwJ5BGJWNVcsV2RVOgQuX2NXZgQ2VjJWMlVhVWdVNlswAm8FagMxBGAANgE6UzdfYwZgBjFbbAU6VGwEZVIyAWQCZQRkVjZXMFdmVTcENV8uVy8EalYgVixVIVUmVWdbdAI/BTcDaARhADEBblNvXzQGPQY5W3sFLVQ8BGlSYAE6AmsEY1Y2VztXY1U/BDFfM1dnBDRWZFYkVXpVc1VkW2oCIQVuA2QEZgA5AW5TZl8wBjYGMFtkBWFUcwRxUnUBKwJrBGNWNlc7V2NVPwQxXzJXZQQzVmdWLFUhVTxVcls7AmcFYgNnBH4AMwFoU2RfLgY1BjVbawV3VGIEPA== + + +### +# @no-redirect +GET http://127.0.0.1:6400/parser?url=https://www.feijix.com/s/tIfhRqH + +### +GET http://127.0.0.1:6400/json/fj/tIfhRqH + +### +# @no-redirect +GET http://127.0.0.1:6400/fj/tIfhRqH diff --git a/web-service/src/test/java/cn/qaiu/web/test/TestAESUtil.java b/web-service/src/test/java/cn/qaiu/web/test/TestAESUtil.java new file mode 100644 index 0000000..60cdcff --- /dev/null +++ b/web-service/src/test/java/cn/qaiu/web/test/TestAESUtil.java @@ -0,0 +1,57 @@ +package cn.qaiu.web.test; + +import cn.qaiu.lz.common.util.AESUtils; +import org.junit.Assert; +import org.junit.Test; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.HexFormat; + +public class TestAESUtil { + + // 1686215935703 + // B4C5B9833113ACA41F16AABADE17349C + @Test + public void decode() throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, + BadPaddingException, InvalidKeyException { + String hex = AESUtils.encryptHexByAES("1686215935703", AESUtils.CIPHER_AES2); + Assert.assertEquals("B4C5B9833113ACA41F16AABADE17349C", hex.toUpperCase()); + } + + @Test + public void encode() throws IllegalBlockSizeException, NoSuchPaddingException, BadPaddingException, + NoSuchAlgorithmException, InvalidKeyException { + String source = AESUtils.decryptByHexAES("B4C5B9833113ACA41F16AABADE17349C", AESUtils.CIPHER_AES2); + Assert.assertEquals("1686215935703", source); + } + + @Test + public void toHex() { + byte[] d234EF67A1s = HexFormat.of().parseHex("D234EF67A1"); + Assert.assertArrayEquals(new byte[]{(byte) 0xd2, (byte) 0x34, (byte) 0xef, (byte) 0x67, (byte) 0xa1}, + d234EF67A1s); + } + + @Test + public void base64AES() throws NoSuchAlgorithmException { + System.out.println(HexFormat.of().formatHex(AESUtils.createKeyString(AESUtils.KEY_SIZE_128_LENGTH).getEncoded())); + System.out.println(HexFormat.of().formatHex(AESUtils.createKeyString(AESUtils.KEY_SIZE_192_LENGTH).getEncoded())); + System.out.println(HexFormat.of().formatHex(AESUtils.createKeyString(AESUtils.KEY_SIZE_256_LENGTH).getEncoded())); + + // TODO Base64-AES + } + + @Test + public void testIdDecode() { + Assert.assertEquals(146731, AESUtils.idEncrypt("7jy0zlv")); + } + + @Test + public void testTs() { + System.out.println(System.currentTimeMillis()); + } +}