OpenSSL and the keytool
Let me start with two important tools
- OpenSSL: The OpenSSL software package can be divided into three main functional parts: SSL library libssl, application command tools, and password algorithm library libcrypto. It uses standard file formats (PEM/CER/CRT/PKCS, etc.) to store key and certificate information.
- Keytool: a key and certificate management tool. It comes from the Java architecture and uses the KeyStore to manage keys and certificates.
Both are tools that can be used to generate encryption keys. Keytool comes from the Java architecture and can operate directly on the KeyStore, whereas OpenSSL does not support direct operation on the KeyStore. This might be the case where a key or certificate is generated using OpenSSL and then imported into the KeyStore using keytool for use in the Java environment.
Of course, OpenSSL has other functions such as acting as a client and server for SSL, which Keytool does not have.
Symmetric encryption
In the encryption method of single-key cryptosystem, the same key can be used to encrypt and decrypt information at the same time. This encryption method is called symmetric encryption, also called single-key encryption. — Baidu Encyclopedia
Characteristics of symmetric encryption algorithm
- Encryption and decryption use the same key
- Fast computing speed, suitable for large amount of data encryption processing
- Security depends on the algorithm, but also on the management of the key, once the key is compromised, the data is exposed
Usage scenarios of symmetric encryption algorithms
Based on the above characteristics, symmetric encryption can be used in some encrypted communication scenarios that require efficient real-time transmission, such as VPN or proxy communication. Another within the same system different modules, such as the front end, input of sensitive information from the front, can use symmetric encryption algorithm to the backend will be encrypted cryptograph, avoid expressly intercepted in the process of transmission, as with internal system key management relatively easy, for the Shared secret have leakage risk of any other scenarios, Symmetric encryption algorithms are not suitable for encryption.
Common symmetric encryption algorithms
algorithm | describe |
---|---|
Data Encryption Standard (DES) | Data encryption standard, fast, suitable for encrypting large amounts of data |
3DES (Triple DES) | Based on DES, a piece of data is encrypted three times with three different keys, with higher intensity |
Advanced Encryption Standard (AES) | Advanced encryption standard: supports encryption of 128, 192, 256, and 512 bits |
Blowfish | It’s fast and safe, and there are no patents or commercial restrictions.Learn more >> |
OpenSSL implements symmetric encryption
OpenSSL> enc --helpusage: enc -ciphername [-AadePp] [-base64] [-bufsize number] [-debug] [-in file] [-iv IV] [-K key] [-k password] [-kfile file] [-md digest] [-none] [-nopad] [-nosalt] [-out file] [-pass arg] [-S salt] [-salt] -A Process base64 data on one line (requires -a) -a Perform base64 encoding/decoding (alias -base64) -bufsize size Specify the buffer size to use for I/O -d Decrypt the input data -debug Print debugging information -e Encrypt the input data (default) -in file Input file to read from (default stdin) -iv IV IV to use, specified as a hexadecimal string -K key Key to use, specified as a hexadecimal string -md digest Digest to use to create a key from the passphrase -none Use NULL cipher (no encryption or decryption) -nopad Disable standard block padding -out file Output file to write to (default stdout) -P Print out the salt, key and IV used, then exit (no encryption or decryption is performed) -p Print out the salt, key and IV used -pass source Password source -S salt Salt to use, specified as a hexadecimal string -salt Use a salt in the key derivation routines (default) -v VerboseCopy the code
Command options | describe |
---|---|
-in file | Full path of the encrypted file |
-out file | The path to the encrypted output file |
-salt | Automatically insert a random number as the file content encryption, default option |
-e | Encryption mode, default |
-d | The decryption mode must be consistent with the encryption algorithm |
-a | Use the -base64-bit encoding format, or -base64 |
-pass source | The password can be entered using command line input (stdin), file input (file), environment variable input (var), file descriptor input (FD), and standard input (stdin). The default is standard input from the keyboard |
Only base64 encodes files without using encryption and decryption
TXT -out base64. TXT /* Decrypt files in base64 format */ openssl enc-base64-in plain. TXT -out base64. TXT TXT /* diff plain. TXT plain2.txt /* diff plain. TXT plain2.txtCopy the code
Different password input modes
Openssl enc-aes-128 -cbc -in plain. TXT -out out. TXT -pass pass:123456 /* TXT openssl enc-AES-128 -cbc -in plain. TXT -out out. TXT -pass file:passwd. TXT /* Enter environment variables. TXT -out. TXT -pass env:passwd /* Enter */ from the file description TXT -pass fd:1 /* Enter */ openssl enc-AES-128 -cbc-in plain. TXT -out out.txt -pass stdinCopy the code
Java implements symmetric encryption
DES
/** * Generate the DES algorithm key *@return byte[]
* @throws Exception
*/
public static byte[] generateDESKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
// must be equal to 56
keyGenerator.init(56);
SecretKey secretKey = keyGenerator.generateKey();
byte[] encodedKey = secretKey.getEncoded();
return encodedKey;
}
/** * DES encryption *@paramEncodedKey generateDESKey Generated key *@paramDataBytes byte[] data to be encrypted *@return byte[]
* @throws Exception
*/
public static byte[] encryptByDES(byte[] encodedKey, byte[] dataBytes) throws Exception {
SecretKey secretKey = new SecretKeySpec(encodedKey, "DES");
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedData = cipher.doFinal(dataBytes);
return encryptedData;
}
/** * DES decryption *@paramEncodedKey generateDESKey Generated key *@paramEncryptedData byte data to be decrypted in the form of [] *@return byte[]
* @throws Exception
*/
public static byte[] decryptByDES(byte[] encodedKey, byte[] encryptedData) throws Exception {
SecretKey secretKey = new SecretKeySpec(encodedKey, "DES");
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptedData = cipher.doFinal(encryptedData);
return decryptedData;
}
Copy the code
The basic version can be used as follows:
@Test
public void testDES_1(a) throws Exception {
byte[] encodedKey = SecurityUtil.generateDESKey();
String data = "this is a good boy";
byte[] encryptedData = SecurityUtil.encryptByDES(encodedKey, data.getBytes());
byte[] decryptedData = SecurityUtil.decryptByDES(encodedKey, encryptedData);
Assert.assertEquals(data, new String(decryptedData));
}
Copy the code
If the encryptedData needs to be returned to the downstream system, Base64 will be used for processing. If the encryptedData needs to be returned to the downstream system, Base64 will be used for processing. I further encapsulate the interface on the basis of the above, making it more close to the daily use of the scenario.
Optimized version:
/** * Generate the DES algorithm key *@returnBase64 encoded string key *@throws Exception
*/
public static String generateDESKeyStr(a) throws Exception {
return Base64.encodeBase64String(generateDESKey());
}
/** * DES encryption *@paramKey Base64-encoded string key *@paramData String data to be encrypted *@returnBase64 encoded encrypted data *@throws Exception
*/
public static String encryptByDES(String key, String data) throws Exception {
byte[] encodedKey = Base64.decodeBase64(key);
byte[] dataBytes = data.getBytes();
byte[] encryptedData = encryptByDES(encodedKey, dataBytes);
return Base64.encodeBase64String(encryptedData);
}
/** * DES decryption *@paramKey Base64-encoded string key *@paramData String data to be decrypted *@returnRaw data *@throws Exception
*/
public static String decryptByDES(String key, String data) throws Exception {
byte[] encodedKey = Base64.decodeBase64(key);
byte[] dataBytes = Base64.decodeBase64(data);
byte[] decryptedData = decryptByDES(encodedKey, dataBytes);
return new String(decryptedData);
}
Copy the code
The optimized version can be used as follows:
@Test
public void testDES_2(a) throws Exception {
String key = SecurityUtil.generateDESKeyStr();
String data = "this is a good boy";
String encryptedData = SecurityUtil.encryptByDES(key, data);
String decryptedData = SecurityUtil.decryptByDES(key, encryptedData);
Assert.assertEquals(data, decryptedData);
}
Copy the code
Here to add, in the actual project development process, also really met many students to Base64 understanding is wrong, for the above processing and conversion process of students who have difficulty in understanding, you can poke here
3DES
/** * Generate 3DES algorithm key *@return byte[]
* @throws Exception
*/
public static byte[] generate3DESKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
// must be equal to 112 or 168
keyGenerator.init(168);
SecretKey secretKey = keyGenerator.generateKey();
byte[] encodedKey = secretKey.getEncoded();
return encodedKey;
}
/** * 3DES encryption *@paramEncodedKey generate3DESKey Generated key *@paramDataBytes byte[] data to be encrypted *@return byte[]
* @throws Exception
*/
public static byte[] encryptBy3DES(byte[] encodedKey, byte[] dataBytes) throws Exception {
SecretKey secretKey = new SecretKeySpec(encodedKey, "DESede");
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedData = cipher.doFinal(dataBytes);
return encryptedData;
}
/** * 3DES decryption *@paramEncodedKey generate3DESKey Generated key *@paramEncryptedData byte data to be decrypted in the form of [] *@return byte[]
* @throws Exception
*/
public static byte[] decryptBy3DES(byte[] encodedKey, byte[] encryptedData) throws Exception {
SecretKey secretKey = new SecretKeySpec(encodedKey, "DESede");
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptedData = cipher.doFinal(encryptedData);
return decryptedData;
}
Copy the code
The usage method is as follows:
@Test
public void test3DES(a) throws Exception {
byte[] encodedKey = SecurityUtil.generate3DESKey();
String data = "this is a good boy";
byte[] encryptedData = SecurityUtil.encryptBy3DES(encodedKey, data.getBytes());
byte[] decryptedData = SecurityUtil.decryptBy3DES(encodedKey, encryptedData);
Assert.assertEquals(data, new String(decryptedData));
}
Copy the code
AES
/** * Generate AES algorithm key *@return byte[]
* @throws Exception
*/
public static byte[] generateAESKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
// must be equal to 128, 192 or 256
// But when you use 192/256, you get:
// java.security.InvalidKeyException: Illegal key size or default parameters
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
byte[] encodedKey = secretKey.getEncoded();
return encodedKey;
}
/** * AES encryption *@paramEncodedKey generateAESKey Generated key *@paramDataBytes byte[] data to be encrypted *@return byte[]
* @throws Exception
*/
public static byte[] encryptByAES(byte[] encodedKey, byte[] dataBytes) throws Exception {
SecretKey secretKey = new SecretKeySpec(encodedKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedData = cipher.doFinal(dataBytes);
return encryptedData;
}
/** * AES secret *@paramEncodedKey generateAESSKey The generated key *@paramEncryptedData byte data to be decrypted in the form of [] *@return byte[]
* @throws Exception
*/
public static byte[] decryptByAES(byte[] encodedKey, byte[] encryptedData) throws Exception {
SecretKey secretKey = new SecretKeySpec(encodedKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptedData = cipher.doFinal(encryptedData);
return decryptedData;
}
Copy the code
The usage method is as follows:
@Test
public void testAES(a) throws Exception {
byte[] encodedKey = SecurityUtil.generateAESKey();
String data = "this is a good boy";
byte[] encryptedData = SecurityUtil.encryptByAES(encodedKey, data.getBytes());
byte[] decryptedData = SecurityUtil.decryptByAES(encodedKey, encryptedData);
Assert.assertEquals(data, new String(decryptedData));
}
Copy the code
Although the AES support 128, 192 or 256 key length, but when we use 192 or 256 – bit length of key, will receive this exception: Java. Security. InvalidKeyException: Illegal key size or default parameters
java.security.InvalidKeyException: Illegal key size or default parameters
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1026)
at javax.crypto.Cipher.implInit(Cipher.java:801)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1249)
at javax.crypto.Cipher.init(Cipher.java:1186)
at com.example.architecture.util.SecurityUtil.encryptByAES(SecurityUtil.java:161)
at com.example.architecture.util.SecurityUtilTest.testAES(SecurityUtilTest.java:97)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
Copy the code
Jar and us_export_policy. jar in JRE support 128-bit key encryption algorithms. However, when we use 192 or 256-bit key algorithms, they are not supported.
Solution: Go to the official download JCE unrestricted permission policy file.
JDK5 | JDK6 | JDK7 | JDK8
Jar and us_export_policy. jar, as well as readme.txt
- If JRE is installed, place the two JAR files in the %JRE_HOME%\lib\security directory to overwrite the original files.
- If you have JDK installed, also place the two JAR files in the %JDK_HOME%\jre\lib\security directory to overwrite the original files.
AES128 differs from AES256 in key length (128bits and 256bits respectively) and number of encryption rounds (10 and 14 rounds respectively). AES is the most secure symmetric encryption algorithm.
Asymmetric encryption
Asymmetric encryption algorithms require two keys: a publickey and a privatekey. The public key and private key are a pair. If the public key is used to encrypt data, only the corresponding private key can be used to decrypt data. Because encryption and decryption use two different keys, the algorithm is called asymmetric encryption. — Baidu Encyclopedia
Characteristics of asymmetric encryption algorithms
- Also known as public-key encryption, an algorithm requires two keys, one of which can be disclosed, and the corresponding private key cannot be deduced from the public key
- The algorithm complexity is higher than symmetric encryption algorithm, so the calculation is relatively slow
- The confidentiality of the key is good, because the public key can be made public, eliminating the need to exchange the key
Usage scenarios of asymmetric encryption algorithms
Because the security is good and the key can be made public without the risk of disclosure during exchange, non-key algorithms are widely used in fields such as SSH, HTTPS, e-certificate, digital signature, and encrypted communication.
Data encryption transmission
Packet signature verification
Common asymmetric encryption algorithms
In 1977, three mathematicians Rivest, Shamir, and Adleman devised an algorithm that could implement asymmetric encryption. The algorithm, called RSA after all three of them, is the most widely used “asymmetric encryption algorithm” ever since it was invented. Other scene algorithms include Elgamal, knapsack algorithm, Rabin, D-H, ECC (Elliptic curve encryption algorithm).
The principle of RSA algorithm is recommended for students who are interested in learning more about it.
Principle of RSA Algorithm (1)
Principle of RSA Algorithm (2)
OpenSSL implementation RSA
Before I begin, I need to add two points:
- If you are not sure about the encoding rules and data format for asymmetric keys, you can take a look at this article. Here are the highlights:
Openssl encodes keys in various forms. Openssl encodes keys in PEM and DER, and provides related instructions for users to convert keys between the two formats.
DER
DER is the binary representation of the key
PEM
The PEM format is transcoding the DER encoding to base64 character format. DER format can be restored through Base64 decoding.
PEM is in plain text format and can contain a certificate or key. It usually starts with something like “– BEGIN… — “start” — END… — “describes the format of the ending. Because DER is a pure binary format, it is not user-friendly, so it is generally stored in PEM.
- RSA asymmetric encryption and decryption algorithm Padding
There are three commonly used padding modes for RSA encryption: RSA_PKCS1_PADDING, RSA_PKCS1_OAEP_PADDING, and RSA_NO_PADDING.
Like the symmetric encryption algorithms DES and AES, RSA is a block cipher algorithm. It always operates on a block of a fixed length. But unlike AES, block length is related to key Length.
The plaintext length of each RSA encryption is limited by the RSA filling mode, but the block length of each RSA encryption is the key length.
Commonly used instructions
instruction | Functional description |
---|---|
genrsa | Generate an RSA private key |
rsa | Format conversion of an RSA key |
rsautl | Encryption, decryption, signature, and authentication |
Genrsa command
OpenSSL> genrsa --helpusage: genrsa [args] [numbits] -des encrypt the generated key with DES in cbc mode -des3 encrypt the generated key with DES in ede cbc mode (168 bit key) -aes128, -aes192, -aes256 encrypt PEM output with cbc aes -camellia128, -camellia192, -camellia256 encrypt PEM output with cbc camellia -out file output the key to 'file -passout arg output file pass phrase source -f4 use F4 (0x10001) for the E value -3 use 3 for the E valueCopy the code
Command options | describe |
---|---|
-des | The generated key is encrypted using DES |
-des3 | The generated key is encrypted using DES3 |
-aes128, -aes192, -aes256 | The generated key is encrypted in AES mode |
-camellia128, -camellia192, -camellia256 | The generated key is encrypted using camellia mode |
-out file | The generated key is written to the file |
-passout arg | Specifies the encryption password for the key file. It can be entered from a file, environment variable, or terminal |
Example:
// Generate a 2048 bit RSA private key openssl genrsa -out pkcs1_private.pem 2048Copy the code
Rsa command
usage: rsa [-ciphername] [-check] [-in file] [-inform fmt] [-modulus] [-noout] [-out file] [-outform fmt] [-passin src] [-passout src] [-pubin] [-pubout] [-sgckey] [-text] -check Check consistency of RSA private key -in file Input file (default stdin) -inform format Input format (DER, NET or PEM (default)) -modulus Print the RSA key modulus -noout Do not print encoded version of the key -out file Output file (default stdout) -outform format Output format (DER, NET or PEM (default PEM)) -passin src Input file passphrase source -passout src Output file passphrase source -pubin Expect a public key (default private key) -pubout Output a public key (default private key) -sgckey Use modified NET algorithm for IIS and SGC keys -text Print in plain text in addition to encodedCopy the code
Command options | describe |
---|---|
-in file | The input file |
-inform format | Input file format (DER, NET or PEM (default)) |
-modulus | Output modulus refers to |
-noout | Does not output the key anywhere |
-out file | Output key file |
-outform format | Output file format (DER, NET or PEM (default)) |
-passin src | Enter the encrypted password of the file, which can be from the file, terminal, environment variables, etc |
-passout src | The encrypted password of the output file can be from the file, terminal, environment variables, etc |
-pubin | Specifies that the input file is a public key |
-pubout | Specifies that the output file is a public key |
Example:
Pem public key openssl rsa -in pkcs1_private.pem -pubout -out pkcs1_public.pemCopy the code
In the Java environment, there are two issues that need to be addressed with the above commands, which we illustrate with two small examples.
Generate a private key in the/TMP directory:
// Generate the key in pem format openssl genrsa -out rsa.pemCopy the code
Try to read rsa.pem and generate a PrivateKey object
@Test
public void testGeneratePrivateKeyWithPEM(a) throws Exception {
byte[] bytes = Files.readAllBytes(Paths.get("/tmp/RSA.pem" ));
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
System.out.println(privateKey.getFormat());
}
Copy the code
Run after found that the abnormal transactions: Java security. Spec. InvalidKeySpecException: Java. Security. InvalidKeyException: invalid key format
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format
at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:217)
at java.security.KeyFactory.generatePrivate(KeyFactory.java:372)
at com.example.architecture.util.RSAUtilTest.testGeneratePrivateKeyWithPEM(RSAUtilTest.java:32)...Copy the code
Cause: The Java security package does not support reading files in PEM format.
Solution: Change the PEM format to DER format before reading data.
Openssl rsa-in rsa.pem -outform der -out rsa.der openssl rsa-in rsa.pem -outform der -out rsa.derCopy the code
Ok, go ahead and read rsa.der and try to generate the PrivateKey object
@Test
public void testGeneratePrivateKeyWithDER(a) throws Exception {
byte[] bytes = Files.readAllBytes(Paths.get("/tmp/RSA.der" ));
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
System.out.println(privateKey.getFormat());
}
Copy the code
Run after will quote another exception: Java. Security. Spec. InvalidKeySpecException: Java. Security. InvalidKeyException: IOException: algid parse error, not a sequence
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:217)
at java.security.KeyFactory.generatePrivate(KeyFactory.java:372)
at com.example.architecture.util.RSAUtilTest.testGeneratePrivateKeyWithDER(RSAUtilTest.java:24)...Copy the code
OpenSSL generates the private key in PKCS#1 format, while the Java security package uses PKCS8EncodedKeySpec to implement the private key. The private key information is defined in the PKCS#8 standard, as can be seen from the following constructor description of the class.
/**
* Creates a new PKCS8EncodedKeySpec with the given encoded key.
*
* @param encodedKey the key, which is assumed to be
* encoded according to the PKCS #8 standard. The contents of
* the array are copied to protect against subsequent modification.
* @exception NullPointerException if {@code encodedKey}
* is null.
*/
public PKCS8EncodedKeySpec(byte[] encodedKey) {
super(encodedKey);
}
Copy the code
Solution: OpenSSL generates the key for use in a Java environment before converting it to PKCS#8 format.
PKCS#1 and PKCS#8 are both standard definitions of asymmetrically encrypted private key information. The difference is that PKCS#1 is for RSA algorithm, while PKCS#8 is general. There are some differences in format definition between the two.
DER -outform DER -nocrypt -out rsa_pkcs8.der // Obtain the private key openssl pkcs8-topk8-inform in rsa. DER -outform DER -nocrypt -out rsa_pkcs8.derCopy the code
Continue reading rsa_PKCS8.der and try to generate the PrivateKey object
@Test
public void testGeneratePrivateKeyWithPKCS8DER(a) throws Exception {
byte[] bytes = Files.readAllBytes(Paths.get("/tmp/RSA_pkcs8.der" ));
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); System.out.println(privateKey.getFormat()); } output: PKCS#8
Copy the code
Done!
Rsautl command
OpenSSL> rsautl --helpUsage: rsautl [options] -in file input file -out file output file -inkey file input key -keyform arg private key format - default PEM -pubin input is an RSA public -certin input is a certificate carrying an RSA public key -ssl use SSL v2 Padding-raw Use No PADDing-PKCS use PKCS#1 V1.5 PADDing-(default) -oaep Use PKCS#1 oaep -sign sign with private key -verify verify with public key -encrypt encrypt with public key -decrypt decrypt with private key -hexdump hex dump outputCopy the code
Command options | describe |
---|---|
-in file | The input file |
-out file | The output file |
-inkey file | The key file |
-keyform arg | Private key format. The default value is PEM |
-pubin | Enter the RSA public key |
-certin | Enter the certificate file carrying the RSA public key |
-ssl | Use the SSLv2 filling method |
-raw | Not filling |
-pkcs | Use PKCS#1 v1.5 filling method, the default filling method |
-oaep | Use PKCS#1 OAEP filling method |
-sign | Use the private key to sign |
-verify | Use the public key to verify the signature |
-encrypt | Using public Key Encryption |
-decrypt | Decrypt using a private key |
-hexdump | Output in hexadecimal dump |
##### Encryption and decryption example: | |
“`shell | |
// Generate an RSA key | |
openssl genrsa -out RSA.pem | |
// Retrieve the public key | |
openssl rsa -in RSA.pem -pubout -out pub.pem |
// Use the RSA public key to encrypt, enter the private key, actually use the corresponding public key to encrypt, TXT -inkey rsa.pem -out encrypted. TXT Openssl rsautl – encrypt-in plain.txt -inkey pub.pem -pubin -out encrypted.txt
// Use the RSA private key to decrypt openssl rautl-decrypt-in encrypted. TXT -inkey rsa.pem -out plain2.txt
##### Sample for verification: Pem // Extract the public key openssl RSA -in rsa. pem -pubout pub.pem // Use the private key to sign TXT -inkey rsa. pem -out sign. TXT // Use the public key to verify openssl rautl -verify -in sign. TXT -pubin -inkey pub.pem -out plain2.txtCopy the code
Encryption, decryption, signature, check, complete code examples:
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class RSAUtil {
/** * RSA algorithm **/
private static final String ALGORITHM_RSA = "RSA";
/** * signature algorithm **/
private static final String ALGORITHM_SIGNATURE = "SHA1WithRSA";
/** * Cipher class provides encryption and decryption functions * * Cipher Cipher = cipher.getInstance ("RSA/ECB/PKCS1PADDING"); * RSA is the algorithm, ECB is the block mode, PKCS1Padding is the fill mode, the whole form a complete encryption algorithm * *
* has the following parameters: * * AES/CBC/NoPadding (128) * * AES/CBC/PKCS5Padding (128) * * AES/ECB/NoPadding (128) * * AES/ECB/PKCS5Padding (128) * * DES/CBC/NoPadding (56) * * DES/CBC/PKCS5Padding (56) * * DES/ECB/NoPadding (56) * * DES/ECB/PKCS5Padding (56) * * DESede/CBC/NoPadding (168) * * DESede/CBC/PKCS5Padding (168) * * DESede/ECB/NoPadding (168) * * DESede/ECB/PKCS5Padding (168) * * RSA/ECB/PKCS1Padding (1024, 2048) * * RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048) * * RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048) *
*/
private static final String PADDING = "RSA/ECB/PKCS1PADDING";
/** * Generates an asymmetric key pair, using RSA ** by default@return
* @throws Exception
*/
public static String[] generateRSAKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM_RSA);
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
String publicKeyStr = Base64.encodeBase64String(publicKey.getEncoded());
String privateKeyStr = Base64.encodeBase64String(privateKey.getEncoded());
return new String[]{publicKeyStr, privateKeyStr};
}
/** * Use the public key of the data receiver to encrypt **@paramPublicKeyStr Public key * in BASE64 encoding@paramData Indicates the data to be encrypted@return
* @throws Exception
*/
public static String encryptByPublicKeyStr(String publicKeyStr, String data) throws Exception {
PublicKey publicKey = getPublicKeyFromString(publicKeyStr);
byte[] bytes = doCipher(Cipher.ENCRYPT_MODE, publicKey, data.getBytes());
return Base64.encodeBase64String(bytes);
}
/** * The data receiver decrypts ** using its own private key@paramPrivateKeyStr BASE64 - encoded private key *@paramEncryptedData Data to be decrypted@return
* @throws Exception
*/
public static String decryptByPrivateKeyStr(String privateKeyStr, String encryptedData) throws Exception {
PrivateKey privateKey = getPrivateKeyFromString(privateKeyStr);
byte[] bytes = doCipher(Cipher.DECRYPT_MODE, privateKey, Base64.decodeBase64(encryptedData));
return new String(bytes);
}
/** * Use the public key of the data receiver to encrypt **@paramPublicKeyPath Public key file path *@paramData Indicates the data to be encrypted@return
* @throws Exception
*/
public static String encryptByPublicKeyFile(String publicKeyPath, String data) throws Exception {
PublicKey publicKey = getPublicKeyFromFile(publicKeyPath);
byte[] bytes = doCipher(Cipher.ENCRYPT_MODE, publicKey, data.getBytes());
return Base64.encodeBase64String(bytes);
}
/** * The data receiver decrypts ** using its own private key@paramPrivateKeyPath Private key file path *@paramEncryptedData Data to be decrypted@return
* @throws Exception
*/
public static String decryptByPrivateKeyFile(String privateKeyPath, String encryptedData) throws Exception {
PrivateKey privateKey = getPrivateKeyFromFile(privateKeyPath);
byte[] bytes = doCipher(Cipher.DECRYPT_MODE, privateKey, Base64.decodeBase64(encryptedData));
return new String(bytes);
}
/** * The data sender signs the data with its own private key **@paramPrivateKeyStr BASE64 - encoded private key *@paramData Data to be signed *@returnSignature data, usually BASE64 encoded and sent to each other *@throws Exception
*/
public static String signByPrivateKeyStr(String privateKeyStr, String data) throws Exception {
PrivateKey privateKey = getPrivateKeyFromString(privateKeyStr);
byte[] bytes = sign(privateKey, data.getBytes());
return Base64.encodeBase64String(bytes);
}
/** * The data receiver verifies the signature with the other party's public key **@paramPublicKeyStr BASE64 encoded private key *@paramData Data to be checked *@paramSign Signature data, BASE64 decoding to verify the signature *@return
* @throws Exception
*/
public static boolean verifyByPublicKeyStr(String publicKeyStr, String data, String sign) throws Exception {
PublicKey publicKey = getPublicKeyFromString(publicKeyStr);
return verify(publicKey, data.getBytes(), Base64.decodeBase64(sign));
}
private static PublicKey getPublicKeyFromString(String publicKeyStr) throws Exception {
byte[] encodedKey = Base64.decodeBase64(publicKeyStr);
return generatePublic(encodedKey);
}
private static PublicKey getPublicKeyFromFile(String publicKeyPath) throws Exception {
byte[] encodedKey = Files.readAllBytes(Paths.get(publicKeyPath));
return generatePublic(encodedKey);
}
private static PublicKey generatePublic(byte[] encodedKey) throws Exception {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
private static PrivateKey getPrivateKeyFromString(String privateKeyStr) throws Exception {
byte[] encodedKey = Base64.decodeBase64(privateKeyStr);
return generatePrivate(encodedKey);
}
private static PrivateKey getPrivateKeyFromFile(String privateKeyPath) throws Exception {
byte[] encodedKey = Files.readAllBytes(Paths.get(privateKeyPath));
return generatePrivate(encodedKey);
}
private static PrivateKey generatePrivate(byte[] encodedKey) throws Exception {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
private static byte[] doCipher(int mode, Key key, byte[] bytes) throws Exception {
Cipher cipher = Cipher.getInstance(PADDING);
cipher.init(mode, key);
return cipher.doFinal(bytes);
}
private static byte[] sign(PrivateKey privateKey, byte[] data) throws Exception {
Signature signature = Signature.getInstance(ALGORITHM_SIGNATURE);
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
private static boolean verify(PublicKey publicKey, byte[] data, byte[] sign) throws Exception {
Signature signature = Signature.getInstance(ALGORITHM_SIGNATURE);
signature.initVerify(publicKey);
signature.update(data);
returnsignature.verify(sign); }}Copy the code
Sample code to test:
@Test
public void test_generateRSAKeyPair(a) throws Exception {
String data = "password:123456";
String[] keyPair = RSAUtil.generateRSAKeyPair();
String publicKeyStr = keyPair[0];
String privateKeyStr = keyPair[1];
String encryptedData = RSAUtil.encryptByPublicKeyStr(publicKeyStr, data);
String decryptedData = RSAUtil.decryptByPrivateKeyStr(privateKeyStr, encryptedData);
Assert.assertEquals(data, decryptedData);
}
Pem ** openssl rsa -in private.pem -outform der -out private.der * openssl pkcs8 -topk8 -inform DER -in private.der -outform DER -nocrypt -out private_pkcs8.der * * openssl rsa -in private.pem -pubout -out public.pem * openssl rsa -pubin -in public.pem -outform der -out public.der */
@Test
public void test_openssl(a) throws Exception {
String data = "password:123456";
String encryptedData = RSAUtil.encryptByPublicKeyFile("/tmp/public.der", data);
String decryptedData = RSAUtil.decryptByPrivateKeyFile("/tmp/private_pkcs8.der", encryptedData);
Assert.assertEquals(data, decryptedData);
}
@Test
public void test_signature(a) throws Exception {
String data = "balance=1000000";
String[] keyPair = RSAUtil.generateRSAKeyPair();
String publicKeyStr = keyPair[0];
String privateKeyStr = keyPair[1];
String sign = RSAUtil.signByPrivateKeyStr(privateKeyStr, data);
boolean pass = RSAUtil.verifyByPublicKeyStr(publicKeyStr, data, sign);
Assert.assertTrue(pass);
}
Copy the code
Certificate and the keytool
Above, we use openSSL tool to generate RSA asymmetric key pair, store the key in string or standard file format and process encryption and decryption. In actual Java project development, keystore is often used to manage the key. For this, we can use keytool to generate the key. Or import the key in another file format into the keystore.
Before introducing keytool, let’s explain a few concepts to help you understand how to use keytool.
certificate
Let’s start with A small scene where A tells B A secret:
The above process has no problem under normal circumstances, which can ensure data encryption and transmission. Even if intercepted by a third party, it cannot be decrypted without B’s private key. However, in a complex network environment, the situation may look like this:The above process is A typical man-in-the-middle attack scenario. There is an extra man-in-the-middle X in the communication link between A and B, but AB has no sense at all. After step 4 of the above process, A has the public key of X, and X has the public key of B. In fact, A needs the public key of B, but A does not know it, and thinks that it has the public key of B, so A still uses the public key to encrypt and send data normally. In this way, the communication information between A and B is completely accessed by X and can be tampered with at will.
In the actual network environment, we cannot prevent the existence of X, so how to solve the above man-in-the-middle attack problem? Through the analysis of the above process, it is not difficult to find that A wants to obtain THE public key of B, but actually receives the public key of X. However, it cannot identify that the public key is not B’s, and the certificate can help us solve this key problem.
CER- A digital certificate
Digital certificates are digital credentials that provide information about the identity of the entity as well as other supporting information. Digital certificates are issued by the Certificate Authority (CA), which guarantees the validity of Certificate information. Digital certificates contain the public key of the entity identified in the certificate, and because the certificate matches the public key to the applicant and the authenticity of the certificate is guaranteed by the issuing authority, digital certificates provide a solution to the problem of how to find the user’s public key and know if it is valid.
There are three common certificates:
- Certificate with private key: As defined by PublicKey Cryptography Standards #12, PKCS#12 is a certificate that contains a public and private key in binary format. PFX is used as the extension name of the certificate file. PKCS#12 can add encryption protection to facilitate the transfer of the certificate and the corresponding private key.
- Binary certificate: defined by the X.509 public key certificate format standard, a certificate does not contain a private key, but contains a public key in binary DER encoding format and uses cer as the extension name of the certificate file.
- A base64-encoded certificate is defined by the X.509 public key certificate format. A certificate does not contain a private key but contains a base64-encoded public key and uses cer as the suffix of the certificate file.
Keystore keystore
A keystore is a file that stores one or more key entries, each identified by an alias, that contain key and certificate-related information.
In Java, each type of Entry in a keystore implements the Keystore.entry interface. There are three basic implementations:
- KeyStore.PrivateKeyEntry
This type of entry holds an encrypted PrivateKey, which you can optionally store in a protected format to prevent unauthorized access. It also comes with a chain of certificates for the corresponding public key. 2. Keystore. SecretKeyEntry This type of entry holds an encrypted SecretKey that can optionally be stored in a protected format to prevent unauthorized access. 3. The KeyStore. TrustedCertificateEntry this type of entry contains a belongs to the other side of the single public key Certificate (Certificate). It is called a trusted certificate because the owner of the keystore believes that the public key in the certificate really belongs to the identity identified by the certificate.
Keystore Keystore file format
format | extension | describe | The characteristics of |
---|---|---|---|
JKS | .jks/.ks | The Java implementation version of the key store, and the provider is SUN | Keystore and private key are protected by different passwords |
JCEKS | .jce | JCE implementation version of the key store, and the provider is SUN JCE | Compared with JKS, 3DES is used to protect the Keystore private key |
PKCS12 | .p12/.pfx | Syntax standard for personal information exchange | Contains the private key, public key, and certificate. The key store and private key are protected by the same password |
BKS | .bks | The BC implementation version of the keystore, and the provider is BC | Based on JCE implementation |
##### Certificate Format of the Certificate file | |||
format | extension | describe | The characteristics of |
— | — | — | — |
DER | .cer/.crt/.rsa | Used to store certificates | No private key, binary format |
PKCS7 | .p7b/.p7r | PKCS#7 syntax standard for encrypted messages | P7b displays the certificate chain in tree form and does not contain the private key. P7r is the reply signed by the CA to the certificate request and can only be used for import |
CMS | .p7c/.p7m/.p7s | Cryptographic Message Syntax | P7c Saves only the certificate. P7m: signature with enveloped data; P7s: timestamp signature file |
PEM | .pem | Printable Base64 encoded information | The encoding format is defined in RFC1421. PEM is short for Privacy Enhanced Mail, but it is also widely used in key management ASCII files. It is generally Base64 encoding |
PKCS10 | .p10/.csr | PKCS #10 Public key Encryption Standard | Certificate signature request file, CA signs and replies with p7R file |
truststore
In addition, we sometimes see the TrustStore. From the perspective of its file format, it is actually the same thing as keystore, but it is separated for convenient management. Keystore generally stores private keys for encryption and decryption or signature, while TrustStore stores some trusted certificates. This is primarily done when Java is called in HTTPS mode in code to ensure that the visitor is trusted.
keytool
Next we use the keytool tool to generate the keys and certificates.
The keytool command
Keytool Key and certificate management tool commands: -certreq Generates a certificate request -ChangeAlias Changes the alias of an entry -delete Deletes an entry -exportcert Exports a certificate -genkeypair generates a keypair -gensecKey generates a key -gencert Generates a certificate based on a certificate request -importCert Imports a certificate or certificate chain -importPass imports a password -importKeystore imports one or all entries from other key stores -keypasswd Changes the key password of the entry -list lists the entries in the keystore -printcert -printCertreq Prints the content of the certificate request. -printcrl Prints the content of the CRL file. -storepasswd Changes the storage password of the key storeCopy the code
Keytool – genkeypair command
keytool -genkeypair -help keytool -genkeypair [OPTION]... Key pair generation options: -alias <alias> Alias of the item to be processed -keyalg <keyalg> Name of the key algorithm -keysize <keysize> size of the key bit -sigalg <sigalg> Name of the signature algorithm -destAlias < destAlias > Target alias -dname <dname> unique discriminant name -startdate <startdate> certificate validity startdate/time -ext <value> x. 509 extension -validity <valDays> validity days -keypass <arg> key password -keystore <keystore> keystore name -storepass <arg> keystore password -storetype <storetype> keystore type -providername <providername> Providerclass < ProviderClass > ProviderClass name -providerarg <arg> ProviderPath < pathList > Providerclasspath -v verbose output -protected Password through a protected mechanismCopy the code
We use this command to generate a pair of asymmetric keys and wrap the public key in the X.509 V3 self-signed certificate with the key entry alias and keystore file name as Java-and-more and keystore type as PKCS12, and enter the corresponding contents as prompted:
Keytool -genkeypair -alias Java -and-more -keyalg RSA -keystore/TMP/Java -and -more-. keystore -storetype pkcs12 enter the keystore password. Enter the new password again: what is your first and last name? What is the name of your organization? What is the name of your organization? What is the name of your city or region? Sz What is the name of your province/city/autonomous region? [Unknown]: sZ What is the two-letter country/area code of the unit? Unknown: China CN= javaAndMore, OU= JavaAndMore, O= JavaAndMore, L=sz, ST=sz, C=China [no] : YCopy the code
Note that PKCS12 does not support setting a keystore entry password. By default, it is the same as the keystore password. If you create a keystore of default type (JKS), you can specify the key entry password using the -keypass parameter.
The keytool -list command displays the contents of the key store.
Keytool -list -v -keystore/TMP/Java -and-more.keystore Enter the keystore password: keystore type: JKS Keystore provider: SUN Your keystore contains one entry alias: Java-and-more Creation Date: 2020-10-8 Entry Type: PrivateKeyEntry Certificate chain Length: 1 Certificate [1]: Owner: CN= javaAndMore, OU= JavaAndMore, O= JavaAndMore, L=sz, ST=sz, C=China CN= JavaAndMore, OU= JavaAndMore, O= JavaAndMore, L= SZ, ST= sZ, C=China Serial number: 80E7F12 Validity Start Date: Thu Oct 08 22:11:59 CST 2020, deadline: Wed Jan 06 22:11:59 CST 2021 Certificate Fingerprint: MD5: 21:C6:CE:BE:D8:38:42:F6:FF:EF:78:D4:E3:AF:B3:57 SHA1: E2:DF:6A:8B:86:CC:65:D4:19:C7:22:B5:06:FC:58:F2:75:FE:8A:D2 SHA256: A1: ": B7: and these F: 77:50:0 E: BE: F4: D4: first: the 2 D: B3:94-88 - D: conquered gaza but A: 5: all DE: 07:33:3 B: 39: A1: B0:40 signature algorithm name: SHA256withRSA Version: 3 Extensions:
#1: ObjectId: 2.5.29.14 Criticality =false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 70 76 4E 22 F6 6B 57 68 B5 F6 92 93 26 D4 A8 80 pvN".kWh....&...
0010: 52 88 1E 74 R..t
]
]
*******************************************
*******************************************
Copy the code
The keytool -exportcert command exports the keystore entry certificate
Keytool -exportcert -keystore/TMP/Java -and-more.keystore -alias Java -and-more -file/TMP/Java -and-more. CRT Enter the password of the keystore. Certificate stored in file </ TMP/Java -and-more.crt>Copy the code
The keytool -printcert command prints the certificate content
Keytool -printcert -v -file/TMP/Java -and-more. CRT CN= javaAndMore, OU= JavaAndMore, O= JavaAndMore, L=sz, ST=sz, C=China CN= JavaAndMore, OU= JavaAndMore, O= JavaAndMore, L= SZ, ST= sZ, C=China Serial number: 80E7F12 Validity Start Date: Thu Oct 08 22:11:59 CST 2020, deadline: Wed Jan 06 22:11:59 CST 2021 Certificate Fingerprint: MD5: 21:C6:CE:BE:D8:38:42:F6:FF:EF:78:D4:E3:AF:B3:57 SHA1: E2:DF:6A:8B:86:CC:65:D4:19:C7:22:B5:06:FC:58:F2:75:FE:8A:D2 SHA256: A1: ": B7: and these F: 77:50:0 E: BE: F4: D4: first: the 2 D: B3:94-88 - D: conquered gaza but A: 5: all DE: 07:33:3 B: 39: A1: B0:40 signature algorithm name: SHA256withRSA Version: 3 Extensions:
#1: ObjectId: 2.5.29.14 Criticality =false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 70 76 4E 22 F6 6B 57 68 B5 F6 92 93 26 D4 A8 80 pvN".kWh....&...
0010: 52 88 1E 74 R..t
]
]
Copy the code
The certificate and key exported from the keystore file are in DER format and can be converted to PEM format using the OpenSSL tool
openssl x509 -inform der -in /tmp/java-and-more.crt -out /tmp/java-and-more.pem
Copy the code
The public key information is exported from the certificate
openssl x509 -in /tmp/java-and-more.pem -pubkey -out public-key.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtkPH2M8uL4T0Lu4g2qYt
zclIkMhNHkfkL5rOqaZKSwYYwgG/NH9V4+Byf2Of5/1GfXQU8dFKwfXSm7rlL4/Y
jKj5uy2xKBq2H2d2m7XoNqWzPOc8swkFraGEhxf4swbU6O/sRIxJJuelruPUh51o
SN3LeLRQBDxkX2irEGICQZGcFshckBvH13PJtHKf0ZnXw3FzFde7IswiVrrwiEXP
ttLQm0hM/xh3/Pcav7u0ademaVppSc8zC6sTxIxwyeyl2J8FXytdUakxixDqm/du
nNBTfO7+dSNGLJ+ATztluhfZcIeE2+t66Ya/6PKK6DSBxZwXnErKcuLvLVPnMX+d
5wIDAQAB
-----END PUBLIC KEY-----
Copy the code
Note: You cannot export the private key information directly from the keystore using a command. The following example uses Java to extract the private and public keys from the PKCS12 certificate
@Test
public void test_keystore(a) throws Exception {
String keyStoreFile = "/tmp/java-and-more.keystore";
char[] password = "123456".toCharArray();
KeyStore keyStore = KeyStore.getInstance("pkcs12");
keyStore.load(Files.newInputStream(Paths.get(keyStoreFile)), password);
Enumeration<String> aliases = keyStore.aliases();
while(aliases.hasMoreElements()) { String alias = aliases.nextElement(); System.out.println(alias); X509CertImpl certImpl = (X509CertImpl) keyStore.getCertificate(alias); PublicKey publicKey = certImpl.getPublicKey(); System.out.println(Base64.encodeBase64String(publicKey.getEncoded())); RSAPrivateCrtKeyImpl keyImpl = (RSAPrivateCrtKeyImpl) keyStore.getKey(alias, password); System.out.println(Base64.encodeBase64String(keyImpl.getEncoded())); }}Copy the code
Issue and import certificates
This process involves three commands:
- keytool -certreq
- keytool -gencert
- keytool -importcert
The three steps are as follows:
- Organization A uses the certreq command to generate A certificate sign Request (CSR) file and sends it to Organization B
- After receiving this request, agency B issues the certificate using the gencert command, which generates a certificate or certificate chain
- After receiving the response, agency A imports the issued certificate into the keystore using the importcert command
The following uses the certificate signed by Alice.keystore as an example to demonstrate the above process:
Sir Into two keystore files
keytool -genkeypair -alias Alice -keyalg RSA -keystore /tmp/Alice.keystore -storetype pkcs12
keytool -genkeypair -alias Bob -keyalg RSA -keystore /tmp/Bob.keystore -storetype pkcs12
Copy the code
Generate a certificate signing request file CSR, that is, export the public key and some personal information alias Alice from the alice.keystore file as the certificate request file
keytool -certreq -alias Alice -keystore /tmp/Alice.keystore -file /tmp/cert.csr
Copy the code
Issue the certificate for cert. CSR using the private key alias Bob entry in the keystore Bob. Keystore and save it to the bob-to-alice.crt file
keytool -gencert -infile /tmp/cert.csr -outfile /tmp/Bob-to-Alice.crt -alias Bob -keystore /tmp/Bob.keystore
Copy the code
Import the issued certificate to the keystore, and update the issued certificate Bob-to-Alice. CRT to the alice. keystore file that already has the alias Alice
Keytool -importcert -file/TMP /Bob-to alice. CRT -alias Alice -keystore/TMP/alice. keystore enter the password of the keystore. Java.lang. Exception: Cannot create chain from replyCopy the code
This is because the trust certificate of the issuing authority must be imported into the keystore file before updating the issued certificate, that is, the certificate of the keystore Bob. Keystore must be imported into the keystore Alice.keystore with its corresponding alias.
Export the trust certificate of Bob. Keystore:
keytool -exportcert -keystore /tmp/Bob.keystore -alias Bob -file /tmp/Bob.crt
Copy the code
Import the trust certificate Bob. CRT into the keystore with its alias Bob
keytool -importcert -file /tmp/Bob.crt -alias Bob -keystore /tmp/Alice.keystore
Copy the code
Import the certificate Bob-to-Alice. CRT alias Alice into the keystore alice. keystore:
Keytool -importcert -file/TMP /Bob-to alice. CRT -alias Alice -keystore/TMP/alice. keystore Enter the keystore password: Certificate reply has been installed in the keystoreCopy the code
By comparing the certificate information of alice. keystore generated at the beginning, it can be found that the certificate chain alias as Alice entry has changed from a single self-signed certificate of Alice.keystore to two self-signed certificates of Bob.keystore and Alice.keystore.
So far, we have basically introduced symmetric encryption and asymmetric encryption from many aspects such as principle, scene, tools and code.
The hash function
Next we supplement an algorithm that is also widely used in daily development: information summary algorithm, also known as hash function, hash function. Different from the above two algorithms, the information summary algorithm is not a encryption algorithm, it has the following characteristics but makes it very suitable in some scenarios:
- A fixed input produces a fixed output, and the probability of different inputs producing the same output is extremely low
- It is theoretically impossible to deduce the original plaintext backward from the hashed value
- Whatever the length of the input data, the length of the output value is fixed (different hashing algorithms have different lengths).
Imagine this scenario, we want to save the user password in the database, first of all can not save plain text, since we want to use ciphertext save, that use symmetric encryption or asymmetric encryption? Combined with the actual scenario and security considerations, both are not appropriate! Because both of these require key management, if the key is leaked, the password is at risk of being cracked. In this scenario, we can use a one-way hash function to solve this problem, so that even if both the algorithm and ciphertext leak, the plaintext cannot be calculated backwards.
Of course, hash functions have more uses, such as file consistency checks, digital signatures, and so on.
Common hash algorithms are: MD5, SHA1, and sha2(sha224, SHA256, SHA384, and SHA512). The encrypted length of SHA1 is 160 bytes. The encrypted length of SHA2 is the same as the encrypted length of shaxxx.
A more detailed introduction to hash algorithms can be found in this article, the three most commonly used hash algorithms.
Openssl DGST command
openssl dgst [-md5|-md4|-md2|-sha1|-sha|-mdc2|-ripemd160|-dss1] [-c] [-d] [-hex] [-binary] [-out filename] [-sign Filename] [-keyform arg] [-passin arg] [-verify filename] [-prverify filename] [-signature filename] [-hMAC key] [file...] Md5 | - md4 | - md2 | - sha1 | - sha | - mdc2 | - ripemd160 digest | - dss1: the name of the hash algorithm, the default value is the md5. -c: Print hashing results separated by colons. -d: displays detailed debugging information. -hex: displays the result in hexadecimal format. This is the default format. - binary: outputs the result in binary form. -out filename: indicates the output filename. If this parameter is not specified, the standard output is used. -sign filename: reads the private key from the specified file to sign the digest valueCopy the code
Openssl DGST sample
openssl dgst -sha1 -c /tmp/java-and-more.pem
SHA1(/tmp/java-and-more.pem)= 7e:2a:0b:1e:2e:ec:f8:c2:f7:6a:b3:bf:25:98:64:26:f5:66:ab:38
Copy the code
Java code to achieve MD5 calculation
@Test
public void test_md5(a) throws Exception {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
byte[] fileBytes = Files.readAllBytes(Paths.get("/tmp/java-and-more.pem"));
messageDigest.update(fileBytes);
byte[] result = messageDigest.digest();
System.out.println(Base64.encodeBase64String(result));
}
Copy the code
Finally write here, conscience, code word is not easy, welcome to collect. Java Architecture (Java-and-more)
References:
- Baike.baidu.com/item/Blowfi…
- baike.baidu.com/item/ symmetric encryption /2…
- www.cnblogs.com/gordon0918/…
- Blog.csdn.net/u011414629/…
- baike.baidu.com/item/ asymmetric encryption…
- www.jianshu.com/p/78886e480…
- Blog.csdn.net/makenothing…
- Blog.csdn.net/zlfing/arti…
- Blog.csdn.net/w47_csdn/ar…