`

APDPlat中的机器码生成机制

阅读更多

APDPlat提供了机器绑定的功能,对于不同的机器会生成不同的机器码,必须要对生成的机器码进行计算获得注册码,注册码验证成功之后系统才能正常运行。

 

本文主要介绍APDPlat如何生成机器码。

 

首先,定义了一个统一的接口,以支持不同操作系统不同实现的透明切换:

 

/**
 *生成机器码的接口,不同平台有不同实现
 * @author 杨尚川
 */
public interface SequenceService {
    /**
     * 获取机器码
     * @return  机器码
     */
    public String getSequence();    
}

 

 

其次,定义了一个抽象类,实现了一些通用的功能,如生成MD5摘要将很长的字符串以固定的位数分割开,以便于人类阅读(如将机器码 71F5DA7F495E7F706D47F3E63DC6349A 每4个一组,以-分割为71F5-DA7F-495E-7F70-6D47-F3E6-3DC6-349A)、利用sigar来生成机器码。这里需要在pom.xml中加入sigar依赖。

 

<dependency>
	<groupId>org.fusesource</groupId>
	<artifactId>sigar</artifactId>
	<version>1.6.4</version>
	<exclusions>
		<exclusion>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
		</exclusion>
	</exclusions>
</dependency>

 

 

import org.apdplat.module.system.service.PropertyHolder;
import org.apdplat.platform.log.APDPlatLogger;
import org.apdplat.platform.util.ConvertUtils;
import org.apdplat.platform.util.FileUtils;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import org.apdplat.platform.log.APDPlatLoggerFactory;
import org.hyperic.sigar.Mem;
import org.hyperic.sigar.NetFlags;
import org.hyperic.sigar.NetInterfaceConfig;
import org.hyperic.sigar.Sigar;

/**
 *机器码生成的通用服务
 * @author 杨尚川
 */
public abstract class AbstractSequenceService   implements SequenceService{
    protected final APDPlatLogger LOG = APDPlatLoggerFactory.getAPDPlatLogger(getClass());
    /**
     * 对一段String生成MD5摘要信息
     * @param message 要摘要的String
     * @return 生成的MD5摘要信息
     */
    protected String getMD5(String message) {
        message += "{apdplat}";
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            LOG.debug("MD5摘要长度:" + md.getDigestLength());
            byte[] b = md.digest(message.getBytes("utf-8"));
            String md5 = ConvertUtils.byte2HexString(b)+message.length();
            return getSplitString(md5);
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            LOG.error("MD5摘要失败",e);
        }
        return null;
    }
    /**
     * 将很长的字符串以固定的位数分割开,以便于人类阅读
     * @param str
     * @return 
     */
    protected String getSplitString(String str){ 
        return getSplitString(str, "-", 4);
    }
    /**
     * 将很长的字符串以固定的位数分割开,以便于人类阅读
     * 如将
     * 71F5DA7F495E7F706D47F3E63DC6349A
     * 以-,每4个一组,则分割为
     * 71F5-DA7F-495E-7F70-6D47-F3E6-3DC6-349A
     * @param str 字符串
     * @param split 分隔符
     * @param length 长度
     * @return 
     */
    protected String getSplitString(String str, String split, int length){        
        int len=str.length();
        StringBuilder temp=new StringBuilder();
        for(int i=0;i<len;i++){
            if(i%length==0 && i>0){
                temp.append(split);
            }
            temp.append(str.charAt(i));
        }
        String[] attrs=temp.toString().split(split);
        StringBuilder finalMachineCode=new StringBuilder();
        for(String attr : attrs){
            if(attr.length()==length){
                finalMachineCode.append(attr).append(split);
            }
        }
        String result=finalMachineCode.toString().substring(0, finalMachineCode.toString().length()-1);
        return result;
    }    
    /**
     * 利用sigar来生成机器码,当然这个实现不是很好,无法获得CPU ID,希望有兴趣的朋友来改进这个实现
     * @param osName 操作系统类型
     * @return 机器码
     */
    protected String getSigarSequence(String osName) {
        try {
            File libFile = new File(FileUtils.getAbsolutePath("/WEB-INF/lib/"+PropertyHolder.getProperty("libsigar."+osName)));
            LOG.debug("libsigar."+osName+" : "+libFile.getAbsolutePath());
            
            System.load(libFile.getAbsolutePath());
            Set<String> result = new HashSet<>();
            Sigar sigar = new Sigar();
            String[] ifaces = sigar.getNetInterfaceList();
            for (String iface : ifaces) {
                NetInterfaceConfig cfg = sigar.getNetInterfaceConfig(iface);                if (NetFlags.LOOPBACK_ADDRESS.equals(cfg.getAddress()) || (cfg.getFlags() & NetFlags.IFF_LOOPBACK) != 0
                        || NetFlags.NULL_HWADDR.equals(cfg.getHwaddr())) {
                    continue;
                }
                String mac = cfg.getHwaddr();
                result.add(mac);
                LOG.debug("mac: " + mac);
            }
            if(result.size()<1){
                return null;
            }
            Properties props = System.getProperties();
            String javaVersion = props.getProperty("java.version");
            result.add(javaVersion);
            LOG.debug("Java的运行环境版本:    " + javaVersion);
            String javaVMVersion = props.getProperty("java.vm.version");
            result.add(javaVMVersion);
            LOG.debug("Java的虚拟机实现版本:    " + props.getProperty("java.vm.version"));
            String osVersion = props.getProperty("os.version");
            result.add(osVersion);
            LOG.debug("操作系统的版本:    " + props.getProperty("os.version"));

            Mem mem = sigar.getMem();
            // 内存总量
            String totalMem = mem.getTotal() / 1024L + "K av";
            LOG.debug("内存总量:    " + totalMem);
            result.add(totalMem);

            LOG.debug("result:    " + result);
            String machineCode = getMD5(result.toString());

            return machineCode;
        } catch (Throwable ex) {
            LOG.error("生成 "+osName+" 平台下的机器码失败", ex);
        }
        return null;
    }
}

 

 

最后,我们分别看看不同平台的实现。

 

Windows:

 

/**
 *在Windows平台上生成机器码
 * @author 杨尚川
 */
public final class WindowsSequenceService extends AbstractSequenceService{    
    @Override
    public String getSequence() {        
        String cpuID=getCPUSerial();
        String hdID=getHDSerial("C");
        if(cpuID==null || hdID==null){
            return null;
        }
        String machineCode = getMD5(cpuID+hdID);
                
        return machineCode;
    }
    
    /**
     *
     * @param drive 硬盘驱动器分区 如C,D
     * @return 该分区的卷标
     */
    private String getHDSerial(String drive) {
        StringBuilder result = new StringBuilder();
        try {
            File file = File.createTempFile("tmp", ".vbs");
            file.deleteOnExit();
            try (FileWriter fw = new java.io.FileWriter(file)) {
                String vbs = "Set objFSO = CreateObject(\"Scripting.FileSystemObject\")\n"
                        + "Set colDrives = objFSO.Drives\n" + "Set objDrive = colDrives.item(\"" + drive + "\")\n"
                        + "Wscript.Echo objDrive.SerialNumber";
                fw.write(vbs);
            }
            Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
            try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
                String line;
                while ((line = input.readLine()) != null) {
                    result.append(line);
                }
            }
            file.delete();
        } catch (Throwable e) {
            LOG.error("生成HDSerial失败", e);
        }
        if (result.length() < 1) {
            LOG.info("无磁盘ID被读取");
        }

        return result.toString();
    }

    /**
     * 获取CPU号,多CPU时,只取第一个
     * @return
     */
    private String getCPUSerial() {
        StringBuilder result = new StringBuilder();
        try {
            File file = File.createTempFile("tmp", ".vbs");
            file.deleteOnExit();
            try (FileWriter fw = new FileWriter(file)) {
                String vbs = "On Error Resume Next \r\n\r\n" + "strComputer = \".\"  \r\n"
                        + "Set objWMIService = GetObject(\"winmgmts:\" _ \r\n"
                        + "    & \"{impersonationLevel=impersonate}!\\\\\" & strComputer & \"\\root\\cimv2\") \r\n"
                        + "Set colItems = objWMIService.ExecQuery(\"Select * from Win32_Processor\")  \r\n "
                        + "For Each objItem in colItems\r\n " + "    Wscript.Echo objItem.ProcessorId  \r\n "
                        + "    exit for  ' do the first cpu only! \r\n" + "Next                    ";

                fw.write(vbs);
            }
            Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
            try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
                String line;
                while ((line = input.readLine()) != null) {
                    result.append(line);
                }
            }
            file.delete();
        } catch (Throwable e) {
            LOG.error("生成CPUSerial失败", e);
        }
        if (result.length() < 1) {
            LOG.info("无CPU_ID被读取");
        }
        return result.toString();
    }
    
    public static void main(String[] args) {        
        SequenceService s = new WindowsSequenceService();
        String seq = s.getSequence();
        System.out.println(seq);
    }
}

 

 

Linux:

 

/**
 *在Linux平台上生成机器码
 * @author 杨尚川
 */
public class LinuxSequenceService  extends AbstractSequenceService{
    @Override
    public String getSequence() {
        return getSigarSequence("linux");
    }

    public static void main(String[] args) {
        SequenceService s = new LinuxSequenceService();
        String seq = s.getSequence();
        System.out.println(seq);
    }
}

 

 

Mac OS X:

 

/**
 *在Mac OS X平台上生成机器码
 * @author 杨尚川
 */
public class MacSequenceService    extends AbstractSequenceService{
    @Override
    public String getSequence() {
        return getSigarSequence("mac");
    }
   
    public static void main(String[] args) {
        SequenceService s = new MacSequenceService();
        String seq = s.getSequence();
        System.out.println(seq);
    }
}

 

 

Solaris:

 

/**
 *在Solaris平台上生成机器码
 * @author 杨尚川
 */
public class SolarisSequenceService    extends AbstractSequenceService{
    @Override
    public String getSequence() {
        return getSigarSequence("solaris");
    }

    public static void main(String[] args) {
        SequenceService s = new SolarisSequenceService();
        String seq = s.getSequence();
        System.out.println(seq);
    }    
}

 

 

 

 APDPlat托管在Github

2
1
分享到:
评论
6 楼 masuweng 2018-08-28  
你好, 根据机器码计算注册码的代码是在哪个包下的哪个类了.
5 楼 masuweng 2018-03-19  
我的那个项目跑起来为什么503了
4 楼 masuweng 2018-03-18  
        
3 楼 steed_ns 2016-05-19  
如果程序发布至云平台怎样与机器绑定?
2 楼 yangshangchuan 2014-04-11  
jackyrong 写道
想请教下,apdplat中,有无策略是应对在客户端部署war的时候,限制用户的使用时间的,比如给出试用的时限,超过后就启动应用失败,我的初步想法是使用私钥+机器码,然后用算法生成序列号的方法,不知道可行否?


当然有啦,呵呵,在部署的时候,可以对JAR进行混淆并指定过期时间(试用期限)
1 楼 jackyrong 2014-04-11  
想请教下,apdplat中,有无策略是应对在客户端部署war的时候,限制用户的使用时间的,比如给出试用的时限,超过后就启动应用失败,我的初步想法是使用私钥+机器码,然后用算法生成序列号的方法,不知道可行否?

相关推荐

    本机机器码生成器(C#编写.net 3.5)

    在给定的标题“本机机器码生成器(C#编写.net 3.5)”中,我们可以看到这是一个利用C#编程语言在.NET Framework 3.5环境下编写的程序,其主要功能是获取并生成基于本机特定硬件信息的机器码。这个程序可以帮助开发者...

    C# 机器码生成License

    1、获取本机的机器码 2、根据机器码生成授权码License

    C# 软件 机器码生成注册码

    机器码,也称硬件指纹,是通过识别计算机的特定硬件信息(如硬盘序列号、CPU序列号、主板ID等)生成的一串唯一标识符。它的目的是确保软件只能在特定的硬件配置上运行,从而防止软件盗版和非法分发。 在C#中,我们...

    机器码生成工具

    机器码 wechoid,一些软件注册时需要提供的参数,目前Actix Analyzer用的就是机器码0x14类型。

    C++动态生成机器码

    C++动态生成机器码是一种高级编程技术,它允许程序员在程序运行时创建并执行自定义的机器代码。这种技术在某些领域,如元编程、逆向工程和安全研究中非常有用,但同时也可能被用于不道德或非法的目的,如创建恶意...

    QT机器码生成程序

    Linux平台下使用QT编写的依据网卡ID等一系列硬件设备的ID识别号生成机器码的程序源码

    基于python 实现的机器码/用户码/注册码 生成器

    注册机 安装说明 执行脚本: ...管理员解密用户提供的【加密机器码】文件 同时为用户设置授权天数,生成【用户码】文件 结合两者生成【注册码】文件 把【用户码】文件和【注册码】文件提供给用户

    机器码生成器MachineCode

    根据CUPID,MAC地址,硬盘ID 计算出一个终端的机器码,并且可以复制

    易语言软件机器码与注册码生成

    根据cpu、硬盘、主板bios组合生成64位机器码,注册码为加密后的机器...校验时不要求机器码完全吻合,只要上述3个硬件中有两个不变即可通过。既防止了通过刷盘更改硬盘序列号,又避免了由于单个硬件损坏影响软件的使用。

    JAVA在Windows平台上生成机器码

    在这个场景中,"JAVA在Windows平台上生成机器码"指的是将Java源代码编译成针对Windows系统的本地代码,也称为本机代码或机器码。 首先,了解Java的编译过程是必要的。通常,Java源代码(`.java`文件)会被Java...

    VB PHP实现机器码注册码计算并生成.rar

    VB PHP实现机器码注册码计算并生成,使用:Key_API.dll,只做了一个PHP API接口,用法:把key_api.dll 复制到你的PHP目录下 ext 目录下 例:\php52\ext 用AIP_REG.bat 注册下控件,如果PHP不能正常调用请修改PHP.ini...

    ASP.NET+SQL2000简单三层获取机器码生成授权码

    【ASP.NET+SQL2000简单三层获取机器码生成授权码】 在IT行业中,软件授权是保护知识产权的重要手段,而生成和验证授权码则是这一过程的关键环节。本项目是基于ASP.NET(C#)和SQL Server 2000构建的简单三层架构,...

    C# 获取并生成机器码

    在给定的标题和描述中,我们关注的是如何在C#中获取这些硬件信息,并利用它们生成机器码。 首先,我们需要了解如何获取硬盘序列号。在Windows系统中,硬盘序列号是一个标识硬盘的唯一数字或字母组合。在C#中,可以...

    根据机器码生成注册码:VB注册机实例.rar

    根据机器码生成注册码,获得序列号并验证,VB注册机实例。我正使用的硬盘算法软件加密钥匙计算器,分享给出大家了,不过有些朋友说用此方法算注册号不好,建议用其他方法。

    机器码生成C#.zip

    VS2010环境,.NET4 获取电脑硬盘序列号和CPU序列号,用硬盘和CPU序列号混合生成机器码. 直接可用,比网上公布的那些获取CPU序列号要快,可以直接使用

    机器码生成

    机器码生成器,免费使用,很方便,欢迎下载

    VB利用网卡MAC制作机器码

    本文将深入探讨如何使用VB来利用计算机的网卡物理地址(MAC地址)生成唯一的“机器码”,这是一种常见的软件授权机制。 首先,让我们理解什么是MAC地址。MAC地址,全称Media Access Control Address,是网络设备...

    C# 读取机器码,CPU序列号,生成注册码类

    根据提供的文件信息,本文将详细解释如何在C#中实现机器码、CPU序列号的读取以及注册码的生成过程。 ### 一、引言 软件注册码是一种常见的软件授权方式,通过绑定特定硬件(如硬盘序列号或CPU序列号)来确保软件...

    iCAM机器码生成器

    iCAM机器码生成器,生成机器码,获得正版注册

Global site tag (gtag.js) - Google Analytics