Use encryption technology to protect Java source code
Java
The source code of the program is easily peeked at by others. Anyone can analyze others' code as long as there is an anti-compiler. This article discusses how to avoid modifying the original program
In
Encryption
Technical Protection source generation
.
I. Why?
Encryption
?
For traditional C or C ++ languages, it is easy to protect the source code on the Web, as long as it is not released. Unfortunately, the source code of the Java program is easily separated.
People peek. Anyone can analyze others' code as long as there is an anti-compiler. Java's flexibility makes the source code easily stolen, but at the same time, it also makes it easier to protect the Code through encryption,
The only thing we need to know is the Java classloader object. Of course, in
Encryption
In the process
Java
Cryptography Extension (JCE) knowledge is also essential.
Several techniques
Technology can be "fuzzy"
Java
Class text
This greatly reduces the effect of the anti-compiler on processing class files. However, it is not difficult to modify the anti-compiler so that it can process these fuzzy-processed class files. Therefore, we cannot simply rely on Fuzzy Technology to ensure
Source code
Security
.
We can use popular encryption tools
Encryption
Ying
For example, PGP (pretty g
Oo
D privacy) or GPG (GNU Privacy
Guard ). In this case, the end user must decrypt the application before running it. However, after decryption, the end user has an unencrypted class file.
Encryption
There is no difference.
Java
The mechanism of loading bytecode in rows implicitly means that you can modify the bytecode. Every time the JVM loads a class file, it needs an object called classloader, which loads the new class
The JVM is running.
JVM
To
Classloader contains a class to be loaded (for example
Java
. Lang. Object) Name string, then the classloader is responsible for finding the class file, loading the original data, and converting it
Class Object.
You can customize classloader to modify it before executing the class file. This technology is widely used-here, it
It is used for decryption when class files are loaded. Therefore, it can be considered as an instant encryptor. Since the decrypted bytecode file will never be stored in the file system, it is difficult for the hacker to obtain the decrypted code.
Because the system is fully responsible for converting the original bytecode into a class object, it is not difficult to create a custom classloader object. You only need to obtain the original data first,
Then, you can perform any conversions including decryption.
Java 2 simplifies the creation of custom classloader to a certain extent. In
Java
In 2, the default Implementation of loadclass is still responsible for processing all the necessary steps, but to take into account various customized class loading processes, it also calls a new findclass method.
This provides a shortcut for writing a custom classloader, which reduces the hassle of overwriting findclass rather than loadclass. This
The method avoids repeated public steps required by all loaders, because this is the responsibility of loadclass.
However, the custom classloader in this article
This method is not used. The reason is simple. If the default classloader first looks for the encrypted class file, it can be found; but because the class file has
Encryption
So it does not recognize this class file, and the loading process will fail. Therefore,
We must implement loadclass by ourselves, which slightly increases the workload.
Ii. Custom Class Loader
Every running
JVM
You already have a classloader. The default classloader is stored locally according to the value of the classpath environment variable.
Find the appropriate bytecode file in the file system.
Application customization classloader requires a deep understanding of this process. We must first create a custom
Classloader class instance, and then explicitly require it to be loaded into another class. This is mandatory.
JVM
Associate the class and all the classes it needs with the custom classloader. Listing
1 shows how to mount class files with custom classloader.
[Listing
1: Use a custom classloader to load class files]
// First create a classloader object
- Classloader myclassloader =
New
Myclassloader ();
// Profit
Mount class files with custom classloader objects
// And convert it into a class Object
-
Class myclass = myclassloader. loadclass (
"Mypackage. myclass"
);
// The most
Create an instance of this class
-
Object newinstance = myclass. newinstance ();
// Note that all other classes required by myclass will pass
// Set
Automatic loading of classloader
As mentioned above, you only need to obtain
Data, and then pass the bytecode to the runtime system. The latter completes the remaining tasks.
Classloader has several important methods. Create a custom
When classloader is used, we only need to overwrite one of them, that is, loadclass, and provide code for getting the data of the original class file. This method has two parameters: the class name and a representation.
Does the JVM require the resolution of class name tags (that is, whether dependency classes are loaded at the same time ). If this flag is true, we only need
JVM
Previously, resolveclass was called.
[Listing 2: A simple implementation of classloader. loadclass]
-
Public
Class loadclass (string name, Boolean resolve)
Throws
Classnotfoundexception {
Try
{
// Me
Class Object to be created
- Class clasz =
Null
;
// Required Step 1: If the class is already in the system buffer,
// Me
You don't have to load it again.
-
Clasz = findloadedclass (name );
If
(Clasz! =
Null
)
Return
Clasz;
// Lower
Surface is custom part
Byte
Classdata [] =
/* Obtain bytecode data in some way */
;
If
(Classdata! =
Null
){
// The bytecode data is successfully read, and now it is converted into a class Object
-
Clasz = defineclass (name, classdata,
0
, Classdata. Length );
- }
// Required Step 2: If the above is not successful,
// Me
We tried to mount it with the default classloader.
If
(Clasz =
Null
)
- Clasz = findsystemclass (name );
// Required
Required Step 3: mount the relevant class if necessary
If
(Resolve & clasz! =
Null
)
- Resolveclass (clasz );
// Set
Class returned to the caller
Return
Clasz;
- }
Catch
(Ioexception IE ){
Throw
New
Classnotfoundexception (ie. tostring ());
- }
Catch
(Generalsecurityexception GSE ){
Throw
New
Classnotfoundexception (GSE. tostring ());
- }
- }
Listing
2 shows a simple loadclass implementation. Most of the Code is the same for all classloader objects, but a small part (marked with comments) is unique. In
During the processing, the classloader object requires several other auxiliary methods:
Findloadedclass: used for check to confirm
The specified class does not exist. The loadclass method should be called first.
Defineclass: Call
Defineclass converts it into a class object. This method must be called for any loadclass implementation.
Findsystemclass:
Supports the default classloader. If you cannot find the specified class (or intentionally do not need to create a custom method), you can call this method to try the default loading method. This
It is very useful, especially when loading the standard from a common JAR File
Java
Class time.
Resolveclass: When
JVM
When you want to load not only the specified class, but also all other classes referenced by the class, it sets the resolve parameter of loadclass.
To true. At this time, we must call resolveclass before returning the newly loaded Class Object to the caller.
III,
Encryption
, Decryption
Java encryption extension is Java Cryptography Extension (JCE. It is Sun's encryption service software, including
Encryption
And the key generation function. JCE is JCA (
Java
Cryptography
Architecture.
JCE does not specify a specific encryption algorithm, but provides a framework. The specific implementation of the encryption algorithm can be used as a service
Donor addition. In addition to the JCE framework, the JCE package also contains sunjce service providers, including many useful
Encryption
Algorithm, such as des (Data Encryption
Standard) and blowfish.
In this article, we will use the DES algorithm to encrypt and decrypt bytecode. The following uses JCE
Encryption
And the basic steps required for data decryption:
Step 1: generate
Security
Key.
You must have a key before encrypting or decrypting any data. The key is accompanied
Encryption
Listing 3 shows how to generate a key.
[Listing
3: generate a key]
Step 2: encrypt data
Data. After obtaining the key, you can use it to encrypt data. In addition to the decrypted classloader, there is usually
Encryption
Independent program of the application to be released (see Listing 4 ).
[Listing 4: keys used
Encryption
Raw Data]
-
// DES algorithm requirements
There is a trusted random number Source
- Securerandom sr =
New
Securerandom ();
// Generate
Keygenerator object
-
Keygenerator kg = keygenerator. getinstance (
"Des"
);
- Kg. INIT (SR );
// Generate the key
- Secretkey key = kg. generatekey ();
// Obtain the key data
Byte
Rawkeydata [] = key. getencoded ();
/* You can use the key to encrypt or decrypt it, or save it
- For future use of files */
- Dosomething (rawkeydata );
// DES algorithm
A trusted random number source is required
- Securerandom sr =
New
Securerandom ();
Byte
Rawkeydata [] =
/* Obtain the key data in some way */
;
// Create an eyspec object from the original key data
- Deskeyspec DKS =
New
Deskeyspec (rawkeydata );
// Create a key factory, and then
Use it to convert deskeyspec
// A secretkey object
Address: http://ajava.org/course/safe/15930.html