如何对java的class类进行加密

class由于可以进行反编译,这样对某个核心的模块来说,会造成关键技术的泄漏。如何对class类进行加密,是某些公司会考虑的问题。

以下公布一个实际的类。实现了一个ClassLoader,可以直接操作加密后的class文件。

其中的加密方式是采用DES加密。当然类需要先进行加密。ClassLoader做的是一个加载类前的解密工作。

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

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

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

  // main过程:我们要在这里读入密匙,创建Start的
  // 实例,它就是我们的定制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( "[Start: reading key]" );
    byte rawKey[] = getCodeByte(keyFilename);
    DESKeySpec dks = new DESKeySpec( rawKey );
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
    SecretKey key = keyFactory.generateSecret( dks );

    // 创建解密的ClassLoader
    instance = new Start( key );

    // 创建应用主类的一个实例
    // 通过ClassLoader装入它
//    System.err.println( "[Start: loading "+appName+"]" );
    Class clasz = instance.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( "[Start: running "+appName+".main()]" );

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

  public static Start getInstance() {
   return instance ;
  }
  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[];
//   try {
//    // 读取经过加密的类文件
//    classData = readClassFile(name);
//   } catch (Exception e) {
//    try {
//     classData = readZipFile(name) ;
//    } catch (Exception e) {
//     classData = readClassFile(name);
//    }
//   }
   classData = readFromURL(name) ;
 
         if (classData != null) {
           // 解密...
           byte decryptedClassData[] = cipher.doFinal( classData );
 
           // ... 再把它转换成一个类
           clasz = defineClass( name, decryptedClassData,
             0, decryptedClassData.length );
//           System.err.println( "[Start: decrypting class "+name+"]" );
         }
     } catch( Exception fnfe ) {
//      System.out.println("decrypting error: "+name) ;
//      fnfe.printStackTrace();
     }

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

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

      // 把类返回给调用者
      return clasz;
    } catch( Exception ie ) {
      throw new ClassNotFoundException( ie.toString());
    }
  }
 
  static private byte[] readFromURL(String className) throws IOException {
 String fileName = className.replace('.','/')+".class" ;
    URL classURL = ClassLoader.getSystemClassLoader().getResource(fileName);
 if (classURL == null) {
  throw new RuntimeException("Cannot find resource /"" +className + "/"");
 }
 InputStream in = classURL.openStream() ;
 int size=JspUtil.getUrlLength(classURL) ;
 byte[] b=new byte[(int)size];
 int rb=0;
 int chunk=0;
 while (((int)size - rb) > 0) {
   chunk=in.read(b,rb,(int)size - rb);
    if (chunk==-1) {
    break;
   }
   rb+=chunk;
 }
 if (rb != size)
   throw new IOException( "Only read "+rb+" of "+size+" for "+className );
 in.close();
 return b;
 
  }

  private static byte[] getCodeByte(String codeStr){
   byte[] bytes = new byte[codeStr.length()/2] ;
   for ( int i = 0,j=0 ; i < codeStr.length() ; ) {
    bytes[j++] = new Integer(getByte(codeStr.charAt(i++)) * 16  | getByte(codeStr.charAt(i++))).byteValue() ;
   }
   return bytes ;
  }
 
  private static byte getByte(char c) {
 switch(c)
 {
  case '0':
   return 0;
 
  case '1':
   return 1;
 
  case '2':
   return 2;
 
  case '3':
   return 3;
 
  case '4':
   return 4;
 
  case '5':
   return 5;
  case '6':
   return 6;
 
  case '7':
   return 7;
 
  case '8':
   return 8;
 
  case '9':
   return 9;
 
  case 'A':
   return 10;
 
  case 'B':
   return 11;
   
  case 'C':
   return 12;
   
  case 'D':
   return 13;
   
  case 'E':
   return 14;
   
  case 'F':
   return 15;
 }
 return 0 ;
  }
}

 

以下是加密类的实现:

public class EncryptClasses
{
  static public void main( String args[] ) throws Exception {
    String keyFilename = args[0];
    String algorithm = "DES";

    // 生成密匙
    SecureRandom sr = new SecureRandom();
    byte rawKey[] = Util.readFile( keyFilename );
    DESKeySpec dks = new DESKeySpec( rawKey );
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( algorithm );
    SecretKey key = keyFactory.generateSecret( dks );

    // 创建用于实际加密操作的Cipher对象
    Cipher ecipher = Cipher.getInstance( algorithm );
    ecipher.init( Cipher.ENCRYPT_MODE, key, sr );

    // 加密命令行中指定的每一个类
    for (int i=1; i<args.length; ++i) {
      String filename = args[i];
  
   File pathFile = new File(filename) ;
  
   if ( pathFile.isDirectory() ) {
  encryptPathFile(ecipher,pathFile) ;
   } else if ( pathFile.isFile() ) {
  encryptClassFile(ecipher,pathFile);
   } else
   System.out.println("error when parse "+pathFile.getPath()) ;
      // 读入类文件
    }
  }
 
  private static void encryptClassFile(Cipher ecipher,File classFile) {
 try {
  if ( classFile.getPath().lastIndexOf(".class") < 0 ) return ;
  // 读入类文件
  byte classData[] = Util.readFile( classFile.getPath() );
  
  // 加密
  byte encryptedClassData[] = ecipher.doFinal( classData );
  
  // 保存加密后的内容
  Util.writeFile( classFile.getPath(), encryptedClassData );
  
  System.out.println( "Encrypted "+classFile.getPath() );
 } catch (Exception e) {
  
  e.printStackTrace();
 }
  }
 
  private static void encryptPathFile(Cipher ecipher,File pathFile) {
   File[] classFiles = pathFile.listFiles() ;
   for ( int i  = 0 ; i < classFiles.length ; i++ ) {
    File classFile = classFiles[i] ;
    if ( classFile.isDirectory() ) encryptPathFile(ecipher,classFile);
    else if ( classFile.isFile() ) encryptClassFile(ecipher,classFile);
    else System.out.println("error when parse "+classFile.getPath()) ;
   }
  }
 
}

简要介绍: 本工具是对java class文件进行加密保护的工具!本工具全面支持linux/unix/windows操作系统。 众所周知,java编译后的class文件是一种中间字节字文件, 很容易被反编译工具反编译,而传统的java源代码保护方法基本都是采用混淆的方式, 但这样会带来很多麻烦,而且也不能真正保护class文件, 本工具是对class文件进行加密,采用jni的方式解密运行, 加密算法达到256位,加密后的class文件不可能被破解,反编译工具也对加密后的class文件无能为力。 运行方式: 运行时,要能正确的加载加密后的class文件, 必须使用我们提供的动态链接库classloader.dll(wndows操作系统)或者libclassloader.so(Linux、Unix操作系统)。 执行java时带上参数-agentlib:\classloader 注意此处不要后缀名.dll(或者.so)。 如: windows下执行javajava -agentlib:C:\classloader HelloWorld Linux、Unix等系列操作系统下执行javajava -agentlib:/home/classloader HelloWorld 应用场合: 独立的应用程序,运行java时,带上参数-agentlib:\classloader Tomcat、Jboss等Java application server修改启动脚本, 把执行java的命令行后面加上参数-agentlib:\classloader 适应环境: 操作系统:所有操作系统,Windows系统、Linux/Unix,只是运行时, 使用的动态链接库文件不一样而已,其它配置完全一样。 jdk必须1.5以上。 下载地址: http://www.cr8ge.com/admin/upload/2011020917102317195.rar http://www.kmcxzs.cn/admin/upload/2011020917131925480.rar
软件介绍 本工具是对java class文件进行加密保护防止反编译的工具!本工具全面支持linux/unix/windows操作系统。 继推出v1.0版本后,获得了用户大量的支持与的反馈,我们再次推出本v2.0版,对加密算法进行了更大的改进,安全性大大提升! 众所周知,java编译后的class文件是一种中间字节字文件, 很容易被反编译工具反编译,而传统的java源代码保护方法基本都是采用混淆的方式, 但这样会带来很多麻烦,而且也不能真正保护class文件, 本工具是对class文件进行加密,采用jni的方式解密运行, 加密算法达到256位,加密后的class文件不可能被破解,反编译工具也对加密后的class文件无能为力。 运行方式: 运行时,要能正确的加载加密后的class文件, 必须使用我们提供的动态链接库classloader.dll(windows操作系统)或者libclassloader.so(Linux、Unix操作系统)。 执行java时带上参数-agentlib:\classloader 注意此处不要后缀名.dll(或者.so)。 如: 我把classloader.dll放在C:\目录下; 运行加密后的class文件命令如下: windows下执行javajava -agentlib:C:\classloader Sample Linux、Unix等系列操作系统下执行javajava -agentlib:/home/classloader Sample 或者把libclassloader.so拷贝到如“/home/yzj/jdk1.6.0_23/jre/lib/i386/”这jdk的运行目录下, 然后执行java如:java -agentlib:classloader Sample 当然如果class文件没加密,这样运行也不会出错! 应用场合: 独立的应用程序,运行java时,带上参数-agentlib:\classloader Tomcat、Jboss等Java application server修改启动脚本, 把执行java的命令行后面加上参数-agentlib:\classloader 适应环境: 操作系统:所有操作系统,Windows系统、Linux/Unix,只是运行时, 使用的动态链接库文件不一样而已,其它配置完全一样。 jdk必须1.5以上。 备注:如果下载站下载下来的程序有运行bug,请从上面两个下载地址更新软件。并给我们留言!谢谢... 升级提示:v2.1相比v2.0修改了一个注册bug。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值