对程序进行加密处理

星期六一 2024-6-30 96 6/30

​ 在小程序开发的过程中,需要用到用户电脑的机器码,我这里采用的方法是获取用户电脑的CPU序列以及BIOS序列结合,然后使用MD5对数据进行加密。在用户验证成功后我会将用户的校验码存储到用户的C盘的AppData中,以txt的格式进行存储,用户在启动后程序会根据存储路径区查找此txt文档并进行校验码比对,不需要再重复输入。

获取用户CPU序列以及BIOS序列

​ 不多赘述,获取CPU序列代码如下:

    /**
     * 获取当前系统CPU序列,可区分linux系统和windows系统
     */
    public static String getCpuId() throws IOException {
        String cpuId;
        // 获取当前操作系统名称
        String os = System.getProperty(SYSTEM_PROPERTY_OS_NAME);
        os = os.toUpperCase();

        if (LINUX_OS_NAME.equals(os)) {
            cpuId = getLinuxDmidecodeInfo("dmidecode -t processor | grep 'ID'", "ID", ":");
        } else {
            cpuId = getWindowsCpuId();
        }
        return cpuId.toUpperCase().replace(" ", "");
    }
    /**
     * 获取linux系统
     * dmidecode
     * 命令的信息
     */
    public static String getLinuxDmidecodeInfo(String cmd, String record, String symbol) throws IOException {
        String execResult = executeLinuxCmd(cmd);
        String[] infos = execResult.split("\n");
        for (String info : infos) {
            info = info.trim();
            if (info.contains(record)) {
                info.replace(" ", "");
                String[] sn = info.split(symbol);
                return sn[1];
            }
        }
        return null;
    }
 /**
     * 执行Linux 命令
     *
     * @param cmd Linux 命令
     * @return 命令结果信息
     * @throws IOException 执行命令期间发生的IO异常
     */
    public static String executeLinuxCmd(String cmd) throws IOException {
        Runtime run = Runtime.getRuntime();
        Process process;
        process = run.exec(cmd);
        InputStream processInputStream = process.getInputStream();
        StringBuilder stringBuilder = new StringBuilder();
        byte[] b = new byte[8192];
        for (int n; (n = processInputStream.read(b)) != -1; ) {
            stringBuilder.append(new String(b, 0, n));
        }
        processInputStream.close();
        process.destroy();
        return stringBuilder.toString();
    }
    /**
     * 获取windows系统CPU序列
     */
    public static String getWindowsCpuId() throws IOException {
        Process process = Runtime.getRuntime().exec(
                new String[]{"wmic", "cpu", "get", "ProcessorId"});
        process.getOutputStream().close();
        Scanner sc = new Scanner(process.getInputStream());
        sc.next();
        String serial = sc.next();
        return serial;
    }

​ 获取BIOS的UUID:

/**
     * 获取 BIOS UUID
     *
     * @return BIOS UUID
     * @throws IOException 获取BIOS UUID期间的IO异常
     */
    public static String getBiosUuid() throws IOException {
        String cpuId;
        // 获取当前操作系统名称
        String os = System.getProperty("os.name");
        os = os.toUpperCase();

        if ("LINUX".equals(os)) {
            cpuId = getLinuxDmidecodeInfo("dmidecode -t system | grep 'UUID'", "UUID", ":");
        } else {
            cpuId = getWindowsBiosUUID();
        }
        return cpuId.toUpperCase().replace(" ", "");
    }

    /**
     * 获取windows系统 bios uuid
     *
     * @return
     * @throws IOException
     */
    public static String getWindowsBiosUUID() throws IOException {
        Process process = Runtime.getRuntime().exec(
                new String[]{"wmic", "path", "win32_computersystemproduct", "get", "uuid"});
        process.getOutputStream().close();
        Scanner sc = new Scanner(process.getInputStream());
        sc.next();
        String serial = sc.next();
        return serial;
    }

​ 获取唯一的机器码只需要将CPU序列和BIOS的UUID拼接起来即可。

​ 对用户电脑的机器码进行MD5加密或者使用之前发布的Hutool工具进行sha256字符串加密都可以,加密后即可生成唯一密钥。我这里对加密字符串做了更多的处理,例如多拼接一些特殊字符...都可以实现更安全的加密方式,代码如下:

    public static String encode(String data) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.update(data.getBytes(StandardCharsets.UTF_8));
            byte[] bytes = messageDigest.digest();
            return new BigInteger(1, bytes).toString(16);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }

下面是复习一下Java的IO

​ 我主要使用一个新建文件以及读取文件,代码如下:

    // 获取当前用户的用户名
    public static final String username = System.getProperty("user.name");

    // 构建文件的完整路径
    public static final String filePath = "C:\\Users\\" + username + "\\AppData\\Local\\checkANS\\pass.txt";

    public static Boolean write(String content) {
        // 创建File对象,代表目标文件
        File file = new File(filePath);

        // 获取上级目录文件对象
        File parentDir = file.getParentFile();

        // 如果上级目录不存在,则创建目录
        if (!parentDir.exists()) {
            // mkdirs() 创建包括父目录在内的所有不存在的目录
            boolean isDirCreated = parentDir.mkdirs();
            if (isDirCreated) {
                System.out.println("目录创建成功:" + parentDir.getAbsolutePath());
            } else {
                System.err.println("创建目录时发生错误:" + parentDir.getAbsolutePath());
                return false;
            }
        }

        try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
            // 写入数据
            writer.write(content);
            System.out.println("文件创建成功并在其中写入了数据:" + filePath);
            return true;
        } catch (IOException e) {
            System.err.println("创建文件或写入数据时发生错误:" + e.getMessage());
            return false;
        }
    }

    public static String getPass(){
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = reader.readLine()) != null) {
                return line;
            }
        } catch (IOException e) {
            System.err.println("读取文件时发生错误:" + e.getMessage());
            return "";
        }
        return "";
    }
- THE END -

星期六一

6月30日17:39

最后修改:2024年6月30日
0

非特殊说明,本博所有文章均为博主原创。

共有 0 条评论