RSA encryption algorithm
Let's review RSA's encryption algorithm. We use relatively standardized language to describe this algorithm based on the definition of public key encryption algorithm and signature algorithm.
The RSA public key encryption system includes the following 3 algorithms: KeyGen (key generation algorithm), Encrypt (encrypt) and Decrypt (decryption algorithm).
The key generation algorithm uses a security constant as input to output a public key PK and a private key SK. The security constant is used to determine how secure the encryption algorithm is, which is generally related to the size of the prime number p used by the encryption algorithm. The larger the prime number p is, the larger the system is, ensuring higher security. In RSA, the key generation algorithm is as follows: the algorithm first randomly generates two different large prime numbers p and q, and calculates N=pq. Then, the algorithm calculates the Euler function. Next, the algorithm randomly selects an integer less than e and calculates the modulo inverse element d of e. Finally, the public key is PK=(N, e) and the private key is SK=(N, d).
The encryption algorithm uses the public key PK and the message M to be encrypted as input and outputs the ciphertext CT. In RSA, the encryption algorithm is as follows: the algorithm directly outputs the ciphertext as the decryption algorithm uses the private key SK and ciphertext CT as inputs, and outputs the message M. In RSA, the decryption algorithm is as follows: the algorithm outputs the plaintext as directly. Since e and d are inversely opposite to each other, we have:
Therefore, from the algorithm description, we can also see that the public key is used to encrypt the data, and the private key is used to decrypt the data. Of course, this can also be understood intuitively: a public key is a public key, and only when it is disclosed can everyone use it to encrypt data. A private key is a private key, and whoever has this key can decrypt the ciphertext. Otherwise, if everyone can see the private key and decrypt it, it will be a mess.
Let’s take a look at the simple implementation in Java:
package com.stone.security; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.util.Arrays; import javax.crypto.Cipher; /** * RSA algorithm public key encryption asymmetric encryption*/ public class RSA { public static final String KEY_ALGORITHM = "RSA"; public static final String CIPHER_ALGORITHM_ECB1 = "RSA/ECB/PKCS1Padding"; public static final String CIPHER_ALGORITHM_ECB2 = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding"; //You cannot use public static final String CIPHER_ALGORITHM_ECB3 = "OAEPWithSHA-256AndMGF1Padding"; //You cannot use static PublicKey publicKey; static PrivateKey privateKey; static Cipher cipher; static KeyPair keyPair; public static void main(String[] args) throws Exception { method1("Skoda U*(Sfsad7f()*^%%$"); method2("Skoda U*(Sfsad7f()*^%%$"); method3("Skoda U*(Sfsad7f()*^%%$"); } /** * Public key encryption, private key decryption uses the default CIPHER_ALGORITHM_ECB1 * @param str * @throws Exception */ static void method1(String str) throws Exception { KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM); KeyPair keyPair = keyGenerator.generateKeyPair(); publicKey = keyPair.getPublic(); privateKey = keyPair.getPrivate(); cipher = Cipher.getInstance(KEY_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, publicKey); //Public key encryption byte[] encrypt = cipher.doFinal(str.getBytes()); System.out.println("Public key encryption 1:" + Arrays.toString(encrypt)); cipher.init(Cipher.DECRYPT_MODE, privateKey);//Private key decryption byte[] decrypt = cipher.doFinal(encrypt); System.out.println("Private key decryption 1:" + new String(decrypt)); } /** * Private key encryption, public key decryption uses the default CIPHER_ALGORITHM_ECB1 * @param str * @throws Exception */ static void method2(String str) throws Exception { KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM); KeyPair keyPair = keyGenerator.generateKeyPair(); publicKey = keyPair.getPublic(); privateKey = keyPair.getPrivate(); cipher = Cipher.getInstance(KEY_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, privateKey); //Private key encryption byte[] encrypt = cipher.doFinal(str.getBytes()); System.out.println("Private key encryption 2: " + Arrays.toString(encrypt)); cipher.init(Cipher.DECRYPT_MODE, publicKey); //Public key decrypt byte[] decrypt = cipher.doFinal(encrypt); System.out.println("Public key decrypt 2: " + new String(decrypt)); } /** * Private key encryption, public key decryption uses CIPHER_ALGORITHM_ECB1 = RSA/ECB/PKCS1Padding * @param str * @throws Exception */ static void method3(String str) throws Exception { KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM); KeyPair keyPair = keyGenerator.generateKeyPair(); publicKey = keyPair.getPublic(); privateKey = keyPair.getPrivate(); cipher = Cipher.getInstance(CIPHER_ALGORITHM_ECB1); cipher.init(Cipher.ENCRYPT_MODE, privateKey); //Private key encryption byte[] encrypt = cipher.doFinal(str.getBytes()); System.out.println("Private key encryption 3:" + Arrays.toString(encrypt)); cipher.init(Cipher.DECRYPT_MODE, publicKey); //Public key decryption byte[] decrypt = cipher.doFinal(encrypt); System.out.println("3 after public key decryption:" + new String(decrypt)); } } DSA algorithm and digital signature
DSA is generally used for digital signatures and certification.
DSA is a variant of Schnorr and ElGamal signature algorithms, and is used by NIST in the United States as DSS (Digital Signature Standard).
DSA is based on the integer finite domain discrete logarithmic problem, and its security is similar to RSA.
In DSA digital signature and authentication, the sender uses his own private key to sign a file or message, and the recipient uses the sender's public key to verify the authenticity of the signature after receiving the message. DSA is just an algorithm, and the difference between RSA is that it cannot be used for encryption and decryption, nor for key exchange.
For signatures only, it is much faster than RSA.
package com.stone.security; import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; /** * DSA-Digital Signature Algorithm is a variant of Schnorr and ElGamal signature algorithms, and is used as DSS by NIST in the United States. * In short, this is a more advanced verification method used as a digital signature. Not only public and private keys, but also digital signatures. Private key encryption generates digital signatures, public key verification data and signatures. * If the data and signature do not match, verification will be considered to be failed! That is, the data in transmission can no longer be encrypted. After the receiver obtains the data, he gets the public key and signature to verify whether the data is valid. */ public class DSA { /** *Not only can you use the DSA algorithm, but you can also use the RSA algorithm for digital signatures*/ public static final String KEY_ALGORITHM = "RSA"; public static final String SIGNATURE_ALGORITHM = "MD5withRSA";*/ public static final String KEY_ALGORITHM = "DSA"; public static final String SIGNATURE_ALGORITHM = "DSA"; public static final String DEFAULT_SEED = "$%^*%^()(HJG8awfjas7"; //Default seed public static final String PUBLIC_KEY = "DSAPublicKey"; public static final String PRIVATE_KEY = "DSAPrivateKey"; public static void main(String[] args) throws Exception { String str = "!@#$!#^$#&ZXVDF Daijun Industrial Road Loves You*()_+"; byte[] data = str.getBytes(); Map<String, Object> keyMap = initKey();// build key PublicKey publicKey = (PublicKey) keyMap.get(PUBLIC_KEY); PrivateKey privateKey = (PrivateKey) keyMap.get(PRIVATE_KEY); System.out.println("Private key format:" + privateKey.getFormat()); System.out.println("Public key format:" + publicKey.getFormat()); // generate the signature String sign = sign(data, getPrivateKey(keyMap)); // Verify the signature boolean verify1 = verify("aaa".getBytes(), getPublicKey(keyMap), sign); System.err.println("Verify data and signature matching:" + verify1); boolean verify = verify(data, getPublicKey(keyMap), sign); System.err.println("Verify data and signature matching:" + verify); } /** * Generate key* * @param seed seed* @return key object* @throws Exception */ public static Map<String, Object> initKey(String seed) throws Exception { System.out.println("Generate key"); KeyPairGenerator keygen = KeyPairGenerator.getInstance(KEY_ALGORITHM); SecureRandom secureRandom = new SecureRandom(); secureRandom.setSeed(seed.getBytes()); //Modulus size must range from 512 to 1024 and be a multiple of 64 keygen.initialize(640, secureRandom); KeyPair keys = keygen.genKeyPair(); PrivateKey privateKey = keys.getPrivate(); PublicKey publicKey = keys.getPublic(); Map<String, Object> map = new HashMap<String, Object>(2); map.put(PUBLIC_KEY, publicKey); map.put(PRIVATE_KEY, privateKey); return map; } /** * Generate the default key* * @return Key object* @throws Exception */ public static Map<String, Object> initKey() throws Exception { return initKey(DEFAULT_SEED); } /** * Get the private key* * @param keyMap * @return * @throws Exception */ public static String getPrivateKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PRIVATE_KEY); return encryptBASE64(key.getEncoded()); //base64 encryption private key} /** * Get the public key* * @param keyMap * @return * @throws Exception */ public static String getPublicKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PUBLIC_KEY); return encryptBASE64(key.getEncoded()); //base64 encryption public key} /** * Use the private key to digitally sign the information* @param data Encrypted data* @param privateKey private key - base64 encrypted * @return * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception { System.out.println("digitize the information with the private key"); byte[] keyBytes = decryptBASE64(privateKey); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey priKey = factory.generatePrivate(keySpec);//Generate private key//Digitsign information with private key Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(priKey); signature.update(data); return encryptBASE64(signature.sign()); } /** * BASE64Encoder Encryption* @param data Data to be encrypted* @return Encrypted string */ private static String encryptBASE64(byte[] data) { BASE64Encoder encoder = new BASE64Encoder(); String encode = encoder.encode(data); return encode; } /** * BASE64Decoder Decrypt* @param data String to be decrypted* @return Decrypted byte[] * @throws Exception */ private static byte[] decryptBASE64(String data) throws Exception { BASE64Decoder decoder = new BASE64Decoder(); byte[] buffer = decoder.decodeBuffer(data); return buffer; } /** * Verify digital signature* @param data Encrypted data* @param publicKey * @param sign Digital signature* @return * @throws Exception */ public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { byte[] keyBytes = decryptBASE64(publicKey); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PublicKey pubKey = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(pubKey); signature.update(data); return signature.verify(decryptBASE64(sign)); //Verify signature} }