catalogue
Software applications inevitably need data interaction and storage, especially data transmission through the Internet. In some scenarios, data can be transmitted in clear text; In some scenarios, even if the data is plaintext, it is necessary to avoid data tampering during transmission, such as order information; In some scenarios, data cannot be transmitted and stored in clear text, such as login information. In these scenarios, the solution is signature or encryption, so it involves the choice of encryption method and algorithm. The text introduces symmetric and asymmetric encryption, as well as the use of java and js.
Symmetric encryption
Encryption and decryption use the same key, that is, both ends of the data interaction hold the same key.
encryption algorithm
AES | Symmetric / block ciphers are generally divided into stream encryption (such as OFB, CFB, etc.) and block encryption (such as ECB, CBC, etc.). For stream encryption, the block cipher needs to be converted to stream mode. For block encryption (or packet encryption), if you want to encrypt data that exceeds the block size, you need to involve filling and chain encryption modes. |
Usage scenario
Generate data signature to avoid data tampering:
Simultaneous interpreting the data set, the client will sort the data according to the data name, and use the key and order set to generate the signature. The signature will be transmitted to the server together with the data set.
After receiving the data set, the server generates a signature according to the same rules and compares the transmitted signatures to avoid data tampering.
Asymmetric encryption
Each user has two secret keys. The public secret key is called the public key, and the secret key he keeps is called the private key.
Usage scenario
A has the public key of B, and B has the public key of A.
A encrypts the information with B's public key and signs with the private key; B uses a's public key to verify the signature, and B uses the private key to decrypt the message.
effect
- Communication security of insecure network
- Information encryption and decryption
- Verify the authenticity of the information source through the public key of the information sender
- Digital signature ensures that the sender cannot deny that the message has been sent
shortcoming
Due to the complexity of the algorithm, the encryption and decryption speed is much slower (thousands of orders of magnitude) than the symmetric encryption algorithm.
encryption algorithm
RSA | The principle of RSA public key cryptosystem is: according to number theory, it is simple to find two large prime numbers, but it is extremely difficult to factorize their product. Therefore, the product can be used as an encryption key |
Elgamal | |
Knapsack algorithm | |
Rabin |
Code example
java uses symmetric encryption
import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; /** * @author ChenHailong * @date 2020/10/10 17:14 **/ public class AESCoder { /** * encryption * @param content Content to be encrypted * @param secretKeyStr AES key used for encryption, BASE64 encoded string * @param iv Initialization vector, 16 bytes in length, 16 * 8 = 128 bits * @return The encrypted ciphertext is returned after BASE64 processing */ public static String encryptAES(byte[] content, String secretKeyStr, String iv) throws Exception { // Get a secret keyspec // SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.getDecoder().decode(secretKeyStr), "AES"); SecretKeySpec secretKeySpec = new SecretKeySpec(secretKeyStr.getBytes(), "AES"); // Get Cipher object of encryption algorithm instance Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //"Algorithm / mode / complement mode" // Get an IvParameterSpec IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes()); // Using CBC mode requires a vector iv, which can increase the strength of the encryption algorithm // Initialization algorithm according to parameters cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); // Perform encryption and return the ciphertext after passing through the assistant at BASE64 return new Base64().encodeToString(cipher.doFinal(content)); } /** * decrypt * @param content: The content to be decrypted is a byte array encoded by BASE64 * @param secretKeyStr: AES key used for decryption, BASE64 encoded string * @param iv: Initialization vector, length 16 bytes, 16 * 8 = 128 bits * @return The decrypted plaintext directly returns the plaintext converted by UTF-8 encoding */ public static String decryptAES(byte[] content, String secretKeyStr, String iv) throws Exception { // The ciphertext is decrypted by BASE64 byte[] contentDecByBase64 = new Base64().decode(content); // Get a secret keyspec // SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.getDecoder().decode(secretKeyStr), "AES"); SecretKeySpec secretKeySpec = new SecretKeySpec(secretKeyStr.getBytes(), "AES"); // Get Cipher object of encryption algorithm instance Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //"Algorithm / mode / complement mode" // Get an initialization IvParameterSpec IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes()); // Initialization algorithm according to parameters cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); // decrypt return new String(cipher.doFinal(contentDecByBase64), "utf8"); } }
js uses symmetric encryption
var encrypt = function (_content) { var _key = getKey() var _iv = getIv(_key) // First, return any type with UTF-8 encoding and decoding parameters let content = CryptoJS.enc.Utf8.parse(_content); let aesKey = CryptoJS.enc.Utf8.parse(_key); let iv = CryptoJS.enc.Utf8.parse(_iv); // encryption let encrypted = CryptoJS.AES.encrypt(content, aesKey, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }) return CryptoJS.enc.Base64.stringify(encrypted.ciphertext); }
java uses asymmetric encryption
import javax.crypto.Cipher; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import static com.chl.victory.core.util.Base64Util.decryptBASE64Bytes; import static com.chl.victory.core.util.Base64Util.encryptBASE64Bytes; /** * RSA Asymmetric encryption */ public class RSACoder { static final String KEY_ALGORITHM = "RSA"; static final String SIGNATURE_ALGORITHM = "MD5withRSA"; /** * Generate a digital signature on the information with the private key * * @param data Encrypted data * @param privateKey Private key * @return */ public static String sign(byte[] data, String privateKey){ try{ // Decrypt the private key encoded by base64 byte[] keyBytes = decryptBASE64Bytes(privateKey); // Construct PKCS8EncodedKeySpec object PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); // KEY_ALGORITHM specifies the encryption algorithm KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // Private key object PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); // Generate a digital signature on the information with the private key Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(priKey); signature.update(data); return encryptBASE64Bytes(signature.sign()); }catch (Exception e){ } return null; } /** * Verify digital signature * * @param data Encrypted data * @param publicKey Public key * @param sign digital signature * @return If the verification is successful, return true and if it fails, return false */ public static boolean verify(byte[] data, String publicKey, String sign){ try{ // Decrypt the public key encoded by base64 byte[] keyBytes = decryptBASE64Bytes(publicKey); // Construct X509EncodedKeySpec object X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); // KEY_ALGORITHM specifies the encryption algorithm KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // Public key object PublicKey pubKey = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(pubKey); signature.update(data); // Verify whether the signature is normal return signature.verify(decryptBASE64Bytes(sign)); }catch (Exception e){ } return false; } /** * Decrypt with private key * @param data base64 byte [] * @param privateKey Private key * @return byte [] of decrypted plaintext */ static byte[] decryptByPrivateKey(byte[] data, String privateKey) throws Exception{ // Decrypt key byte[] keyBytes = decryptBASE64Bytes(privateKey); // Get private key PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key _privateKey = keyFactory.generatePrivate(pkcs8KeySpec); // Decrypt data Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, _privateKey); return cipher.doFinal(data); } /** * Decrypt with private key * @param data base64 Formal ciphertext * @param privateKey Private key * @return Decrypted plaintext */ public static String decryptByPrivateKey(String data, String privateKey){ try { return new String(decryptByPrivateKey(decryptBASE64Bytes(data),privateKey)); } catch (Exception e) { } return null; } /** * Encrypt with public key * * @param data Plaintext to be encrypted byte [] * @param key Public key * @return Encrypted byte [] * @throws Exception */ static byte[] encryptByPublicKey(byte[] data, String key) throws Exception { // Decrypt public key byte[] keyBytes = decryptBASE64Bytes(key); // Get public key X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicKey = keyFactory.generatePublic(x509KeySpec); // Encrypt data Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data); } /** * Encrypt with public key * * @param data Plaintext to be encrypted * @param key Public key * @return Encrypted base64 form */ public static String encryptByPublicKey(String data, String key){ try { return encryptBASE64Bytes(encryptByPublicKey(data.getBytes(), key)); } catch (Exception e) { e.printStackTrace(); } return null; } /** * Generate a new pair of keys * * @throws Exception */ public static RSAStrKeyPair genNewKeyPair(){ try{ KeyPairGenerator keyPairGen = KeyPairGenerator .getInstance(KEY_ALGORITHM); keyPairGen.initialize(1024); KeyPair keyPair = keyPairGen.generateKeyPair(); String publicK = encryptBASE64Bytes(keyPair.getPublic().getEncoded()); String privateK = encryptBASE64Bytes(keyPair.getPrivate().getEncoded()); return new RSAStrKeyPair(privateK, publicK); }catch (Exception e){ } return null; } }
js uses asymmetric encryption
// jsencrypt.min.js var pubKey = xxxx var encrypt = new JSEncrypt(); encrypt.setPublicKey(pubKey); var encryptedPass = encrypt.encrypt(pass);