根据机器的CPU、主板、MAC地址生成唯一的激活码,授权认证

根据机器的CPU、主板、MAC地址生成唯一的激活码,授权认证

  • Dagon_Code
    • 判断是否为虚拟机或者容器
    • Windows下
      • 获取CPU序列号
      • 获取主板序列号
      • 获取本机所有MAC地址信息
    • Linux下
      • 执行命令
      • 执行命令后获取信息
    • 根据获取的机器信息,生成唯一的激活码。
      • 激活码生成策略
        • 加密算法介绍
        • 加密方案设计
    • 具体代码实现

参考了网上许多博客,文章,最后总结出来。

https://github.com/Dagon0577/Dagon_Code

Dagon_Code

从Windows,Linux获取CPU,主板,MAC地址,虚拟ID(docker,machine-rkt),并生成Dagon_Code。

判断是否为虚拟机或者容器

首先判断是否为虚拟机或者是容器,若不是,再去物理机下获取。(相关方法在下文)

/**
     * 判断是否为容器、虚拟机,返回虚拟ID
     *
     * @return
     */
    public static String getVirtualID() {
        String execResult = executeLinuxCmd("systemd-detect-virt");
        if (!execResult.contains("none")) {
            //docker容器
            String VirtualID = getSerialNumber("cat /proc/1/cgroup", "docker", "docker/");
            if (VirtualID != null) {
                return VirtualID;
            }
            //machine-rkt
            VirtualID = getSerialNumber("cat /proc/1/cgroup", "machine-rkt", "machine-rkt\\");
            if (VirtualID != null) {
                VirtualID.replaceAll("\\x2d", "-");
                return VirtualID;
            }
            //vmware
            VirtualID = getSerialNumber("dmidecode -t system", "UUID", ":");
            if (VirtualID != null) {
                return VirtualID;
            }
            return "UNKNOWN";
        }
        return null;
    }

Windows下

通过创建vbs脚本,然后使用Runtime.getRuntime().exec()执行脚本,获取序列号等信息。

获取CPU序列号

 /**
     * 获取CPU序列号
     *
     * @return
     */
    public static String getCPUSerial() {
        String result = "";
        try {
            File file = File.createTempFile("tmp", ".vbs");
            file.deleteOnExit();
            FileWriter fw = new java.io.FileWriter(file);
            String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
                    + "Set colItems = objWMIService.ExecQuery _ \n"
                    + "   (\"Select * from Win32_Processor\") \n"
                    + "For Each objItem in colItems \n" + "    Wscript.Echo objItem.ProcessorId \n"
                    + "    exit for  ' do the first cpu only! \n" + "Next \n";

            // + "    exit for  \r\n" + "Next";
            fw.write(vbs);
            fw.close();
            String path = file.getPath().replace("%20", " ");
            Process p = Runtime.getRuntime().exec("cscript //NoLogo " + path);
            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line;
            while ((line = input.readLine()) != null) {
                result += line;
            }
            input.close();
            file.delete();
        } catch (Exception e) {
            e.fillInStackTrace();
        }
        if (result.trim().length() < 1 || result == null) {
            result = "无CPU_ID被读取";
        }
        return result.trim();
    }

