I feel like it has been a long time since I last wrote a blog. Let me complain first. This month, the company has been working overtime, publishing and launching the publication, and new projects are too tight, so I won’t say much about the specific ones. Today, it is really important to talk about asymmetric encryption. Asymmetric encryption is indispensable in our daily lives.
concept
Before talking about RSA, let’s first talk about what asymmetric encryption is. When talking about symmetric encryption, it was once said that symmetric encryption algorithms use the same secret key when encrypting and decrypting, and both parties to encrypt and decrypt must use the same key to communicate normally. Asymmetric encryption is not the case. The asymmetric encryption algorithm requires two keys to encrypt and decrypt, namely the public key and the private key.
One thing to note is that the public key and the private key must be a pair. If the data is encrypted with the public key, then only the corresponding private key can be decrypted, and vice versa. Since encryption and decryption use two different keys, this algorithm is called asymmetric encryption algorithm.
Working process
As shown in the figure below, data is transmitted using asymmetric encryption.
The main algorithms used in asymmetric encryption include: RSA, Elgamal, backpack algorithm, Rabin, DH, ECC (elliptic curve encryption algorithm), etc. Today, we will mainly introduce RSA. As for other algorithms, we will choose a few to introduce them later.
RSA
In fact, RSA appeared as early as 1978, and it was the first algorithm that can be used for both data encryption and digital signatures. It is easy to understand and operate and is also very popular. The principle is as described in the above working process.
The RSA algorithm is based on a very simple number theory fact: it is easy to multiply two large prime numbers, but it is extremely difficult to factorize their products, so the product can be disclosed as an encryption key.
Code implementation
Let’s take a look at the specific code implementation below.
import com.google.common.collect.Maps; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import javax.crypto.Cipher; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Map; /** * Created by xiang.li on 2015/3/3. * RSA encryption and decryption tool class*/ public class RSA { /** * Define encryption method*/ private final static String KEY_RSA = "RSA"; /** * Define signature algorithm*/ private final static String KEY_RSA_SIGNATURE = "MD5withRSA"; /** * Define public key algorithm*/ private final static String KEY_RSA_PUBLICKEY = "RSAPublicKey"; /** * Define private key algorithm*/ private final static String KEY_RSA_PRIVATEKEY = "RSAPrivateKey"; /** * Initialization key* @return */ public static Map<String, Object> init() { Map<String, Object> map = null; try { KeyPairGenerator generator generator = KeyPairGenerator.getInstance(KEY_RSA); generator.initialize(1024); KeyPair keyPair = generator.generateKeyPair(); // public key RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // Private key RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // Encapsulate the key as map map = Maps.newHashMap(); map.put(KEY_RSA_PUBLICKEY, publicKey); map.put(KEY_RSA_PRIVATEKEY, privateKey); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return map; } /** * Use the private key to generate a digital signature for the information* @param data Encrypted data* @param privateKey Private key* @return */ public static String sign(byte[] data, String privateKey) { String str = ""; try { // Decrypt the private key encoded byte[] bytes = decryptBase64(privateKey); // Construct the PKCS8EncodedKeySpec object PKCS8EncodedKeySpec pkcs = new PKCS8EncodedKeySpec(bytes); // The specified encryption algorithm KeyFactory factory = KeyFactory.getInstance(KEY_RSA); // Get the private key object PrivateKey key = factory.generatePrivate(pkcs); // Use the private key to generate a digital signature for information Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE); signature.initSign(key); signature.update(data); str = encryptBase64(signature.sign()); } catch (Exception e) { e.printStackTrace(); } return str; } /** * Verify digital signature* @param data Encrypted data* @param publicKey Public key* @param sign Digital signature* @return Verify successful return true, failed return false */ public static boolean verify(byte[] data, String publicKey, String sign) { boolean flag = false; try { // Decrypt the public key encoded byte[] bytes = decryptBase64(publicKey); // Construct the X509EncodedKeySpec object X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes); // The specified encryption algorithm KeyFactory factory = KeyFactory.getInstance(KEY_RSA); // Get the public key object PublicKey key = factory.generatePublic(keySpec); // Verify the digital signature with the public key Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE); signature.initVerify(key); signature.update(data); flag = signature.verify(decryptBase64(sign)); } catch (Exception e) { e.printStackTrace(); } return flag; } /** * Private key decrypt* @param data Encrypted data* @param key Private key* @return */ public static byte[] decryptByPrivateKey(byte[] data, String key) { byte[] result = null; try { // Decrypt the private key byte[] bytes = decryptBase64(key); // Obtain the private key PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes); KeyFactory factory = KeyFactory.getInstance(KEY_RSA); PrivateKey privateKey = factory.generatePrivate(keySpec); // Decrypt the data Cipher cipher = Cipher.getInstance(factory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); result = cipher.doFinal(data); } catch (Exception e) { e.printStackTrace(); } return result; } /** * Private key decryption* @param data Encrypted data* @param key public key* @return */ public static byte[] decryptByPublicKey(byte[] data, String key) { byte[] result = null; try { // Decrypt the public key byte[] bytes = decryptBase64(key); // Get the public key X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes); KeyFactory factory = KeyFactory.getInstance(KEY_RSA); PublicKey publicKey = factory.generatePublic(keySpec); // Decrypt the data Cipher cipher = Cipher.getInstance(factory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicKey); result = cipher.doFinal(data); } catch (Exception e) { e.printStackTrace(); } return result; } /** * Public key encryption* @param data data to be encrypted* @param key Public key* @return */ public static byte[] encryptByPublicKey(byte[] data, String key) { byte[] result = null; try { byte[] bytes = decryptBase64(key); // Get the public key X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes); KeyFactory factory = KeyFactory.getInstance(KEY_RSA); PublicKey publicKey = factory.generatePublic(keySpec); // Encrypt data Cipher cipher = Cipher.getInstance(factory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); result = cipher.doFinal(data); } catch (Exception e) { e.printStackTrace(); } return result; } /** * Private key encryption* @param data to be encrypted* @param key Private key* @return */ public static byte[] encryptByPrivateKey(byte[] data, String key) { byte[] result = null; try { byte[] bytes = decryptBase64(key); // Get the private key PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes); KeyFactory factory = KeyFactory.getInstance(KEY_RSA); PrivateKey privateKey = factory.generatePrivate(keySpec); // Encrypt data Cipher cipher = Cipher.getInstance(factory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateKey); result = cipher.doFinal(data); } catch (Exception e) { e.printStackTrace(); } return result; } /** * Get the public key* @param map * @return */ public static String getPublicKey(Map<String, Object> map) { String str = ""; try { Key key = (Key) map.get(KEY_RSA_PUBLICKEY); str = encryptBase64(key.getEncoded()); } catch (Exception e) { e.printStackTrace(); } return str; } /** * Get the private key* @param map * @return */ public static String getPrivateKey(Map<String, Object> map) { String str = ""; try { Key key = (Key) map.get(KEY_RSA_PRIVATEKEY); str = encryptBase64(key.getEncoded()); } catch (Exception e) { e.printStackTrace(); } return str; } /** * BASE64 Decrypt* @param key String that needs to be decrypted* @return Byte array* @throws Exception */ public static byte[] decryptBase64(String key) throws Exception { return (new BASE64Decoder()).decodeBuffer(key); } /** * BASE64 Encryption* @param key Byte array that needs to be encrypted* @return String* @throws Exception */ public static String encryptBase64(byte[] key) throws Exception { return (new BASE64Encoder()).encodeBuffer(key); } /** * Test method* @param args */ public static void main(String[] args) { String privateKey = ""; String publicKey = ""; // Generate public key private key Map<String, Object> map = init(); publicKey = getPublicKey(map); privateKey = getPrivateKey(map); System.out.println("Public key: /n/r" + publicKey); System.out.println("Private key: /n/r" + privateKey); System.out.println("Public key encryption------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- "; byte[] encWord = encryptByPublicKey(word.getBytes(), publicKey); String decWord = new String(decryptByPrivateKey(encWord, privateKey)); System.out.println("Before encryption: " + word + "/n/r" + "After decryption: " + decWord); System.out.println("Private key encryption---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- encryptByPrivateKey(english.getBytes(), privateKey); String decEnglish = new String(decryptByPublicKey(encEnglish, publicKey)); System.out.println("Before encryption: " + english + "/n/r" + "After decryption: " + decEnglish); System.out.println("Private key signature-public key verification signature"); // Generate signature String sign = sign(encEnglish, privateKey); System.out.println("Signature:/r" + sign); // Verify the signature boolean status = verify(encEnglish, publicKey, sign); System.out.println("Status:/r" + status); } } Encrypt and decrypt results
Conclusion
In fact, a seemingly complex process can be described in one sentence: using public key encryption and private key decryption, one data transfer from Party B to Party A is completed, through private key encryption and public key decryption, and at the same time, through private key signature and public key verification signature, one data transfer and verification from Party A to Party B is completed, and two data transfers complete a complete set of data interactions.
The emergence of asymmetric encryption algorithms is to solve the problem of encrypting and decrypting only one key. As long as this key is lost or disclosed, the encrypted data will be easily attacked. At the same time, it is precisely because of the emergence of asymmetric encryption algorithms that the subsequent digital signatures, digital certificates, etc. are obtained.
Okay, let’s stop here today. The next article continues asymmetric encryption. As for which one, I will know at that time. Keep it secret here first