⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 运用加密技术保护java源代码.txt

📁 含有许多JAVA的技巧!
💻 TXT
📖 第 1 页 / 共 2 页
字号:
   // 创建一个密匙工厂,然后用它把DESKeySpec对象转换成
   // 一个SecretKey对象
   SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
   SecretKey key = keyFactory.generateSecret( dks );

   // Cipher对象实际完成解密操作
   Cipher cipher = Cipher.getInstance( "DES" );

   // 用密匙初始化Cipher对象
   cipher.init( Cipher.DECRYPT_MODE, key, sr );

// 现在,获取数据并解密
   byte encryptedData[] = /* 获得经过加密的数据 */

   // 正式执行解密操作
   byte decryptedData[] = cipher.doFinal( encryptedData );

   // 进一步处理解密后的数据
   doSomething( decryptedData );


四、应用实例 
前面介绍了如何加密和解密数据。要部署一个经过加密的应用,步骤如下: 

步骤1:创建应用。我们的例子包含一个App主类,两个辅助类(分别称为Foo和Bar)。这个应用没有什么实际功用,但只要我们能够加密这个应用,加密其他应用也就不在话下。 
步骤2:生成一个安全密匙。在命令行,利用GenerateKey工具(参见GenerateKey.java)把密匙写入一个文件: % java GenerateKey key.data


步骤3:加密应用。在命令行,利用EncryptClasses工具(参见EncryptClasses.java)加密应用的类: % java EncryptClasses key.data App.class Foo.class Bar.class

该命令把每一个.class文件替换成它们各自的加密版本。 
步骤4:运行经过加密的应用。用户通过一个DecryptStart程序运行经过加密的应用。DecryptStart程序如Listing 6所示。 
【Listing 6:DecryptStart.java,启动被加密应用的程序】

import java.io.*;
import java.security.*;
import java.lang.reflect.*;
import javax.crypto.*;
import javax.crypto.spec.*;

public class DecryptStart extends ClassLoader
{
// 这些对象在构造函数中设置,
// 以后loadClass()方法将利用它们解密类
private SecretKey key;
private Cipher cipher;

// 构造函数:设置解密所需要的对象
public DecryptStart( SecretKey key ) throws GeneralSecurityException,
     IOException {
   this.key = key;

   String algorithm = "DES";
   SecureRandom sr = new SecureRandom();
   System.err.println( "[DecryptStart: creating cipher]" );
   cipher = Cipher.getInstance( algorithm );
   cipher.init( Cipher.DECRYPT_MODE, key, sr );
}

// main过程:我们要在这里读入密匙,创建DecryptStart的
// 实例,它就是我们的定制ClassLoader。
// 设置好ClassLoader以后,我们用它装入应用实例,
// 最后,我们通过Java Reflection API调用应用实例的main方法
static public void main( String args[] ) throws Exception {
   String keyFilename = args[0];
   String appName = args[1];

    // 这些是传递给应用本身的参数
   String realArgs[] = new String[args.length-2];
   System.arraycopy( args, 2, realArgs, 0, args.length-2 );

   // 读取密匙
   System.err.println( "[DecryptStart: reading key]" );
   byte rawKey[] = Util.readFile( keyFilename );
   DESKeySpec dks = new DESKeySpec( rawKey );
   SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
   SecretKey key = keyFactory.generateSecret( dks );

   // 创建解密的ClassLoader
   DecryptStart dr = new DecryptStart( key );

   // 创建应用主类的一个实例
   // 通过ClassLoader装入它
   System.err.println( "[DecryptStart: loading "+appName+"]" );
   Class clasz = dr.loadClass( appName );

   // 最后,通过Reflection API调用应用实例
   // 的main()方法

   // 获取一个对main()的引用
   String proto[] = new String[1];
   Class mainArgs[] = { (new String[1]).getClass() };
   Method main = clasz.getMethod( "main", mainArgs );

   // 创建一个包含main()方法参数的数组
   Object argsArray[] = { realArgs };
   System.err.println( "[DecryptStart: running "+appName+".main()]" );

   // 调用main()
   main.invoke( null, argsArray );
}

public Class loadClass( String name, boolean resolve )
     throws ClassNotFoundException {
   try {
     // 我们要创建的Class对象
     Class clasz = null;

     // 必需的步骤1:如果类已经在系统缓冲之中
     // 我们不必再次装入它
     clasz = findLoadedClass( name );

if (clasz != null)
       return clasz;

     // 下面是定制部分
     try {
       // 读取经过加密的类文件
       byte classData[] = Util.readFile( name+".class" );

       if (classData != null) {
         // 解密...
         byte decryptedClassData[] = cipher.doFinal( classData );

         // ... 再把它转换成一个类
         clasz = defineClass( name, decryptedClassData,
           0, decryptedClassData.length );
         System.err.println( "[DecryptStart: decrypting class "+name+"]" );
       }
     } catch( FileNotFoundException fnfe ) {
     }

     // 必需的步骤2:如果上面没有成功
     // 我们尝试用默认的ClassLoader装入它
     if (clasz == null)
       clasz = findSystemClass( name );

     // 必需的步骤3:如有必要,则装入相关的类
     if (resolve && clasz != null)
       resolveClass( clasz );

     // 把类返回给调用者
     return clasz;
   } catch( IOException ie ) {
     throw new ClassNotFoundException( ie.toString()
);
   } catch( GeneralSecurityException gse ) {
     throw new ClassNotFoundException( gse.toString()
);
   }
}
}