获取主板序列号

 /**
     * 获取主板序列号
     *
     * @return
     */
    public static String getMotherboardSN() {
        String result = "";
        try {
            File file = File.createTempFile("realhowto", ".vbs");
            file.deleteOnExit();
            FileWriter fw = new java.io.FileWriter(file);

            String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
                    + "Set colItems = objWMIService.ExecQuery _ \n"
                    + "   (\"Select * from Win32_BaseBoard\") \n"
                    + "For Each objItem in colItems \n" + "    Wscript.Echo objItem.SerialNumber \n"
                    + "    exit for  ' do the first cpu only! \n" + "Next \n";

            fw.write(vbs);
            fw.close();
            String path = file.getPath().replace("%20", " ");
            Process p = Runtime.getRuntime().exec("cscript //NoLogo " + path);
            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line;
            while ((line = input.readLine()) != null) {
                result += line;
            }
            input.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result.trim();
    }

获取本机所有MAC地址信息

/**
     * MAC
     * 通过jdk自带的方法,先获取本机所有的ip,然后通过NetworkInterface获取mac地址
     *
     * @return
     */
    public static String getMac() {
        try {
            String resultStr = "";
            List<String> ls = getLocalHostLANAddress();
            int num = 0;
            for (String str : ls) {
                InetAddress ia = InetAddress.getByName(str);// 获取本地IP对象
                // 获得网络接口对象(即网卡),并得到mac地址,mac地址存在于一个byte数组中。
                byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
                // 下面代码是把mac地址拼装成String
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < mac.length; i++) {
                    if (i != 0) {
                        sb.append("-");
                    }
                    // mac[i] & 0xFF 是为了把byte转化为正整数
                    String s = Integer.toHexString(mac[i] & 0xFF);
                    sb.append(s.length() == 1 ? 0 + s : s);
                }
                if (num == ls.size() - 1) {
                    resultStr += sb.toString().toUpperCase();
                } else {
                    // 把字符串所有小写字母改为大写成为正规的mac地址并返回
                    resultStr += sb.toString().toUpperCase() + ",";
                }
                num++;
            }
            return resultStr;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

Linux下

Linux同样使用Runtime.getRuntime().exec()执行Linux命令,获取相关信息。

执行命令

 public static String executeLinuxCmd(String cmd) {
        try {
            System.out.println("got cmd job : " + cmd);
            Runtime run = Runtime.getRuntime();
            Process process;
            process = run.exec(cmd);
            InputStream in = process.getInputStream();
            BufferedReader bs = new BufferedReader(new InputStreamReader(in));
            StringBuffer out = new StringBuffer();
            byte[] b = new byte[8192];
            for (int n; (n = in.read(b)) != -1; ) {
                out.append(new String(b, 0, n));
            }
            in.close();
            process.destroy();
            return out.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

执行命令后获取信息

 /**
     * @param cmd    命令语句
     * @param record 要查看的字段
     * @param symbol 分隔符
     * @return
     */
    public static String getSerialNumber(String cmd, String record, String symbol) {
        String execResult = executeLinuxCmd(cmd);
        String[] infos = execResult.split("\n");

        for (String info : infos) {
            info = info.trim();
            if (info.indexOf(record) != -1) {
                info.replace(" ", "");
                String[] sn = info.split(symbol);
                return sn[1];
            }
        }

        return null;
    }

    /**
     * @param cmd    命令语句
     * @param record 要查看的字段
     * @param symbol 分隔符
     * @return
     */
    public static String getAllSerialNumber(String cmd, String record, String symbol) {
        String execResult = executeLinuxCmd(cmd);
        String[] infos = execResult.split("\n");
        StringBuilder result = new StringBuilder();
        int k = 0;
        for (int i = 0; i < infos.length - 1; i++) {
            String info = infos[i];
            info = info.trim();
            if (info.indexOf(record) != -1) {
                info.replace(" ", "");
                String[] sn = info.split(symbol);
                if (k != 0) {
                    result.append(',');
                }
                result.append(sn[1]);
                k++;
            }
        }
        if (k != 0) {
            return result.toString();
        } else {
            return null;
        }
    }

根据获取的机器信息,生成唯一的激活码。

激活码生成策略

加密算法介绍

  • SHA1是一种流行的消息摘要算法,跟MD5相比,SHA1MD5的 安全性更强。对于长度小于 2 ^ 64 位的消息,SHA1会产生一个160位的消息摘要。基于MD5SHA1的信息摘要特性以及不可逆 (一般而言),可以被应用在检查文件完整性以及数字签名等场景。
  • Blowfish算法是著名的对称加密算法,是一种将64位数据分组及使用可变长度密钥的对称密钥分组加密算法,可用来加密64位长度的字符串。32位处理器诞生后,Blowfish算法因其在加密速度上的优越性而引起人们的广泛关注。Blowfish算法具有加密速度快、紧凑、密钥长度可变、免费使用等特点,已被广泛使用于软件保护、软件认证激活。算法核心在于子密钥的生成,它将变长密钥扩展成总长4168 比特位的子密钥数组。算法中使用了大量的子密钥,而子密钥又依赖于用户密钥,实际加密解密过程中使用的是更新后的子密钥数组,子密钥即P数组和S盒。算法输人64位明文信息,经过加密运算,输出64位密文信息。

加密方案设计

Dagon_Code将混合使用上述两种加密算法,设计设计一种新型的、高效的、破解难度高的混合加密方案,以增强安全性。加密方案核心步骤如下:

  • 1.对原始信息资源使用SHA1算法进行加密,产生128位散列值;

  • 2.将步骤1产生的固定长度散列值作为Blowfish算法的用户密钥,初始化Blowfish加密算法;

  • 3.使用初始化完成后的Blowfish算法对原始信息资源的进行加密,加密后即会产生高安全性的密文数据。

具体代码实现

https://github.com/Dagon0577/Dagon_Code

快速通道

你可能感兴趣的:(算法,加密,激活码)