Java Encryption Technology-Origin of Asymmetric Encryption Algorithms DH

Keywords: Java Junit network Mac

Links to the original text: https://my.oschina.net/mohaiyong/blog/221266

DH
Diffie-Hellman algorithm (D-H algorithm), key agreement protocol. It is an idea put forward by Diffie and Hellman, founders of public key cryptosystem. Simply put, it allows two users to exchange information on public media to generate a "consistent" and shared key. In other words, Party A produces a pair of keys (public key and private key) and Party B produces a pair of keys (public key and private key) according to Party A's public key. Taking this as the baseline, as the basis of data transmission secrecy, both sides use the same symmetric encryption algorithm to construct a local key to encrypt data. In this way, after the exchange of the local key algorithm, both parties disclose their own public keys, encrypt data using the other party's public key and the private key just generated, and decrypt the data using the other party's public key and their own private key. It is not only the two sides of A and B, but also can be extended to multi-party sharing data communication, thus completing the secure communication of network interactive data. The algorithm originates from the Chinese congruence theorem, the Chinese remainder theorem.  

Process analysis:

1. Party A constructs the key pair, publishes the public key to Party B and keeps the private key; both parties agree on the data encryption algorithm; Party B constructs the key pair through Party A's public key, publishes the public key to Party A, and keeps the private key.
2. Party A uses private key, Party B public key and agreed data encryption algorithm to construct local key, then encrypts data through local key and sends it to Party B after encryption. Party B uses private key, Party A public key and agreed data encryption algorithm to construct local key, and then decrypts data through local key.
3. Party B uses private key, Party A public key and agreed data encryption algorithm to construct local key, then encrypts data through local key and sends it to Party A after encryption. Party A uses private key, Party B public key and agreed data encryption algorithm to construct local key, and then decrypts data through local key.


Implemented through java code as follows: See Coder class Java Encryption Technology (I)
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;

/**
 * DH Secure Coding Component
 * 
 * @author Liang Dong
 * @version 1.0
 * @since 1.0
 */
public abstract class DHCoder extends Coder {
	public static final String ALGORITHM = "DH";

	/**
	 * Default number of key bytes
	 * 
	 * <pre>
	 * DH
	 * Default Keysize 1024  
	 * Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive).
	 * </pre>
	 */
	private static final int KEY_SIZE = 1024;

	/**
	 * DH Under encryption, a symmetric encryption algorithm is needed to encrypt data. Here we use DES or other symmetric encryption algorithms.
	 */
	public static final String SECRET_ALGORITHM = "DES";
	private static final String PUBLIC_KEY = "DHPublicKey";
	private static final String PRIVATE_KEY = "DHPrivateKey";

	/**
	 * Initialize Party A key
	 * 
	 * @return
	 * @throws Exception
	 */
	public static Map<String, Object> initKey() throws Exception {
		KeyPairGenerator keyPairGenerator = KeyPairGenerator
				.getInstance(ALGORITHM);
		keyPairGenerator.initialize(KEY_SIZE);

		KeyPair keyPair = keyPairGenerator.generateKeyPair();

		// Party A Public Key
		DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();

		// Party A's private key
		DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();

		Map<String, Object> keyMap = new HashMap<String, Object>(2);

		keyMap.put(PUBLIC_KEY, publicKey);
		keyMap.put(PRIVATE_KEY, privateKey);
		return keyMap;
	}

	/**
	 * Initialize Party B key
	 * 
	 * @param key
	 *            Party A Public Key
	 * @return
	 * @throws Exception
	 */
	public static Map<String, Object> initKey(String key) throws Exception {
		// Analysis of Party A's Public Key
		byte[] keyBytes = decryptBASE64(key);
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
		PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);

		// Constructing Party B's Key from Party A's Public Key
		DHParameterSpec dhParamSpec = ((DHPublicKey) pubKey).getParams();

		KeyPairGenerator keyPairGenerator = KeyPairGenerator
				.getInstance(keyFactory.getAlgorithm());
		keyPairGenerator.initialize(dhParamSpec);

		KeyPair keyPair = keyPairGenerator.generateKeyPair();

		// Party B Public Key
		DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();

		// Party B's Private Key
		DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();

		Map<String, Object> keyMap = new HashMap<String, Object>(2);

		keyMap.put(PUBLIC_KEY, publicKey);
		keyMap.put(PRIVATE_KEY, privateKey);

		return keyMap;
	}

	/**
	 * Encryption < br >
	 * 
	 * @param data
	 *            Data to be encrypted
	 * @param publicKey
	 *            Party A Public Key
	 * @param privateKey
	 *            Party B's Private Key
	 * @return
	 * @throws Exception
	 */
	public static byte[] encrypt(byte[] data, String publicKey,
			String privateKey) throws Exception {

		// Generate local key
		SecretKey secretKey = getSecretKey(publicKey, privateKey);

		// data encryption
		Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());
		cipher.init(Cipher.ENCRYPT_MODE, secretKey);

		return cipher.doFinal(data);
	}

	/**
	 * Decryption < br >
	 * 
	 * @param data
	 *            Data to be decrypted
	 * @param publicKey
	 *            Party B Public Key
	 * @param privateKey
	 *            Party B's Private Key
	 * @return
	 * @throws Exception
	 */
	public static byte[] decrypt(byte[] data, String publicKey,
			String privateKey) throws Exception {

		// Generate local key
		SecretKey secretKey = getSecretKey(publicKey, privateKey);
		// data decryption
		Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());
		cipher.init(Cipher.DECRYPT_MODE, secretKey);

		return cipher.doFinal(data);
	}

	/**
	 * Building keys
	 * 
	 * @param publicKey
	 *            public key
	 * @param privateKey
	 *            private key
	 * @return
	 * @throws Exception
	 */
	private static SecretKey getSecretKey(String publicKey, String privateKey)
			throws Exception {
		// Initialize public key
		byte[] pubKeyBytes = decryptBASE64(publicKey);

		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKeyBytes);
		PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);

		// Initialize the private key
		byte[] priKeyBytes = decryptBASE64(privateKey);

		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKeyBytes);
		Key priKey = keyFactory.generatePrivate(pkcs8KeySpec);

		KeyAgreement keyAgree = KeyAgreement.getInstance(keyFactory
				.getAlgorithm());
		keyAgree.init(priKey);
		keyAgree.doPhase(pubKey, true);

		// Generate local key
		SecretKey secretKey = keyAgree.generateSecret(SECRET_ALGORITHM);

		return secretKey;
	}

	/**
	 * 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());
	}

	/**
	 * Obtain 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());
	}
}


Given another test class:
import static org.junit.Assert.*;

import java.util.Map;

import org.junit.Test;

/**
 * 
 * @author Liang Dong
 * @version 1.0
 * @since 1.0
 */
public class DHCoderTest {

	@Test
	public void test() throws Exception {
		// Generating Party A Key Pairs
		Map<String, Object> aKeyMap = DHCoder.initKey();
		String aPublicKey = DHCoder.getPublicKey(aKeyMap);
		String aPrivateKey = DHCoder.getPrivateKey(aKeyMap);

		System.err.println("Party A Public Key:\r" + aPublicKey);
		System.err.println("Party A's private key:\r" + aPrivateKey);
		
		// Generating Local Key Pairs from Party A's Public Key
		Map<String, Object> bKeyMap = DHCoder.initKey(aPublicKey);
		String bPublicKey = DHCoder.getPublicKey(bKeyMap);
		String bPrivateKey = DHCoder.getPrivateKey(bKeyMap);
		
		System.err.println("Party B Public Key:\r" + bPublicKey);
		System.err.println("Party B's Private Key:\r" + bPrivateKey);
		
		String aInput = "abc ";
		System.err.println("original text: " + aInput);

		// Construction of ciphertext by Party A's public key and Party B's private key
		byte[] aCode = DHCoder.encrypt(aInput.getBytes(), aPublicKey,
				bPrivateKey);

		// Decrypted by Party B's public key and Party A's private key
		byte[] aDecode = DHCoder.decrypt(aCode, bPublicKey, aPrivateKey);
		String aOutput = (new String(aDecode));

		System.err.println("Decrypt: " + aOutput);

		assertEquals(aInput, aOutput);

		System.err.println(" ===============Conversely, encryption and decryption================== ");
		String bInput = "def ";
		System.err.println("original text: " + bInput);

		// Constructing ciphertext with Party B's public key and Party A's private key
		byte[] bCode = DHCoder.encrypt(bInput.getBytes(), bPublicKey,
				aPrivateKey);

		// Decrypted by Party A's public key and Party B's private key
		byte[] bDecode = DHCoder.decrypt(bCode, aPublicKey, bPrivateKey);
		String bOutput = (new String(bDecode));

		System.err.println("Decrypt: " + bOutput);

		assertEquals(bInput, bOutput);
	}

}


Console output:
Party A Public Key:
MIHfMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHz
W5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSG
kx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgANDAAJAdAWBVmIzqcko
Ej6qFjLDL2+Y3FPq1iRbnOyOpDj71yKaK1K+FhTv04B0zy4DKcvAASV7/Gv0W+bgqdmffRkqrQ==

//Party A's private key:
MIHRAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYX
rgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpD
TWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgAQyAjACJRfy1LyR
eHyD+4Hfb+xR0uoIGR1oL9i9Nk6g2AAuaDPgEVWHn+QXID13yL/uDos=

//Party B public key:
MIHfMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHz
W5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSG
kx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgANDAAJAVEYSfBA+I9nr
dWw3OBv475C+eBrWBBYqt0m6/eu4ptuDQHwV4MmUtKAC2wc2nNrdb1wmBhY1X8RnWkJ1XmdDbQ==

//Party B's private key:
MIHSAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYX
rgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpD
TWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgAQzAjEAqaZiCdXp
2iNpdBlHRaO9ir70wo2n32xNlIzIX19VLSPCDdeUWkgRv4CEj/8k+/yd

//Original: abc 
//Decryption: abc 
 ===============Conversely, encryption and decryption================== 
//Original: def 
//Decryption: def


As I said, both parties can encrypt the data sent to the other party after obtaining the public key of the other party, and decrypt the received data at the same time, so as to achieve the purpose of data secure communication!



Related links:
Java Encryption Technology (1) - BASE64 and One-way Encryption Algorithms MD5 & SHA & MAC
Java Encryption Technology (2) - Symmetric Encryption DES&AES
Java Encryption Technology (3) - PBE Algorithms
Java Encryption Technology (4) - Asymmetric Encryption Algorithms RSA
Java Encryption Technology (V) - Origin of Asymmetric Encryption Algorithms DH
Java Encryption Technology (6) - Digital Signature Algorithms DSA
Java Encryption Technology (7) - Highest ECC of Asymmetric Encryption Algorithms
Java Encryption Technology (8) - Digital Certificate
Java Encryption Technology (9) - Preliminary Exploration of SSL
Java Encryption Technology (10) - One-way Authentication
Java Encryption Technology (11) - Two-way Authentication
Java Encryption Technology (12) - *. PFX (*. p12) - Personal Information Exchange File

Reproduced in: https://my.oschina.net/mohaiyong/blog/221266

Posted by WarDeities on Sun, 08 Sep 2019 23:06:22 -0700