对于未经加密的应用,正常执行方式如下: % java App arg0 arg1 arg2

对于经过加密的应用,则相应的运行方式为:% java DecryptStart key.data App arg0 arg1 arg2


DecryptStart有两个目的。一个DecryptStart的实例就是一个实施即时解密操作的定制ClassLoader;同时,DecryptStart还包含一个main过程,它创建解密器实例并用它装入和运行应用。示例应用App的代码包含在App.java、Foo.java和Bar.java内。Util.java是一个文件I/O工具,本文示例多处用到了它。完整的代码请从本文最后下载。

五、注意事项 
我们看到,要在不修改源代码的情况下加密一个Java应用是很容易的。不过,世上没有完全安全的系统。本文的加密方式提供了一定程度的源代码保护,但对某些攻击来说它是脆弱的。 

虽然应用本身经过了加密,但启动程序DecryptStart没有加密。攻击者可以反编译启动程序并修改它,把解密后的类文件保存到磁盘。降低这种风险的办法之一是对启动程序进行高质量的模糊处理。或者,启动程序也可以采用直接编译成机器语言的代码,使得启动程序具有传统执行文件格式的安全性。 

另外还要记住的是,大多数JVM本身并不安全。狡猾的黑客可能会修改JVM,从ClassLoader之外获取解密后的代码并保存到磁盘,从而绕过本文的加密技术。Java没有为此提供真正有效的补救措施。 

不过应该指出的是,所有这些可能的攻击都有一个前提,这就是攻击者可以得到密匙。如果没有密匙,应用的安全性就完全取决于加密算法的安全性。虽然这种保护代码的方法称不上十全十美,但它仍不失为一种保护知识产权和敏感用户数据的有效方案。 

参考资源 

在运行时刻更新功能模块。介绍了一个利用类库加载器ClassLoader 实现在运行时刻更新部分功能模块的Java程序,并将其与C/C++中实现同样功能的动态链接库方案进行了比较。 
Java 技巧 105:利用 JWhich 掌握类路径。展示一个简单的工具,它可以清楚地确定类装载器从类路径中载入了什么 Java 类。 
要了解更多的 Java 安全信息,请阅读 java.sun.com的 Java Security API 页。 
如何封锁您的(或打开别人的) Java 代码。Java 代码反编译和模糊处理的指南。 
使您的软件运行起来:摆弄数字。真正安全的软件需要精确的随机数生成器。 

下载本文代码:EncryptedJavaClass_code.zip

关于作者 
俞良松,软件工程师,独立顾问和自由撰稿人。最初从事PB和Oracle开发,现主要兴趣在于Internet开发。您可以通过 javaman@163.net 和我联系。

本栏文章均来自于互联网,版权归原作者和各发布网站所有,本站收集这些文章仅供学习参考之用。任何人都不能将这些文章用于商业或者其他目的。( ProgramFan.Com ) 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -