JAVA encryption algorithm asymmetric encryption algorithm (DH RSA)

  • 2020-05-12 02:45:47
  • OfStack

Asymmetric cryptographic concepts

1. The main difference with symmetric encryption algorithm is that the encryption and decryption keys are not the same, 1 public (public key) and 1 private (private key). It mainly solves the key distribution management problem of symmetric encryption algorithm and improves the security of the algorithm.

2, asymmetric encryption algorithm encryption, decryption efficiency is relatively low. In algorithm design, asymmetric encryption algorithm has strict requirements on the length of encrypted data. For example, the RSA algorithm requires no more than 53 bytes of data to be encrypted.

3. Asymmetric encryption algorithm is mainly used to exchange the key of symmetric encryption algorithm rather than data exchange

4. java6 provides two algorithms of DH and RSA. Bouncy Castle provides E1Gamal algorithm support. In addition to the above three algorithms, there is an ECC algorithm, which is currently supported by no relevant open source components

Two keys are required for encryption or decryption, the public key and the private key

Features: high safety, slow speed

use

【 key exchange (DH) 】

In the absence of determining the common key, both parties shall generate the key without providing encryption work. Encryption and decryption shall also be realized by other symmetric encryption algorithms

Example of DH algorithm


import javax.crypto.KeyAgreement;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

//1  Generate source key 
//2  Pass the source public key to the target, and the target, through the source public key, generates the target public key and private key 
//3  Give the target public key to the source 
//4  Each party USES the other's public key and its own private key to generate a local key 
//5  The key exchange is completed if both parties generate the same local key 
public class DHUtil {

  public static final String PUBLIC_KEY = "DH_Public_Key";
  public static final String PRIVATE_KEY = "DH_Private_key";

  /**
   *  Generate the source key pair 
   * @return
   * @throws Exception
   */
  public static Map<String,Object> initSourceKey() throws Exception{
    // create KeyPairGenerator The example is selected DH algorithm 
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");

    // Initializes key length, default 1024 , optional range 512-65536 & 64 A multiple of 
    keyPairGenerator.initialize(1024);

    // Generate key pair 
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    DHPublicKey dhPublicKey = (DHPublicKey) keyPair.getPublic();
    DHPrivateKey dhPrivateKey = (DHPrivateKey) keyPair.getPrivate();

    // Put the key pair in Map
    Map<String,Object> keyMap = new HashMap<String, Object>();
    keyMap.put(PUBLIC_KEY, dhPublicKey);
    keyMap.put(PRIVATE_KEY, dhPrivateKey);
    return keyMap;
  }

  /**
   *  Through the source public key   generate   Target key pair 
   * @param sourcePublicKey
   * @return
   * @throws Exception
   */
  public static Map<String,Object> initTargetKey(byte[] sourcePublicKey) throws Exception {

    KeyFactory keyFactory = KeyFactory.getInstance("DH");

    // Through the source public key, generate keySpec , the use of KeyFactory Generated source PublicKey The relevant information 
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(sourcePublicKey);
    DHPublicKey sourcePublic = (DHPublicKey) keyFactory.generatePublic(keySpec);

    DHParameterSpec dhPublicKeyParams = sourcePublic.getParams();

    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
    keyPairGenerator.initialize(dhPublicKeyParams);

    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    DHPublicKey dhPublicKey = (DHPublicKey) keyPair.getPublic();
    DHPrivateKey dhPrivateKey = (DHPrivateKey) keyPair.getPrivate();

    // Put the key pair in Map
    Map<String,Object> keyMap = new HashMap<String, Object>();
    keyMap.put(PUBLIC_KEY, dhPublicKey);
    keyMap.put(PRIVATE_KEY, dhPrivateKey);
    return keyMap;
  }

  /**
   *  use 1 Square the public key and another 1 Generates the local key 
   * @return
   */
  public static byte[] generateLocalSecretKey(byte[] aPublicKey, byte[] bPrivateKey) throws Exception{
    KeyFactory keyFactory = KeyFactory.getInstance("DH");

    // through A Public key, generate keySpec , the use of KeyFactory generate A PublicKey The relevant information 
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(aPublicKey);
    PublicKey publicKey = keyFactory.generatePublic(keySpec);

    // through B Private key, generated B PrivateKey The relevant information 
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(bPrivateKey);
    PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

    // through KeyAgreement right A the PublicKey and B the PrivateKey encrypted 
    KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
    keyAgreement.init(privateKey);
    keyAgreement.doPhase(publicKey,true);


    return keyAgreement.generateSecret("AES").getEncoded();// The algorithm USES symmetric encryption algorithm ( DES . DESede . AES ) 
    //return keyAgreement.generateSecret();        //  You can also use the default method without selecting the algorithm 
  }

  // Gets the public key byte array 
  public static byte[] getPublicKey(Map<String,Object> map){
    return ((DHPublicKey) map.get(PUBLIC_KEY)).getEncoded();
  }

  // Gets the private key byte array 
  public static byte[] getPrivateKey(Map<String,Object> map){
    return ((DHPrivateKey) map.get(PRIVATE_KEY)).getEncoded();
  }

