技术背景
为便于描述和理解本发明,现给出现有技术中相关名词的解释如下:
OTA:Over The Air,即空中、无线方式
J2ME:Java 2 Micro Edition,即适合小型手持系统(包括移动终端)使用的Java
MIDP:Mobile Information Device Profile,移动信息设备描述,是J2ME的技术规范,目前有两个版本,即MIDP1.0和MIDP2.0。MIDP2.0是MIDP1.0的升级版本,向下兼容MIDP1.0规范
JAR:Java Archive,Java包文件
KVM:千字节级java虚拟机,手机等小型设备的Java虚拟机,针对这类设备内存较少的事实,它需要的内存以千字节(k)为单位
Java文件:java源代码文件,通常以java为扩展名
Class文件:编译后的java二进制可执行文件,运行在java虚拟机上,通常以.class为扩展名
字节码(bytecode):特指class文件中包含的二进制可执行代码,是java虚拟机指令的组合
类(class):是Java语言中功能模块的基本单位,包含若干个Java Method。在编译后的二进制发布包中,每一个class文件对应一个类
MIDlet:MIDlet类是所有J2ME软件的入口类的超类(父类)。有时候也使用MIDlet术语来指一个J2ME软件
Java Method:Java方法,是Java语言中逻辑组合的基本单位,在其它编程语言(如C和Pascal)中通常称为函数function或过程procedure,在编译后的class文件中,字节码也是以method为单位而组合存在的
编译:把源文件转换成可执行代码的过程,在下文中特指从java源代码到class文件的转换
反编译:把二进制可执行文件还原成源代码的转换过程,在下文中特指从class文件到java源文件的转换
预校验(preverify):使用Java编译器编译后的class文件要经过预校验处理,处理后的class文件才能正确地被KVM载入运行,J2ME用预校验机制一方面减轻了KVM的负担,一方面仍然确保了class文件的正确性。
混淆(obfuscate):一种对二进制可执行文件进行处理,在不改变程序运行逻辑的前提下,通过删除执行文件内的调试和辅助信息,修改变量、方法名称,改变包结构等手段,使得处理后的可执行文件反编译得到的源代码可读性大大下降,从而达到保护开发者知识产权的方法。
J2ME技术是由美国sun公司提出的,旨在为手机等小型手持无线设备提供可移植的java扩展机制。从此技术提出到现在已经过了好几年的时间,得到了手机厂商、运营商、软件开发商的广泛支持。目前,可以说支持J2ME的手机已经在全世界范围内普及。然而,有调查数据显示,在中国的Java手机用户中,仅有约30%为下载J2ME应用和游戏付费,大部分用户则使用盗版手机软件。这是因为,J2ME软件由于其先天性的安全性缺陷,使得应用很易于破解,且难以对非法传播进行有效控制。J2ME软件的非法传播现象并非仅在中国出现,国外也面临着类似的情况。
针对J2ME软件被大量非法复制和使用的情况,OMA国际组织(OpenMobileAlliance.org)提出了无线设备上的DRM(Digital RightsManagement,数字版权管理)方案,用来防止J2ME软件被非法传播。DRM把内容(图片,铃声,主题,游戏,应用……)和使用权限分开,人们对使用权付费而不是对内容本身付费。然而,OMA的方案需要硬件的特殊支持,也就是说无法适用于市场上保有的巨大基数的现有终端。
图1是现有技术的一种基于DRM方案的软件保护方法的示意图。这种软件保护方法是由国外一些公司(比如Wi-software)提出的。按照这种方法,通过一定的技术手段,向J2ME软件中自动加入一些权限验证代码。使用者在访问到真正的内容之前要先经过权限的检测,因此,只有通过了权限检测的用户才能访问到真正的内容。如图1所示,通过在入口类(MIDlet)嵌入合法性验证逻辑来进行权限检测,只有通过了权限检测,才可以访问到软件主逻辑。
然而,以Wi-software为代表的这种基于DRM方案的软件保护方法仍然存在着不足之处。对于普通用户来讲,它能够起到一些防止非法传播和使用的目的,但是,对于经验丰富的破解者来说,比如说掌握了一定破解技术的技术人员,有可能通过“反编译-删除权限检测代码-重新编译-重新打包”这样模式化的手段来进行破解。对于这样的技术人员,以Wi-software为代表的这种基于DRM方案的软件保护方法便起不到应有的防解密作用。
图2是现有技术的一种基于注册码的软件保护方法。这种方法是由一些软件开发者在开发过程中,为防止所开发的软件日后被非法使用,在程序中人为的加入了注册码验证机制,要求使用者必须购买一个合法的注册码或序列号才能访问软件的全部功能。如图2所示,在软件主逻辑中加入注册码验证逻辑。这样,在软件运行时,将执行注册码验证逻辑,用户必须使用另行购得的注册码或序列号,才能通过注册码验证逻辑,进而访问软件的全部功能。
然而,由于手机软件技术平台的限制,注册码无法与手机终端实现绑定。也就是说,一些恶意的用户完全可以取得一个合法注册码后将其与软件的拷贝一起传播。因此这种方案同样无法有效防止软件被非法传播和使用,因而不能对软件开发者的软件开发成果进行有效保护。而进一步说,有经验的破解者同样可以按照前面说过的方法,定位到注册验证代码,将此代码删除或篡改后重新打包发布。
由此,需要提供一种更好的软件保护方法,以防止J2ME软件被以网络下载等方式非法传播并使用。
具体实施方式
图3是本发明的软件加密和验证方法的方框图。本发明的软件加密和验证方法使用java类变形技术,直接对手机软件的二进制发布包(JAR包)中的多个类(Class)文件进行加密处理。如图3所示,功能模块A-D是JAR包中的类文件,对功能模块A-D中的全部或部分功能模块进行加密。在本发明中,这种加密可以通过加入激活码验证代码来实现。然而,本发明并不仅限于这种方式,也可以通过加入其它的密码,如随机产生的加密来实现。
处理后的被保护JAR包仍然是一个合法的J2ME程序,可以正常安装到手机终端上。但被保护JAR包依赖于由服务器提供的全部激活码才能正常运行,它会自动向服务器请求更新激活码。
按照本发明,加入的激活码验证逻辑并非简单的集中存在于一个固定的位置,而是可以存在于多个class文件的Java Method中,甚至遍布所有class文件的Java Method。由于本发明的激活码产生逻辑完全在服务器端,破解者无法根据加密内容推导出激活码产生算法。
按照本发明,所加入的激活码并不是永久有效的。本发明对于所加入的激活码分配日期和时间限制。例如,激活码在某个日期(如2006年12月31日)前有效。或者,激活码在几小时~几天的时间内有效。当然,对于日期和时间的限制并不是固定的,而是可以在实现本发明过程中根据实际情况选择。
根据本发明,使用权限以激活码的形式存在,并且激活码只在一定日期或时间限制范围内有效。例如,嵌入的激活码验证逻辑可以使用系统日期作为验证运算的一个输入,激活码必须与系统日期匹配才能通过验证。使用与日期不匹配的激活码将导致程序发生不可预知的错误。例如,每天第一次运行的时候,被保护J2ME程序将自动向服务器请求更新激活码。当然,向服务器请求更新激活码的间隔并不限于一天,而可以是几小时、几天或更长的日期。
根据本发明,使用权限还可以通过规定使用次数来限制。例如,可以对嵌入的激活码验证逻辑设定一个规定的使用次数,每过一定的时间(如一天或几小时),则次数减1。当次数减到0时,激活码变为无效,必须更新激活码才能继续使用软件。本发明对次数的限定并不限于以一定的时间间隔(如一天或几小时)来作为次数递减的时间单位,本发明也可以将次数设定为每次软件启动则减1。
本发明可以采用二进制数据作为激活码。由于二进制数据不具有可读性,因此难以被抄录并传播。另外,由于本发明对激活码设置日期和/或时间限制,因此,在日期或时间比较短的情况下,使得传播激活码的行为丧失了意义。本发明还可以采用文本数据作为激活码。
另外,本发明也并不限于仅在JAR包的类文件中加入密码(或激活码),而是,本发明可以将JAR包的入口类(MIDlet)、软件主逻辑、各个功能模块均作为加密的对象。如图3所示,本发明的激活码可以同时加在入口类(MIDlet)、软件主逻辑、和多个功能模块A-D中。
激活码的检验和更新流程
本发明向JAR包中嵌入的激活码检验和更新逻辑可用下面图4-图6的流程图来表示。
图4是本发明的激活码检验和更新的流程图。本发明使用类变形技术在客户端(也就是JAR包)中加入激活码检验和更新逻辑。而在服务器端,提供一个对应的服务器端程序,用以产生合法激活码并根据客户端的请求向其发放激活码。服务器端程序可对激活码的产生和发放进行完全的控制,进而实现各种资费模式。
如图4所示,在手机上的J2ME软件被启动后,在步骤S1,程序检验激活码的有效性。如果激活码有效,则直接进入软件主逻辑。如果在步骤S1中判断出激活码已变为无效,则在步骤S2获取用户唯一标识(ID)。在步骤S3,手机向服务器发送请求,以获取更新的激活码。响应于该请求,在步骤S4,服务器在判定用户唯一标识正确的情况下,返回更新的激活码和更新的使用权限。该更新的使用权项可以是更新的时间或日期限制,也可以是可用次数限制。在步骤S5,手机保存用户ID、更新的激活码和更新的使用权限。
图5是图4的激活码检验和更新过程中的检验激活码有效性的具体流程图。如图5所示,在步骤S11,首先判断是否存在激活码。如果判断结果为激活码不存在,则激活码无效(“否”),程序进入图4的步骤S2,以获取新的激活码。如果在步骤S11中判断出激活码存在,则在步骤S12,进一步判断当前激活码使用权限是否有效,即判断是否在规定的使用日期之前、或规定的时间长度之内、或规定的可用次数之内。如果判断结果为激活码已无效(“否”),则进入图4的步骤S2,以向服务器请求获取新的激活码。如果在步骤S12中判断出激活码的使用权限有效,即在规定的使用日期之前、或规定的时间长度之内、或规定的可用次数之内,则将可用次数减1,并进入软件主逻辑。
在图5的实施例中,如果所设置的使用权限为可用次数,则在判断为激活码的可用次数大于0的情况下,将可用次数减1,并进入软件主逻辑。
图6是图4的激活码检验和更新过程中的获取用户唯一标识(ID)的具体流程图。如图6所示,在步骤S21,手机从本地载入用户唯一标识。该用户唯一标识可以是手机号码或设定的密码,也可以是由本发明预先在JAR包中嵌入的唯一ID。如果成功获取用户唯一标识,则进入图4的步骤S3,以进一步获得更新的激活码。如果在图6的步骤S21没有获取用户唯一标识,则在步骤S22请求用户输入其唯一标识(如手机号或密码)。在步骤S23,手机检验用户所输入的标识是否有效。如果有效,则进入图4的步骤S3,以进一步获得更新的激活码。如果无效,则返回步骤S22。
在图6中,手机在步骤S23检验用户输入的标识是否有效。然而,本发明并不限于此,手机可以将用户输入的唯一标识不经过检验就发送到服务器侧,并由服务器侧判断是否为有效的用户唯一标识,并在判断为有效的用户唯一标识时向手机返回更新的激活码和新的使用权限。
上面的流程描述了一种通用的方案,而对于移动网络运营商,因为他们可以直接根据手机的网络请求获得用户的唯一标识(手机号码),所以获取用户唯一ID的过程可以省略,这样流程还能更加简化。在这种情况下,服务器识别手机用户的唯一标识,根据唯一标识判断是否为合法用户,并且在判断为合法用户的情况下,向手机返回更新的激活码和/或更新的使用权限。在这种情况下,除了一次网络请求之外(出于安全方面的考虑,手机上的Java运行环境通常需要用户确认后才允许Java软件访问网络,这点和PC上网不同),其它的过程完全不需要跟用户交互,对用户更加透明,用户的体验更好。
激活码验证逻辑的一个例子
本发明向JAR包中各个class的多个Java Method中嵌入了激活码验证逻辑,以提高破解难度。在本发明的一种实施方式中,激活码和当日日期匹配。在这种情况下,加入的代码是一个简单的表达式验证,其逻辑可用以下伪代码近似表示:
if(<当日时间码><运算><方法特征码>)!=<方法激活码>){
return;
}
其中:
a.<当日时间码>是经过运算的本日时间数字,要求在本日内任意两个时刻,运算获得的<当日时间码>相等,而在任意两不等日期内的两个时刻,运算获得的时间码则不等;
b.<运算>是加、减、异或等算术或逻辑运算;
c.<方法特征码>是由本发明加入的,只与特定方法相关的特征数字。服务器端记录所有特征数字,并产生和其匹配的激活码;
d.<方法激活码>是从服务器端获得的激活码中的一部分(数组的一个或多个元素)。
在实际应用中,本发明的软件加密和验证方法还采用以下手段减少插入代码的特征,以防止破解者摸出一定的规律或模式后编写电脑程序辅助破解:
1.随机的把<当日时间码>或<方法激活码>先赋值给局部变量,再使用局部变量参与表达式验证,这样生成的验证代码中使用的虚拟机指令是不一样的;
2.利用加法、异或、逻辑比较等运算满足交换率的特性,随机的改变表达式中各个项的位置;
3.并不是把插入代码集中添加到一个位置,而是在Method的前部随机找若干位置分散的插入虚拟机指令;
4.随机使用几种不同的方法来获取系统时间和运算<当日时间码>;
5.表达式验证中用到的静态变量,随机的、分散的分布在各个类中。
将以上几点组合起来,随机选用,这样在最终产生的类文件的字节码中极难找出各个加密点的共同特征或模式,因此编写程序进行自动破解几乎不可能。由于本发明激活码产生逻辑完全在服务器端,破解者也无法根据加密内容推导出激活码产生算法。对于试图进行破解的人来说,他必须找到所有加密位置,并在所有加密方法的二进制字节码上一一进行修改,只要有一两处遗漏的地方,就会导致程序运行中发生不可预知的错误。同时,本发明还可以对class文件进行有针对性的“反反编译”处理,处理后的绝大多数class文件都不能被主流反编译器(jad,jode等)完全反编译,使得“反编译——修改——重新编译”的简单破解方法彻底失效。
在本发明的这个实施例中,例如,可以使用系统日期或时间作为验证运算的一个输入,激活码必须与系统日期和时间匹配才能通过验证。使用与日期或时间不匹配的激活码将导致程序发生不可预知的错误。例如,每隔预定的时间(比如一天),被保护J2ME程序将自动向服务器请求更新激活码。
服务器端的控制
服务器端的基本职责是:响应手机软件的更新请求,验证请求合法性,生成激活码,并根据资费模式和用户定购关系发放激活码。服务器端比较灵活,可以根据具体需求来进行相应的扩展。
被保护J2ME软件向服务器发起的激活码更新请求中可以包含以下参数:
1.软件的唯一编号,服务器端使用此编号来确定该软件的资费模式;
2.用户的唯一标识(手机号/密码),服务器端使用此标识来识别合法用户并维护该用户的定购关系;
3.发起请求时刻的手机本地时间,因为手机的时间可能和服务器时间存在一定误差,因此服务器使用此时间来确定误差量。
服务器端根据以上参数可以选择是否正常回应:
1.用户唯一标识正确(手机号和密码匹配),且用户对软件拥有有效定购关系,则正常发放激活码;
2.用户唯一标识错误(手机号和密码不匹配),拒绝回应;
3.用户对软件没有有效定购关系,拒绝回应;
4.同一位用户一天内对激活码请求次数过多,则认为此用户唯一标识已被非法传播,可拒绝回应;
5.请求中的手机时间和服务器时间相差过多(比如1天),则认为用户恶意修改了手机系统时间,可拒绝回应;
服务器端向被保护J2ME软件回应的数据中包含以下内容:
1.状态码,正常或错误,对于出错的情况此代码表示错误代码;
2.新的激活码;
3.新的可用次数,使用可用次数可以实现计次资费模式。
本发明的软件加密和验证方法有以下几个技术优点:
1.可以完全基于MIDP1.0技术规范实现,不需要设备的特殊支持,可适用于市面上绝大多数终端。
2.本发明的软件加密和验证方法沿用了数字版权管理的思想,即:把内容和使用权分开,经过加密的内容可以任意传播,但必须获得适当的使用权后才能使用该内容,使用权限对象中包含对内容进行解密的必要数据。本发明充分考虑到了现有硬件平台和软件技术的局限性,对各种破解手段均设计了相应的对策。本发明是完善、可靠、健壮的DRM解决方案,把内容本身与内容的使用权限成功的剥离。内容已被加密,可以用任意方式传播,能够正常安装,但必须从服务器端获得适当的使用权限才能正常运行。而使用权限也可以使用多种方式、通过多种渠道进行销售。可以实现以使用时间和使用次数为单位的,非常灵活的资费控制模式。
3.通过技术手段,直接对最终的二进制可执行文件(.class文件)进行加密。开发者在开发流程中完全不必考虑版权保护问题,而可以把精力全部投入到内容的开发上。
4.激活码更新流程定期发生(例如,一天只发生一次),对用户体验的影响很小。而加入的激活码验证代码对软件的性能影响极小。
5.加入的代码非常精简,对软件发布包体积的影响很小,且可以通过改变加密点的数量来进行控制。
综上所述,本发明的软件加密和验证方法将软件的内容本身与其使用权限进行了有效的分离,拷贝可以自由的传播,但必须获得适当的激活码和相应的使用权限才能正常使用。激活码的产生和权限的发放则完全由服务器控制,安全而可靠。本发明使得J2ME等无线软件易于传播的特性不再成为软件开发者的敌人,相反,成为他们拓展市场的有力途径。
虽然上面参照特定实施例对本发明进行了说明,但是很明显的,在不脱离本发明的主要精神和范畴的前提下,可以对这些实施例进行各种修改和改变。所以,应该将说明书和附图理解为示例性的而非限制性的。