commit 1d903f15a7110b0538ece6d35f7362f56d1ebdbe Author: niushuai233 Date: Tue Aug 30 12:12:53 2022 +0800 feat: 完成steam令牌本地获取 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..f9dfe23 --- /dev/null +++ b/pom.xml @@ -0,0 +1,100 @@ + + + 4.0.0 + + cc.niushuai.project + steam-token + 0.0.1 + steam令牌计算 + + + 1.8 + UTF-8 + UTF-8 + 8 + 8 + + 5.7.22 + 1.3 + 1.18.22 + + + + + + cn.hutool + hutool-all + ${hutool.version} + + + + commons-cli + commons-cli + ${commons.cli.version} + + + + org.projectlombok + lombok + ${lombok.version} + + + + + + aliyun + https://maven.aliyun.com/repository/public + + true + + + false + + + + + + aliyun-plugin + https://maven.aliyun.com/repository/public + + true + + + false + + + + + + steam-token-generator + + + maven-assembly-plugin + + false + + jar-with-dependencies + + + + + cc.niushuai.project.steam.token.SteamTokenApplication + + + + + + make-assembly + package + + assembly + + + + + + + + \ No newline at end of file diff --git a/src/main/java/cc/niushuai/project/steam/token/SteamTokenApplication.java b/src/main/java/cc/niushuai/project/steam/token/SteamTokenApplication.java new file mode 100644 index 0000000..c99131c --- /dev/null +++ b/src/main/java/cc/niushuai/project/steam/token/SteamTokenApplication.java @@ -0,0 +1,24 @@ +package cc.niushuai.project.steam.token; + +import cc.niushuai.project.steam.token.ins.SteamTwoFactorToken; +import cc.niushuai.project.steam.token.util.GlobalUtil; +import cn.hutool.core.date.DateUtil; + +/** + * Steam 令牌计算 + * + * @author niushuai + * @date 2022/8/29 17:53 + */ +public class SteamTokenApplication { + + public static void main(String[] args) { + + GlobalUtil.init(args); + System.out.println("初始化命令行参数成功" + args); + + String steamGuardCode = SteamTwoFactorToken.generateSteamGuardCode(GlobalUtil.getShared_secret()); + System.out.println("当前时间: " + DateUtil.now()); + System.out.println("Steam令牌: " + steamGuardCode); + } +} diff --git a/src/main/java/cc/niushuai/project/steam/token/entity/SteamCommand.java b/src/main/java/cc/niushuai/project/steam/token/entity/SteamCommand.java new file mode 100644 index 0000000..a06936b --- /dev/null +++ b/src/main/java/cc/niushuai/project/steam/token/entity/SteamCommand.java @@ -0,0 +1,49 @@ +package cc.niushuai.project.steam.token.entity; + +import cc.niushuai.project.steam.token.enums.GuardCalcTypeEnum; +import cc.niushuai.project.steam.token.util.GlobalUtil; +import cn.hutool.core.util.StrUtil; +import lombok.Data; + +/** + * steam文件令牌信息 + * + * @author niushuai + * @date 2022/8/30 10:47 + */ +@Data +public class SteamCommand { + + private GuardCalcTypeEnum type; + + /** + * 直接指定秘钥 + */ + private String sharedSecret; + + /** + * 指定steam令牌文件 从文件中读取秘钥 + */ + private String path; + + public SteamCommand verify() { + if (StrUtil.isEmpty(sharedSecret) && StrUtil.isEmpty(path)) { + System.err.println("参数缺失!"); + printUsage(); + GlobalUtil.exit(); + } + if (StrUtil.isNotEmpty(sharedSecret)) { + this.setType(GuardCalcTypeEnum.COMMAND); + } else { + this.setType(GuardCalcTypeEnum.STEAM_FILE); + } + return this; + } + + public void printUsage() { + System.out.println("usage: \n\tjava -jar steam-token-generator.jar [-sharedSecret xxx] [-path xxx]"); + System.out.println("eg: \n\tjava -jar steam-token-generator.jar -sharedSecret sJH7ffdwqgluzJK0tB6L7LklYSg="); + System.out.println("\tjava -jar steam-token-generator.jar -path Steamguard-16561111382543543"); + System.out.println("tips: \n\t两个参数任选其一, 若都传递则直接使用sharedSecret"); + } +} diff --git a/src/main/java/cc/niushuai/project/steam/token/entity/SteamInfo.java b/src/main/java/cc/niushuai/project/steam/token/entity/SteamInfo.java new file mode 100644 index 0000000..b5bd165 --- /dev/null +++ b/src/main/java/cc/niushuai/project/steam/token/entity/SteamInfo.java @@ -0,0 +1,29 @@ +package cc.niushuai.project.steam.token.entity; + +import cc.niushuai.project.steam.token.enums.GuardCalcTypeEnum; +import lombok.Data; + +/** + * steam文件令牌信息 + * + * @author niushuai + * @date 2022/8/30 10:47 + */ +@Data +public class SteamInfo { + + private GuardCalcTypeEnum type; + + private String shared_secret; + private String serial_number; + private String revocation_code; + private String uri; + private String server_time; + private String account_name; + private String token_gid; + private String identity_secret; + private String secret_1; + private String status; + private Integer steamguard_scheme; + private String steamid; +} diff --git a/src/main/java/cc/niushuai/project/steam/token/enums/GuardCalcTypeEnum.java b/src/main/java/cc/niushuai/project/steam/token/enums/GuardCalcTypeEnum.java new file mode 100644 index 0000000..6b05130 --- /dev/null +++ b/src/main/java/cc/niushuai/project/steam/token/enums/GuardCalcTypeEnum.java @@ -0,0 +1,20 @@ +package cc.niushuai.project.steam.token.enums; + +/** + * 令牌计算类型 + * + * @author niushuai + * @date 2022/8/30 11:05 + */ +public enum GuardCalcTypeEnum { + + /** + * 命令行参数 + */ + COMMAND, + + /** + * 读取文件 + */ + STEAM_FILE; +} diff --git a/src/main/java/cc/niushuai/project/steam/token/ins/SteamTwoFactorToken.java b/src/main/java/cc/niushuai/project/steam/token/ins/SteamTwoFactorToken.java new file mode 100644 index 0000000..9c976cd --- /dev/null +++ b/src/main/java/cc/niushuai/project/steam/token/ins/SteamTwoFactorToken.java @@ -0,0 +1,82 @@ +package cc.niushuai.project.steam.token.ins; + +import cn.hutool.core.codec.Base64; +import cn.hutool.core.util.StrUtil; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +/** + * SteamToken计算 + * + * @author niushuai + * @date 2022/8/29 17:55 + */ +public class SteamTwoFactorToken { + + private static final byte[] s_rgchSteamguardCodeChars = {50, 51, 52, 53, 54, 55, 56, 57, 66, 67, 68, 70, 71, 72, 74, 75, 77, 78, 80, 81, 82, 84, 86, 87, 88, 89}; + private byte[] mSecret; + + public SteamTwoFactorToken(String sharedSecret) { + if (StrUtil.isNotEmpty(sharedSecret)) { + this.mSecret = Base64.decode(sharedSecret.getBytes()); + } else { + throw new RuntimeException("未知参数 shared_secret"); + } + } + + public static String generateSteamGuardCode(String sharedSecret) { + return new SteamTwoFactorToken(sharedSecret).generateSteamGuardCode(); + } + + public final String generateSteamGuardCode() { + return generateSteamGuardCodeForTime(currentTime()); + } + + private final String generateSteamGuardCodeForTime(long calcTime) { + if (this.mSecret == null) { + return ""; + } + byte[] bArr = new byte[8]; + long j2 = calcTime / 30; + int i = 8; + while (true) { + int i2 = i - 1; + if (i <= 0) { + break; + } + bArr[i2] = (byte) ((int) j2); + j2 >>>= 8; + i = i2; + } + SecretKeySpec secretKeySpec = new SecretKeySpec(this.mSecret, "HmacSHA1"); + try { + Mac instance = Mac.getInstance("HmacSHA1"); + instance.init(secretKeySpec); + byte[] doFinal = instance.doFinal(bArr); + int i3 = doFinal[19] & 15; + int i4 = (doFinal[i3 + 3] & 255) | ((doFinal[i3 + 2] & 255) << 8) | ((doFinal[i3] & Byte.MAX_VALUE) << 24) | ((doFinal[i3 + 1] & 255) << 16); + byte[] bArr2 = new byte[5]; + for (int i5 = 0; i5 < 5; i5++) { + byte[] bArr3 = s_rgchSteamguardCodeChars; + bArr2[i5] = bArr3[i4 % bArr3.length]; + i4 /= bArr3.length; + } + return new String(bArr2); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 系统时间 不带毫秒 + * + * @author niushuai + * @date: 2022/8/30 10:28 + * @return: {@link long} 秒级时间戳 + */ + public final long currentTime() { + return System.currentTimeMillis() / 1000; + } +} diff --git a/src/main/java/cc/niushuai/project/steam/token/util/CommandParseUtil.java b/src/main/java/cc/niushuai/project/steam/token/util/CommandParseUtil.java new file mode 100644 index 0000000..931d2bd --- /dev/null +++ b/src/main/java/cc/niushuai/project/steam/token/util/CommandParseUtil.java @@ -0,0 +1,48 @@ +package cc.niushuai.project.steam.token.util; + +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.json.JSONUtil; +import org.apache.commons.cli.*; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * 处理命令行参数 + * + * @author niushuai + * @date: 2022/8/30 10:42 + */ +public class CommandParseUtil { + + public static T parse(String[] args, Class clazz) { + CommandLineParser parser = new DefaultParser(); + //获取字段 + Field[] fields = ReflectUtil.getFields(clazz); + //使用字段创建options,options是parse需要的参数 + Options options = new Options(); + for (Field field : fields) { + String name = field.getName(); + Option option = Option.builder(name).argName(name) + .desc(name) + .hasArg(true) + .type(field.getType()) + .build(); + options.addOption(option); + } + try { + CommandLine cl = parser.parse(options, args); + Map map = new HashMap<>(); + for (Field argsField : fields) { + String name = argsField.getName(); + map.put(name, cl.getOptionValue(name)); + } + + return (T) JSONUtil.toBean(JSONUtil.toJsonStr(map), clazz); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} \ No newline at end of file diff --git a/src/main/java/cc/niushuai/project/steam/token/util/GlobalUtil.java b/src/main/java/cc/niushuai/project/steam/token/util/GlobalUtil.java new file mode 100644 index 0000000..f9e6db1 --- /dev/null +++ b/src/main/java/cc/niushuai/project/steam/token/util/GlobalUtil.java @@ -0,0 +1,69 @@ +package cc.niushuai.project.steam.token.util; + +import cc.niushuai.project.steam.token.entity.SteamCommand; +import cc.niushuai.project.steam.token.entity.SteamInfo; +import cc.niushuai.project.steam.token.enums.GuardCalcTypeEnum; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; + +import java.util.stream.Collectors; + +/** + * 初始化工具类 + * + * @author niushuai + * @date 2022/8/30 10:33 + */ +public class GlobalUtil { + + private static String shared_secret = ""; + + /** + * 处理命令行参数 + * + * @param args 命令行参数 + * @author niushuai + * @date: 2022/8/30 10:52 + */ + public static void init(String[] args) { + + SteamCommand command = CommandParseUtil.parse(args, SteamCommand.class).verify(); + System.out.println("秘钥解析类型: " + command.getType()); + + if (GuardCalcTypeEnum.COMMAND.equals(command.getType())) { + shared_secret = command.getSharedSecret(); + } else { + // 需要先读文件 再取值 + + try { + String steamGuardInfoJson = FileUtil.readLines(command.getPath(), "UTF-8").stream().collect(Collectors.joining()); + + // 文件内容转bean + SteamInfo steamInfo = JSONUtil.toBean(steamGuardInfoJson, SteamInfo.class); + System.out.println("Steam ID: " + steamInfo.getSteamid()); + System.out.println("Steam 账户: " + steamInfo.getAccount_name()); + shared_secret = steamInfo.getShared_secret(); + } catch (IORuntimeException e) { + System.err.println("Steam令牌文件未找到: " + command.getPath() + ", 请确认路径是否正确!"); + } + } + + if (StrUtil.isEmpty(shared_secret)) { + String msg = GuardCalcTypeEnum.COMMAND.equals(command.getType()) ? "命令行shared_secret参数" : "Steam令牌文件路径"; + System.err.println("未找到相关秘钥[shared_secret], 请确认" + msg + "是否正确"); + exit(); + } + + System.out.println("shared_secret init success: " + shared_secret); + } + + public static String getShared_secret() { + return shared_secret; + } + + public static void exit() { + System.exit(0); + } +}