  public static void main(String[] args) throws Exception {

    byte[] source_public_key;
    byte[] source_private_key;
    byte[] source_local_key;

    byte[] target_public_key;
    byte[] target_private_key;
    byte[] target_local_key;

    Map<String, Object> sourceKey = initSourceKey();
    source_public_key = getPublicKey(sourceKey);
    source_private_key = getPrivateKey(sourceKey);

    System.out.println(" Source public key: "+BytesToHex.fromBytesToHex(source_public_key));
    System.out.println(" Source the private key: "+BytesToHex.fromBytesToHex(source_private_key));

    Map<String, Object> targetKey = initTargetKey(getPublicKey(sourceKey));
    target_public_key = getPublicKey(targetKey);
    target_private_key = getPrivateKey(targetKey);

    System.out.println(" Target public key: "+BytesToHex.fromBytesToHex(target_public_key));
    System.out.println(" Target private key: "+BytesToHex.fromBytesToHex(target_private_key));

    source_local_key = generateLocalSecretKey(target_public_key, source_private_key);
    target_local_key = generateLocalSecretKey(source_public_key, target_private_key);

    System.out.println(" Source local key: "+BytesToHex.fromBytesToHex(source_local_key));
    System.out.println(" Target local key: "+BytesToHex.fromBytesToHex(target_local_key));
  }
}

[encryption/decryption (RSA)] [digital signature (RSA)]

The RSA algorithm is later than the DH algorithm, which is the first asymmetric cryptosystem.

RSA algorithm speed slow, not suitable for the encryption of large amounts of data. One solution is to will RSA to mix with symmetric encryption is used, the data encrypted with a symmetric encryption, asymmetric encryption keys using RSA algorithm encryption, because the key is very short, so the cost is not too much time. In fact, the disadvantages of symmetric encryption only 1 bad is the key, symmetric encryption is also difficult to crack.

Scenario 1 for RSA:

(1) the server generates a public key and a private key and exposes the public key.

(2) the client USES the public key to encrypt the data and hand it over to the server. It is impossible for others to understand the encrypted data.

(3) the server USES the private key to decrypt the data and view the data submitted by the user.

In this scenario, the public key is like a mailbox into which everyone can put messages, but only the person who holds the key to the mailbox can open the box and view the messages.

Scenario 2 for RSA:

(1) the emperor generated a public key and a key, the public key public.

(2) there are two strings of Numbers in the lower right corner of the imperial edict. The first string of Numbers is a random string, and the second string of Numbers is the result of encrypting the first string of Numbers with a private key.

(3) some people did not believe that the imperial edict was written by the emperor, so they decrypted the second string of Numbers using the public key. After decrypting, they found that the second string of Numbers was just like the first string of Numbers, indicating that the emperor really wrote them, because people like 1 did not have the key, so they could not encrypt the data that could be decrypted with the public key.

In this scenario, the public key is used for decryption, and the private key is used for encryption, which can be used when publishing an announcement to prove that the announcement was actually made by someone.

In fact, the signature does not have to be very long. In general, the signature is fixed in length. To fix the length, we can use MessageDigest algorithm, such as MD5 and SHA series.

The RSA encryption/decryption example


import javax.crypto.Cipher;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;

/**
 * RSA Encryption tools 
 */
public class RSAUtil {

  public static final String PUBLIC_KEY = "RSA_Public_Key";
  public static final String PRIVATE_KEY = "RSA_Private_Key";

  /**
   *  Initialization key 
   * @return
   * @throws Exception
   */
  public static Map<String,Object> initKey() throws Exception{
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(1024);//512-65536 & 64 A multiple of 
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

    Map<String,Object> keyMap = new HashMap<String, Object>();
    keyMap.put(PUBLIC_KEY, publicKey);
    keyMap.put(PRIVATE_KEY, privateKey);
    return keyMap;
  }

  public static RSAPublicKey getPublicKey(Map<String,Object> keyMap) {
    return (RSAPublicKey) keyMap.get(PUBLIC_KEY);
  }

  public static RSAPrivateKey getPrivateKey(Map<String,Object> keyMap){
    return (RSAPrivateKey) keyMap.get(PRIVATE_KEY);
  }

  /**
   *  Use the public key to encrypt the data 
   * @param data
   * @param publicKey
   * @return
   * @throws Exception
   */
  public static byte[] encrypt(byte[] data, RSAPublicKey publicKey) throws Exception{
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE,publicKey);
    return cipher.doFinal(data);
  }

  /**
   *  Decrypt using the private key 
   * @param data
   * @param privateKey
   * @return
   * @throws Exception
   */
  public static byte[] decrypt(byte[] data, RSAPrivateKey privateKey) throws Exception{
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE,privateKey);
    return cipher.doFinal(data);
  }

  public static void main(String[] args) throws Exception {
    String data = " Jay Chou - dong ";
    Map<String, Object> keyMap = initKey();

    byte[] miwen = encrypt(data.getBytes(),getPublicKey(keyMap));
    System.out.println(" Encrypted content: "+BytesToHex.fromBytesToHex(miwen));

    byte[] plain = decrypt(miwen, getPrivateKey(keyMap));
    System.out.println(" Declassified content: "+new String(plain));

  }
}


Related articles: