如何对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      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)