I heard that wechat search “Java fish” will change strong oh!
This article is in Java Server, which contains my complete series of Java articles, can be read for study or interview
(I) Encryption algorithm
Information encryption is now almost all projects need to use technology, identity authentication, single sign-on, information communication, payment and other scenarios often need to use encryption algorithm, the so-called encryption algorithm, is the original plaintext through a series of algorithm operations into ciphertext. Next, we will introduce some commonly used encryption algorithms at present. This period does not involve the bottom layer of the algorithm, but mainly introduces the application and shows the code.
If you just want to understand how it works, you can skip the code, which you can use directly.
(2) MD5 algorithm
To be precise, MD5 is not an encryption algorithm, but a digest algorithm. MD5 can output a string of 128bits in plaintext, which cannot be converted to plaintext. Some MD5 decryption websites on the Internet only save the CORRESPONDING MD5 strings of some strings, and find out the original text through the MD5 strings that have been recorded.
In several projects I’ve worked on, I’ve often seen MD5 used for encryption. For example, for password encryption, after a password is generated, MD5 is used to generate a 128-bit string and save it in the database. After the user enters the password, MD5 string is generated first and then compared in the database. Therefore, we cannot retrieve the original password when retrieving it, because the plaintext password is not saved at all.
public class MD5 {
/** * generate MD5 *@param str
* @return* /
public String encode(String str) {
byte[] result = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes("UTF-8"));
result = md.digest();
} catch (Exception e) {
e.printStackTrace();
return null;
}
return parseByte2HexStr(result);
}
/** * convert binary to hexadecimal **@param buf
* @return* /
private String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
public static void main(String[] args) {
MD5 md5=new MD5();
String content = "The test the test"; System.out.println(md5.encode(content)); }}Copy the code
(3) SHA1 algorithm
SHA1 is a similar message digest algorithm to MD5, but it is more secure than MD5.
public class SHA1 {
public String encode(String str) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(str.getBytes("utf-8"));
byte[] digest = md.digest();
return byteToHexString(digest);
} catch (Exception e) {
e.printStackTrace();
return null; }}public static String byteToHexString(byte[] bytes) {
return String.valueOf(Hex.encodeHex(bytes));
}
public static void main(String[] args) {
SHA1 sha1 = new SHA1();
String content = "The test the test"; System.out.println(sha1.encode(content)); }}Copy the code
(4) AES algorithm
AES is a common symmetric encryption algorithm. Symmetric encryption means that encryption with a key can be decrypted using the key. A state-owned enterprise I have contacted is using AES to realize integrated login internally. The third-party system provides an interface for receiving user information. The STATE-OWNED enterprise encrypts the user information through the AES and sends the user information to the third-party system through this interface. The third-party system performs login operations by itself. It is important to note that the key is very important. If the key is lost, information may be leaked.
public class AES {
/** * converts the incoming plaintext to ciphertext *@param str
* @param pwd
* @return* /
public String encode(String str,String pwd) {
byte[] result = null;
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(pwd.getBytes());
kgen.init(128, random);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
// Create a password
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] byteContent = str.getBytes();
result = cipher.doFinal(byteContent);
} catch (Exception e) {
return null;
}
return parseByte2HexStr(result);
}
/** * Converts the passed ciphertext to plain text *@param str
* @param pwd
* @return* /
public String decode(String str,String pwd) {
byte[] result = null;
byte[] content = parseHexStr2Byte(str);
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(pwd.getBytes());
kgen.init(128, random);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
// Create a password
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
result = cipher.doFinal(content);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return new String(result);
}
/** * convert binary to hexadecimal **@param buf
* @return* /
private String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
/** * convert hexadecimal to binary **@param hexStr
* @return* /
private byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1) {
return null;
}
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
public static void main(String[] args) {
AES aes = new AES();
String content = "Test encryption";
// AES key length should be 16 bits (not required)
String pwd = "javayznbjavayznb";
/ / encryption
System.out.println("Before encryption:" + content);
String encodeResultStr = aes.encode(content,pwd);
System.out.println("After encryption:" + encodeResultStr);
/ / decryption
String decodeResultStr = aes.decode(encodeResultStr,pwd);
System.out.println("After decryption:"+ decodeResultStr); }}Copy the code
(5) DES
DES is also a symmetric encryption algorithm, but it is less secure, efficient, and flexible than AES. However, IT can ensure security. DES also requires encryption and decryption using keys, so keys are very important:
public class DES {
/** * converts the incoming plaintext to ciphertext *@param str
* @param pwd
* @return* /
public String encode(String str,String pwd) {
byte[] result = null;
try {
DESKeySpec keySpec = new DESKeySpec(pwd.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(keySpec);
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] byteContent = str.getBytes();
result = cipher.doFinal(byteContent);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return parseByte2HexStr(result);
}
/** * Converts the passed ciphertext to plain text *@param str
* @param pwd
* @return* /
public String decode(String str,String pwd) {
byte[] result = null;
byte[] content = parseHexStr2Byte(str);
try {
DESKeySpec keySpec = new DESKeySpec(pwd.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(keySpec);
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
result = cipher.doFinal(content);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return new String(result);
}
/** * convert binary to hexadecimal **@param buf
* @return* /
private String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
/** * convert hexadecimal to binary **@param hexStr
* @return* /
private byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1) {
return null;
}
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
public static void main(String[] args) {
DES des = new DES();
String content = "The test the test";
// The key length of DES must be 8 bits (if the key length is less than 8 bits, an error will be reported. After 8 bits, the encryption result will not be affected)
String pwd = "javayznb";
/ / encryption
System.out.println("Before encryption:" + content);
String encodeResultStr = des.encode(content,pwd);
System.out.println("After encryption:" + encodeResultStr);
/ / decryption
String decodeResultStr = des.decode(encodeResultStr,pwd);
System.out.println("After decryption:"+ decodeResultStr); }}Copy the code
(6) of the RSA
RSA is the most influential public key encryption algorithm and can be used for encryption and signature checking. The encryption method used when paying treasure pays docking is RSA. In RSA, there is a pair of keys called public key and private key. The private key is stored by an individual, and the public key may be held by multiple people.
The main application scenarios of RSA are encryption and check, not to mention encryption. Check means that messages are signed using private keys so that messages cannot be tampered with or forged.
Encryption mode: User B sends encrypted data to user A
1. A generates A public key and A private key. The private key is reserved and the public key can be obtained by anyone.
2. B gets the public key and encrypts the data using the public key
3. User A receives the ciphertext and decrypts it using the private key.
1. User A generates A public key and A private key. The private key is kept by user A, and the public key can be obtained by anyone.
2. User A uses the private key to sign the message and sends the signed message to user B.
3. B checks the public key. If true is returned, it indicates that the message was sent from A and has not been tampered with.
public class TestRSA {
/** * The maximum encrypted plaintext size of RSA */
private static final int MAX_ENCRYPT_BLOCK = 117;
/** * Maximum size of RSA ciphertext */
private static final int MAX_DECRYPT_BLOCK = 128;
/** * get the key pair **@returnThe key to * /
public static KeyPair getKeyPair(a) throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(1024);
return generator.generateKeyPair();
}
/** * get the private key **@paramPrivateKey privateKey character string *@return* /
public static PrivateKey getPrivateKey(String privateKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
return keyFactory.generatePrivate(keySpec);
}
/** * Get public key **@paramPublicKey publicKey character string *@return* /
public static PublicKey getPublicKey(String publicKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
return keyFactory.generatePublic(keySpec);
}
/** * RSA encryption **@paramData Indicates the data to be encrypted@paramPublicKey public key *@return* /
public static String encrypt(String data, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
int inputLen = data.getBytes().length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// Encrypt data in segments
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
// Get the encrypted content encoded using Base64 and converted to a string using UTF-8 standards
// An encrypted string
return new String(Base64.encodeBase64String(encryptedData));
}
/** * RSA decryption **@paramData Data to be decrypted *@paramPrivateKey private key *@return* /
public static String decrypt(String data, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] dataBytes = Base64.decodeBase64(data);
int inputLen = dataBytes.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// decrypt data in segments
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
// The decrypted content
return new String(decryptedData, "UTF-8");
}
/** ** signature **@paramData Data to be signed *@paramPrivateKey private key *@returnSignature * /
public static String sign(String data, PrivateKey privateKey) throws Exception {
byte[] keyBytes = privateKey.getEncoded();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = keyFactory.generatePrivate(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(key);
signature.update(data.getBytes());
return new String(Base64.encodeBase64(signature.sign()));
}
/** * check the signature **@paramSrcData The original string *@paramPublicKey public key *@paramSign the signature *@returnCheck whether the visa is approved */
public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
byte[] keyBytes = publicKey.getEncoded();
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey key = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(key);
signature.update(srcData.getBytes());
return signature.verify(Base64.decodeBase64(sign.getBytes()));
}
public static void main(String[] args) {
try {
// Generate a key pair
KeyPair keyPair = getKeyPair();
String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
System.out.println("The private key." + privateKey);
System.out.println("Public." + publicKey);
/ / RSA encryption
String data = "Text content to be encrypted";
String encryptData = encrypt(data, getPublicKey(publicKey));
System.out.println("Encrypted content :" + encryptData);
/ / RSA decryption
String decryptData = decrypt(encryptData, getPrivateKey(privateKey));
System.out.println("Decrypted content :" + decryptData);
/ / RSA signature
String sign = sign(data, getPrivateKey(privateKey));
System.out.println("Signed:"+sign);
/ / RSA attestation
boolean result = verify(data, getPublicKey(publicKey), sign);
System.out.print("Inspection Result :" + result);
} catch (Exception e) {
e.printStackTrace();
System.out.print("Encryption and decryption exception"); }}}Copy the code
(7) Summary
Encryption is an issue that comes up both at work and in an interview and must be mastered. Do not require encryption code written by hand, but to know what each encryption algorithm is doing, is what kind of effect.