Java has three main features: platform independence, network mobility, and security. The Java architecture provides powerful support and assurance for these three features, this article focuses on the principles and usage of the Java architecture to support information security.
Java Architecture
Shows the architecture of Java. First, the Java source code Java file is compiled by the compiler into a Java binary bytecode class file, and then the class file is loaded by the class loader in the Java Virtual Machine, at the same time, the class loader will load the original Java API class file. The class loader is mainly responsible for loading, connecting and initializing these class files, and then handed over to the execution engine in the Virtual Machine for running, the execution engine interprets the Java commands in the class file as a specific local operating system method for execution, while the security manager controls the access to external resources according to the configured security policy.
Java is executed in a way that is not compiled but interpreted. The same source code on different platforms is compiled into the same binary bytecode that complies with Java specifications, then, it is handed over to the virtual machines supporting the respective platforms for explanation and execution. "compile first, then explain, and then execute." the three-step approach enables Java to implement "write once, run everywhere ", if Java applications use 100% standard Java APIs and do not directly call local methods, they can be used on multiple platforms without modification, such platform independence makes applications in heterogeneous network environments or embedded systems more convenient and realistic. The Network Mobility of Java brings about a brand new software model. Based on the distributed processing mode, the software and data can be transmitted to the client through the network, this ensures that the client has the necessary software to browse and manipulate data transmitted over the network. The Java architecture supports cutting a single execution file into a small binary bytecode File class file, these files can be dynamically connected and scaled according to application requirements. Java architecture supports security mainly through Java language security, virtual machine classloaders, security managers, and Java security APIs to prevent malicious program attacks, the program cannot damage the user's computer environment; prevent intrusion; the program cannot obtain the confidential information of the host or the Intranet; identify and verify the identity of the program provider and the user; encrypt, encrypt the data transmitted and exchanged, or encrypt the persistent data. Verify the operation, set rules, and verify the operation.
Java information security necessity
As Internet applications become more and more widely used and the Internet itself has unique resource sharing, it is very important for users to obtain and process information in a timely and accurate manner according to their needs, this is also why Java is rapidly developing and widely accepted. However, at the same time, the network also provides a potential way to access computers through attacks, especially when users download network software to run locally, which requires Java to prevent viruses/Trojans, protects information and the local environment. For example, when we browse a webpage, the applet on the webpage may be automatically downloaded and run, and the applet may come from unreliable places, or we can use unreliable service objects on the network found through the Jini service to obtain the service. If there is no security mechanism provided by the Java architecture, this may lead to the introduction of a hostile program that causes information loss, Data leaks, the belief in data forgery, and the modification of Local Computer Security Settings, and other consequences, bringing unknown serious consequences.
Java security
Java Language designers designed Java based on C ++. Therefore, compared with C ++, its syntax is simpler and clearer, the structure, unit, operator overload, and virtual basic class are not used in Java, and multiple interfaces are implemented without multiple inheritance. This reduces the chances of developers making mistakes and helps them write safer code.
Java removes the confusing and error-prone "Pointer" in the C ++ language and replaces it with a list, heap, hash table, and other structures to avoid any insecure structure. Java also has no index check for array access, because this will often lead to unpredictable program operations, and all its array access must first check whether it is out of bounds. Java requires that all variables cannot be used before initialization. for basic data type variables, they are automatically assigned to an initial value, avoiding uninitialized variables to obtain memory information. All these make the program unable to access any memory address. The entity information in the memory can only be accessed through objects with permissions, instead, the type pointer is forcibly converted to a memory pointer like C ++, and then the private variable is found through the memory lookup method.
Java memory allocation is transparent to developers. developers use the new method to create objects. In this case, the virtual machine will find the appropriate memory space from the heap memory, developers do not need or cannot intervene. For memory reclaim, Java avoids explicit intervention by developers, such as C free or C ++ delete commands, and avoids unintentional Memory Corruption by developers. Java uses the "Garbage Collection" mechanism of virtual machines to realize automatic memory management, releasing memory resources that are no longer in use. The memory recycler is like a garbage collection car, however, unlike the collection car we see on the street, which only collects garbage from people in the waste bin, it also needs to go to your house to help you find out the unwanted garbage, take these things away, and finally sort out the home space to free up the maximum space for you to release new things. The purpose of the Java memory recycler is to find objects that are no longer referenced, release the memory space, and sort out the memory fragments to avoid "insufficient memory.
For serialized objects exchanged in the network, it is easy to access the private information of objects when recreating objects. Java provides two methods to protect information at this time, one method is to add the transient keyword to the variable so that the variable will not be read and written during Object serialization. The other is to implement the externalizable interface instead of the serizlizable interface, in this way, the object can only be saved and rebuilt through the writeexternal and readexternal methods, and other methods cannot be performed.
These are the basis of information security provided by Java.
Class Loader
Although it is called a class loader, in fact, the class loader in the Java Virtual Machine is not only responsible for loading but also responsible for connecting and initializing the Java type required by the application. Loading is to read the binary bytecode into the virtual machine, and the connection is to allocate class variable memory for the read type and convert the symbols used in the constant pool of the type into direct reference, the final initialization process is to assign an appropriate initial value to the type variable.
The Class Loader provides different namespaces for the loaded classes. the bytecode generated by the Unified source code is loaded into the same namespace. classes with the same class name cannot be loaded in the same namespace, classes in the same namespace can directly interact with each other, while classes in different namespaces cannot interact with each other unless an explicit interaction mechanism is provided, the namespace and class member access permissions are used to protect the trusted class boundaries.
The class loader is divided into four types: start class loader, standard extension class loader, path class loader, and network class loader. The start class loader loads the original Java API class from the local system to start the Java Virtual Machine. The other three loaders load user-defined classes at runtime, the standard extension class loader loads standard Java classes extended by different virtual machine providers, and classes in the classpath are loaded by the path class loader, network class loaders load class files downloaded over the network. Each type of loaders creates an loader instance when loading classes. The Class Loader adopts the parent-parent delegation chain mode (this mode is similar to the responsibility chain mode mentioned in gof's design mode). Besides starting the class loader, each class loader has its own "parent ". A class can define its own parent by using three methods: the first method is reference. For example, Class A references Class B (that is, A and B are correlated ), the Class B loader acts as the "parent" of the Class A loader, and is loaded earlier than Class A. The second method is used to customize "parent ", in this case, the "parent" of the loaded class is itself the Class Loader. The third method is the default method used when the first two methods are not used, by default, the start class loader is used as "parent ".
During the loading process, when a load request is sent, the loader first asks its "parent"-path class loader-to find and load the class, the loader also loads requests to its "parent", layer-by-layer requests until the loader starts to obtain the request to find and load the class, if this class is not loaded and cannot be found, the subloader that returns the result is loaded by the subloader until the request is returned to the original loader. If the loading is not successful yet, the Network Class Loader tries to find and download data from the network. If it fails, it will throw a noclassdeffounderror exception.
This process ensures that the start class loader can load classes before the standard extension class loader, and the standard extension class loader can load classes before the path class loader, finally, it is loaded by the Network Class Loader. For example, an application is trying to load a Java with malicious code. lang. string class, because it is a part of Java API, The namespace they load can get special access permissions of the trusted class, but because the start class loader is first loaded, so Java. lang. string will only be loaded by the startup class from the original Java API, while Java with malicious code. lang. the string class is not loaded, which effectively protects the trusted class boundary.
The Class Loader also includes a type check function module, which is responsible for ensuring program robustness. It performs four checks in the type life cycle. The first check is to check the structure of the binary bytecode when loading. First, the format must meet the specifications defined by the Java language, then make sure that the class bytecode to be loaded is a Java instruction in a combination. The second check is the semantic check of the type data during the connection to ensure that the bytecode complies with the specification during compilation. For example, the final class will not be derived from the subclass, the final method is not reloaded. Each class has only one superclass. The basic data type is not forcibly converted to other data types. The third check is also related to the instruction structure during the connection to ensure that the instruction's operand type and value are correct, and the operand stack will not experience upper overflow or lower overflow. The last check is to check whether the symbolic reference in the type is correct when it is parsed during dynamic connection. All of the above problems will cause malicious behavior, so you must check before running. Some checks will check when the virtual machine runs bytecode, such as array out-of-bounds, object type conversion, etc, once the check finds a problem, an exception is thrown to prevent the program from being executed.
The Class Loader avoids some hostile people from writing their own Java classes, and these class methods contain commands beyond the method, the failure of the Virtual Machine and the possibility of obtaining confidential information ensure the robustness of the program and prevent the execution of malicious code that replaces the original Java API, in addition, the Class Loader prevents malicious code from interfering with malicious code, protects the boundaries of trusted API class libraries, and ensures that code operations can be performed.
Security Manager
The security manager sets up a "sandbox" to protect the environment of the Java Virtual Machine. This "sandbox" provides the program with an operating environment that limits the application, resources outside the virtual machine will not be damaged by malicious code inside the virtual machine. Security policies of the security manager can flexibly establish fine-grained access control policies and grant different resource access permissions to different code units, this is also one of the biggest features and advantages of the Java architecture security model.
First, we need to clarify the source of the Code unit before granting permissions. signature guarantees allow users to confirm the source of the file, and these files are not modified before being loaded on the local virtual machine, operation permissions can be assigned only when the reliability of source code sources is ensured. You can use the jarsigner tool in JDK to sign a class or jar file. It first calculates one-way hash Based on the file content, generates a hash value, and then adds the hash to the end of the file as part of the file and passes it to the user, after receiving the file, the user generates a new hash value and compares it with the hash value at the end of the file. If the two hash values are the same, the file content is not changed, although different file content may generate the same hash value, Java generally uses the 124-bit hash, this length cannot be calculated to generate a known hash value from a different input. There is no way to ensure the source of the Code by means of the hash value, because malicious people can completely replace the entire file and the hash value, in order to prevent such a thing from happening, the hash value must be encrypted with the private key before sending. Why not encrypt the entire file? Because jarsigner uses the DES algorithm by default, encryption is a time-consuming process, we only need to encrypt the hash value to ensure the source of the file, not the confidentiality of the file, after receiving the file, the user decrypts it with the public key of the file provider to verify that the hash value is not replaced.
The code source is clarified, and the operation permission can be assigned to it after it is not modified. The security policy is a Java. sercurity. policy implementation class. The policy mainly contains information about the code source and corresponding permissions, the check method of the security manager determines the operation permissions assigned to the imported code based on the policy object. The code source is represented by Java. Security. codesource. This object contains a set of certificate objects, indicating the signature guaranteed for this code file. The permission is implemented using Java. sercurity. permission is represented by a subclass instance. Each permission has three attributes: type, name, and operation that can be performed. The type indicates the resource type of permission control, for example, filepermission indicates the file operation permission, and the name indicates the object for permission control. For example, filepermission is named "/mydoc/order.txt", indicating the operation permission for file order.txt, the operation attributes that can be performed indicate the operations that can be performed by this permission. For example, "read" indicates that this filepermissioncan be used to read order.txt.
Developers can compile code to inherit the securitymanager class and establish their own security manager to set security policies. A more convenient and common method is to set policy files. This is an example of a policy file:
// Obtain the signed public key from the mykeys File Keystore "mykeys" // The fathersign Code grants the permission to read the order.txt File Grant signedby "father "{ Permission java. Io. filepermission "order.txt", "read "; } // All jars and class from {java_home}/security/EX/directory have the permission to read and write the order.txt File Grant codebase "file: $ {java_home}/security/EX /*"{ Permission java. Io. filepermission "order.txt", "read, write "; } // All jar files and class files with the wife signature under the {java_home}/security/EX/directory have the permission to accept, connect to, and listen to port 8080. Grant signedby "wife" codebase "file: $ {java_home}/security/EX /*"{ Permission java. Io. socketpermission "*: 8080", "Accept, connect, listen "; } // All codes have the permission to read and write the appversion. properties file. Grant { Permission java. Io. filepermission "appversion. properties", "read, write "; } |
If an application does not specify to start the security manager for intervention, all its operations will not be restricted by the manager. There are two ways to specify to start the security manager, one is specified when running the application, and the other is specified in the Code.
Java-djava. serciruty. Manager myapplication |
Start the default security manager. At this time, the security policy is set according to the Java default global policy file. This file is
/Java_home/lib/security/Java. Policy. Java-djava. serciruty. Manager-djava. serciruty. Policy = <URL> myapplication |
Start the security manager. In addition to the default global policy file. serciruty. the policy file specified by the Policy parameter is used to set the security policy. The file name can be used either by URL or directly by file name.
If it is specified in the Code, when the program sets a java. Lang. securitymanager instance through the setsecuritymanager method, the security manager starts to control the application level. When the class loader loads the class to a virtual machine, the security manager finds the corresponding permissions based on the code source and signature, and then establishes the protection domain protectiondomain of the class, the protected domain defines all permissions for this class. When an application uses this class and performs any possible unsafe operations, it will request an operation license from the security manager. The security manager has a series of check methods to check whether the operation is feasible, for example, the checkread method checks whether a file can be read and the checkwrite method checks whether a file can be written. The manager calls the relevant check method according to the operation request type, the check method checks whether the operation is feasible Based on the protection domain of the class. If the operation has no permission, an exception is thrown, and the operation cannot be executed after receiving the exception. If the operation is feasible, the check method returns smoothly and the operation continues.
The preceding signature verification, security policy definition, and security manager permission check processes effectively protect the security of external resources used by Java applications. Note that the core API class loaded by the start class loader is not controlled by the permission of the security manager, this is why the class loader is used to prevent the core API from being replaced by malicious code.
Security APIs provided by the Java Architecture
The Java architecture provides three main security APIs: Java authentication and authorization Service (JAAS) and Java Secure Socket Extension (Java Secure Socket Extension, JSSE) and java encryption extension (Java Cryptography Extension, JCE ). As mentioned above, JAAS used in Security Manager, in this section, we refer to the Java encryption extension package JCE and Java Secure Socket Extension package JSSE provided by Java to encrypt information, these APIs provide encryption algorithms to encrypt and decrypt arbitrary data as needed.
The Java encryption extension package JCE provides key-Based Encryption Through javax. crypto. the cipher class implements data encryption and decryption. the encryption and decryption object can enable the array object in the program, or read or write data through the Java stream interface. Cipher-type encryption allows you to select multiple encryption algorithms, encryption modes, and fill mechanisms. The encryption algorithm JCE provides des, multiple des, pbewithmd5anddes, RSA, and blowfish. Des is the Data Encryption Standard adopted by many organizations. Multiple des use multiple des passwords for how long DES encryption increases the difficulty of attacks, but also increases the time spent in encryption and decryption; pbewithmd5anddes previously mentioned that it is mainly used to calculate the hash and then encrypt the hash to implement signature authentication. RSA is a group encryption algorithm published in 1978, blowfish is also the most widely used public key algorithm. Blowfish is an encryption algorithm published by Bruce Schneier without applying for a patent and publishing the implemented code, it is suitable for situations where you do not need to change the key frequently.
The encryption mode is used to further adjust the encrypted data to increase the difficulty of decryption. The mode can also process the grouped plaintext as the plain text of the stream to reduce the amount of data processed each time, JCE provides the electronic cryptographic mode ECB, the password encapsulation link mode CBC, the password feedback mode CFB, and the output feedback mode ofB. (I added myself: For group passwords such as 3eds, there is a one-to-one correspondence between the plaintext group and the corresponding ciphertext group for a given key. In other words, if the key is the same, duplicate plaintext groups can always encrypt the same ciphertext. If a piece of plain text includes repeated groups, the ciphertext will also contain the same pattern, which can help attackers. In addition, each ciphertext Group of the group password lacks an internal link. This means that an attacker who monitors encrypted groups may randomly change or delete the group. E-cryptographic model ECB is the simplest mode, only groups 8 bytes of plaintext and encrypts the entire plaintext group at a time. It is suitable for encrypting binary data streams. The password encapsulates the connection mode CBC, use an 8-byte group as the input data to correct the encryption results of another group. In this way, the Data Types contained in the text can be hidden. In this mode, text data can be encrypted; the cryptographic feedback mode is CFB. Similar to the CBC mode, the implementation is slightly different. The difference is that the CBC mode requires plaintext grouping for correction, while the CFB requires less data and the length can be adjusted; the output feedback mode ofB is suitable for situations where the encrypted data may change during transmission. A change error will only affect this bit without affecting the entire group. JCE can select two filling mechanisms: pcks5padding and nopadding. when the former is used to group plaintext, if the number of bytes is multiples of 8, the data length must be a complete group, the latter does not fill in the Data. when the text is grouped, an exception is thrown if the number of bytes is a multiple of 8.
The Java Secure Socket Extension package JSSE provides encryption based on data transmitted between sockets. The biggest difference between JCE and JCE is that the data encryption process and transmission process are not separated, if JAAS allows us to identify application providers and restrict their access to only authorized systems, JSSE ensures the data security transmitted by our applications. JSSE implements SSL (Secure Socket Layer) encryption. as the basis of the HTTPS protocol, SSL provides methods to encrypt data on TCP sockets, it is also the most common Encryption Method Based on Web applications. To use the jsse api, we first need to establish an SSL environment. the SSL server establishes a key inventory and puts the server's private key and authentication identity certificate, and the ssl client establishes a trust library to verify the trust certificate, both the keystore and the trusted keystore are managed through the keytool tool in JDK. Second, we need to use a JSSE socket factory instead of directly using java.net. the socket class obtains the socket. The client code obtains the socket from sslsocketfactory, and the server code obtains the socket from sslserversocketfactory. by obtaining the socket from these factories, we can use the framework provided by the JSSE provider, instead of simply creating standard, insecure sockets as the java.net package allows us to do. With JSSE, we can define secure socket connections between clients and servers that run any application protocol, including HTTP, TCP/IP, FTP, or telnet.
Summary:
Information security is a problem that must be paid attention to and solved in the computer field. The Java architecture provides a flexible and robust framework for information security. As long as we use it properly, we can ensure information security, reduce our costs and risks. At the same time, we also need to strengthen some other related security work, such as protecting our private key, so as to ensure that the Java security framework plays the biggest role. Java security framework also has some shortcomings, such as applications constantly allocating memory or creating new threads causing denial of service, and ing security models with system users. With the development of information technology, information security will also face more and more challenges, all of which require improved and further development of the Java security framework.