[Java study notes (123)] Java security class loader, security manager, digital signature, encryption

This article is published by the official account [Developing Pigeon]! Welcome to follow! ! !


Old Rules-Sister Town House:

One. Java security

(I. Overview

        Java technology provides three mechanisms to ensure security:

  1. Language design features (array boundary check, type conversion check)

  2. Access control mechanism, used to control the operations that the code can perform (file access, network access)

  3. Code signing, the author of the code can use standard encryption algorithms to authenticate the Java code and check whether the code has been modified


(Two) class loader

        The Java compiler converts the source instructions for the virtual machine. The virtual machine code is stored in a class file with a .class extension. Each class file contains the definition and implementation code of a certain class or interface.

1. Class loading process

        The virtual machine only loads the class files needed for program execution, and first reads the content of the class file. If the class has the domain or super class of another class, then these class files will also be loaded, loading a certain class dependent The process of all classes is called class resolution. Next, the virtual machine loads the main method in the class. If the main method needs more classes, it will load these classes.

2. The hierarchy of class loaders

        Every Java program has at least three class loaders: boot class loader, platform class loader, and system class loader.

        The boot class loader is responsible for loading platform classes in the internal modules of the JDK, and the loader does not have a corresponding ClassLoader object. Before Java9, the Java platform classes are located in rt.jar. Today's Java platform is modular. Each platform module contains a JMOD file. The platform class loader will load all classes in the Java platform that the boot class loader has not loaded. . The system class loader will load application classes from the module path and the class path.

        Class loaders have a parent-child relationship. In addition to the bootstrap class loader, each class loader has a parent class loader. Each parent class loader will be loaded first. When the parent class loader fails to load, it will be loaded. The given class. Certain plug-in classes can also be loaded. Use an instance of the URLClassLoader class to load the plug-in class. Since no parent class loader is specified in the URLClassLoader constructor, the father of pluginLoader is the system class loader.
Class loading is loaded because other classes need it. Occasionally, we also need to interfere and specify the class loader, such as loading a helper method:

Class.forName(classNameString);

        This method is called from a plug-in class, classNameString specifies a class contained in the JAR of the plug-in, this class is loaded by Class.forName, using the system class loader, and for it, the plug-in The classes in the JAR are not visible. This phenomenon is called class loader inversion. Therefore, the plug-in class needs to use an appropriate class loader, and set the specified class loader as the context class loader of the current thread. Each thread has a reference to the class loader, called the context class loader, the main thread The context class loader is the system class loader. When a new thread is created, its context class loader will be set to the context class loader of the parent thread. As follows:

Thread t= Thread.currentThread();
t.setContextClassLoader(loader);

        Then the plug-in class can obtain this context class loader:

Thread t = Thread.currentThread();
ClassLoader loader = t.getContextClassLoader();
Class<?> cl = loader.loadClass(claaName);

3. Class loader as a namespace

        In the same virtual machine, there can be two classes, their class name and package name can be the same, the class is determined by its full name and class loader, for example, the application server will use a separate for each application Class loader, which allows the virtual machine to distinguish classes from different applications.

4. Bytecode verification

        When the class loader passes the bytecodes of the newly loaded Java platform classes to the virtual machine, these bytecodes must first be checked by the verifier, which is responsible for checking which instructions cannot be executed for obvious destructive operations , Except for system classes, all classes must be checked. Such as:

(1) Initialization of variables;

(2) Match between method call and object reference type;

(3) All accesses to local variables fall on the runtime stack;

(4) The stack does not overflow during runtime;


(3) Security Manager

        Once the class is loaded into the virtual machine and checked by a validator, the second security mechanism of the Java platform will be activated. This mechanism is the security manager.

1. Permission Check

        The security manager is a class that is responsible for controlling whether specific operations are allowed to be executed, such as exiting the virtual machine, etc. When running Java applications, the default setting is not to install the security manager, and all operations are acquiesced. We can set up a strategy and execute it through the countermeasures in the strategy when we encounter security problems. However, the integrity of the security policy depends on careful coding. The system service provider in the standard library must negotiate with the security manager before attempting to continue any sensitive operations.

2. Java platform security

        Starting from Java 1.2, the Java platform has a more flexible security mechanism, and its security strategy establishes the mapping relationship between code sources and access permission sets. The code source is specified by a code location and a certificate set. The code location specifies the source of the code. For example, the code location of the code in the JAR package is the URL of the file. The purpose of the certificate is to ensure that the code has not been tampered with by one party. Permission refers to any attribute that the security manager is responsible for checking. The Java platform supports many access permission classes, and each class encapsulates the detailed information of a specific permission. Each class has a protection domain, which is an object used to encapsulate the code source and permission collection of the class. When the SecurityManager class needs to check a certain permission, it needs to look at the class of all methods currently on the call stack, and then It needs to obtain the protection domains of all types, and asks each protection domain whether its permission set allows the execution of the operation currently being checked.

3. Security Policy File

        The policy manager needs to read the corresponding policy files. These files contain instructions for mapping code sources to permissions. The following is a policy file:

grant codebase http://www.horstmann.com/classes
{
    
    
	permission java.io.FilePermission “/tmp/*”, “read, write”;
}

(4) Digital signature

1. Message summary

        The message digest is the digital fingerprint of the data block. For example, SHA1 (Secure Hash Algorithm #1) can compress any data block, no matter how long its data is, into a 160-bit sequence. If one or more bits of the data are changed, the message digest will also change. And the forger who owns a given message cannot create a fake message with the same digest as the original message.

        The MessageDigest class is a factory for creating objects that encapsulate the fingerprint algorithm. Its static method getInstance returns an object of a class that inherits the MessageDigest class. The object for obtaining the SHA fingerprint is as follows:

MessageDigest alg = MessageDigest.getInstance(“SHA-1);

        After obtaining the MessageDigest object, you can repeatedly call the update method to provide all the bytes in the message to the object.

2. Message signature

        The message digest solves the problem of message authentication. When the message and the message digest are transmitted separately, the recipient can check whether the message has been tampered with, but if the message and the message digest are intercepted at the same time, then the message is modified, according to the public The message digest algorithm calculates the fingerprint, so the recipient will never know that the message has been tampered with. The message signature solves this problem.

        Public key encryption technology is based on the two concepts of public key and private key. Public keys can be published to the world, but private keys can only be held by themselves. It is almost impossible to calculate another key from one key, which means that even if everyone knows your public key, it is impossible to calculate your private key. Therefore, when A wants to send a message to B, A uses his private key to sign the message digest, and B knows A’s public key, and B uses A’s public key to verify the signature. If it passes the verification, Then B knows that the original message has not been tampered with and that the message was signed by A because it is the holder of the private key. But this also implies a risk. If A's private key is stolen, then A's identity will be replaced by someone else.

3. Verify the signature

        JDK is equipped with a keytool program, which is a command line tool used to generate and manage a set of certificates, as well as manage keystores, certificate databases, and private/public key pairs. Each item in the keystore has An alias, the following is that Alice creates a keystore alice.certs and uses the alias to generate a key pair:

keytool -genkeypair -keystore alice.certs -alias alice

        After creating the keystore, Alice can export the public key:

keytool -exportcert -keystore alice.certs -alias alice -file alice.cer

        When the recipient receives the public key and imports it into the keystore:

keytool -importcert -keystore bob.certs -alias alice -file alice.cer

        Alice can send the signed document to accept it. The jarsigner tool is responsible for signing and verifying the JAR file. Alice only needs to add the document to the JAR file to be signed:

jar cvf document.jar document.txt

        Then use the jarsigner tool to add the signature to the file, specify the keystore to be used, the JAR file and the alias of the key:

jarsigner -keystore alice.certs document.jar alice

        When the receiver receives the JAR file, use jarsigner's -verify option to verify the file:

jarsigner -verify -keystore bob.certs document.jar

4. Certification issues

        What we have solved before is the verification problem of the message, that is, we can determine whether the message is the original message, but the authentication of the identity of the sender has not been solved. Only when we trust the identity of the sender can we authenticate his message. In fact, it is a trust issue. If we only trust the message sent by A, as long as the stranger sends the public key to A, A will sign with the private key on the basis of the public key. We hold A's public key, and we only need to use A's public key to verify the message sent by A to confirm that A has verified the identity of the stranger.

        However, under normal circumstances, there will be no such acquaintance identity. It is generally a chain of trust, and we can trust any person in the chain; or an organization that everyone trusts to provide authentication services. We often encounter digital signatures signed by one or more entities responsible for guaranteeing the identities of others, but we need to assess the extent to which we can trust these institutions.


5. Certificate signing

        Information transmission on the Internet is very frequent. It is impossible for us to verify every piece of information, which is too cumbersome. Therefore, it is best if there is an entity we trust to verify these signatures. For example, Cindy trusts the ACME software department, which is responsible for the operation of the certificate authority (CA). First, we create a keystore acme.Certs, generate a key pair and export the public key, and the public key is imported into a In the self-signed certificate:

keytool -genkeypair -keystore acme.certs -alias acmeroot
keytool -exportcert -keystore acme.certs -alias acmeroot -file acmeroot.cer

        If Alice wants to send a message to Cindy, he needs to sign his own certificate and submit it to ACME. ACME will be responsible for verifying Alice's identity and generate a signing certificate. Alice will give the certificate to Cindy or put it on the ACME company directory. , The file contains Alice’s public key and ACME’s statement, proving that the key really belongs to Alice. In this way, after Cindy imports the certificate into her key store, the key store verifies that the key is signed by the trusted root key already in the key store, and Cindy does not need to check the certificate. The fingerprint is verified. Once Cindy adds the root certificate and the certificates of the people who send him messages, he doesn't have to worry about the keystore.


(5) Encryption

1 Overview

        When the information is authenticated, the information itself is visible. Encryption technology can encrypt the information and can only be decrypted with a matching key. Authentication is sufficient for code signing, there is no need to hide the code, and for confidential messages, encryption is required.

2. Symmetric cryptography

        The Java cryptography extension includes a Cipher class, which is the super class of all encryption algorithms. Call the getInstance method to obtain a cryptographic object:

Ciphre cipher = Cipher.getInstance(aligorithmName);

        Algorithms usually include "DES", or "AES", etc. DES is a data encryption standard, and AES is an advanced encryption standard. Once a cryptographic object is obtained, it can be initialized by setting the mode and key.


3. Key generation

        In order to encrypt, we need to generate a key. Each password has a different format for the key. We need to ensure that the generation of the key is random. The following steps need to be followed:

(1) Obtain the KeyGenerator for the encryption algorithm;

(2) Use a random source to initialize the key generator;

(3) Call the generateKey method;

        Such as generating AES key:

KeyGenerator keygen = KeyGenerator,getInstance(“AES”);
var random = new SecureRandom();
keygen.init(random);
Key key = keygen.generateKey();

        If you want to generate a key, you must use a real random number. The regular random number generator in the Random class generates random numbers based on date and time. It is not random enough, because the computer clock can be accurate to 0.1 seconds and can store up to 864,000 per day. If the attacker knows the date when the key is released, he can generate all possible seeds for that day.

        The random numbers generated by the SecureRandom class are more secure, but a seed is still required to start generating a sequence of numbers at a random point. It can be obtained from a hardware device or a random keyboard.

        All known public key algorithms are much slower than symmetric key algorithms (AES or DES). It is not appropriate to use public key algorithms to encrypt a large amount of information. Public key algorithms can be used to encrypt a small amount of key data. Use a symmetric key algorithm to encrypt a large amount of general data.

Guess you like

Origin blog.csdn.net/Mrwxxxx/article/details/113776521