Java uses ElGamal algorithm and some issues that need attention

Recently I was working on a demo using the ElGamal algorithm, and I encountered a lot of big pits and recorded them.

For the use of ElGamal, refer to this link: Asymmetric Encryption Algorithm-ElGamal Algorithm

For his use, since jdk did not implement ElGamal, he had to refer to two jar packages: bcprov-jdk16-145.jar and commons-codec-1.11.jar, which later became the source of all evil.

The code written by the predecessor of the original link is as follows:

//initialize key  
        //generate key pair  
        Map<String,Object> keyMap=ElGamalCoder.initKey();  
        // public key  
        byte[] publicKey=ElGamalCoder.getPublicKey(keyMap);  
          
        //private key  
        byte[] privateKey=ElGamalCoder.getPrivateKey(keyMap);  
        System.out.println("Public key: /n"+Base64.encodeBase64String(publicKey));  
        System.out.println("Private key: /n"+Base64.encodeBase64String(privateKey));  
          
        System.out.println("================The key pair is constructed, Party A publishes the public key to Party B, and starts the transmission of encrypted data====== =======");  
        String str="ElGamal Cipher Exchange Algorithm";  
        System.out.println("/n============A sends encrypted data to Party B==============");  
        System.out.println("原文:"+str);  
          
        //Party B uses the public key to encrypt the data  
        byte[] code2=ElGamalCoder.encryptByPublicKey(str.getBytes(), publicKey);  
        System.out.println("==========Party B uses the public key to encrypt the data==============");  
        System.out.println("Encrypted data: "+Base64.encodeBase64String(code2));  
          
          
        //Party A uses the private key to decrypt the data  
        byte[] decode2=ElGamalCoder.decryptByPrivateKey(code2, privateKey);  
          
        System.out.println("Data decrypted by Party A: "+new String(decode2));

The key generation, encryption and decryption are all in one function, so there is no problem when running this way, and there is no garbled code, because the byte[] array is directly used as plaintext and ciphertext for encryption and decryption. However, my requirement is to generate, encrypt, and decrypt the public and private keys in different places, so there are two problems:

1. Instead of using the byte array as a parameter, serialize the byte array into a string, and when the string is passed in as a key for encryption and decryption, the decryption result will be garbled.

Solution: I did not find a suitable serialization method to serialize the generated public and private keys in byte[] format into correct strings, and finally use the file method to solve: write byte[] into a file with byte stream, generate Two files: publicKey and privateKey, when used, read the binary data in the file as byte[], and use this byte[] as a parameter to pass in, there will be no problem of garbled characters.

2. I wrote three functions to separate key generation, encryption and decryption. When called separately, the following exception is reported:

Exception in thread "main" java.security.NoSuchAlgorithmException: ElGamal KeyFactory not available
	at java.security.KeyFactory.<init>(Unknown Source)
	at java.security.KeyFactory.getInstance(Unknown Source)
	at com.sta.Util.ElGamalCoder.encryptByPublicKey(ElGamalCoder.java:104)
	at com.sta.Util.ElGamalCoder.decrypt(ElGamalCoder.java:211)
	at com.sta.Util.ElGamalCoder.main(ElGamalCoder.java:249)
Let's take a look at this sentence:
ElGamal KeyFactory not available

The reason for this sentence is that as mentioned above, the JDK does not implement the ElGamal algorithm by itself, and additional support needs to be added. The code written by the predecessors in the link is called in the same function for key generation, encryption and decryption. Therefore, in the encryption The code written to add ElGamal support during key generation is also valid for encryption and decryption methods, but separate encryption and decryption from key generation. When called separately, KeyFactory will not have ElGamal support, so the above exception is thrown. This link: KeyFactory in java

So I made the following changes to the code written by my predecessors:

/**
	 * Public key encryption
	 * @param data data to be encrypted
	 * @param key key
	 * @return byte[] encrypted data
	 * */
	public static byte[] encryptByPublicKey(byte[] data,byte[] key) throws Exception{
		//----------------- Here are the changes, adding ElGamal support ----------------------- -------------------------
                //Add support for BouncyCastle
		Security.addProvider(new BouncyCastleProvider());
		AlgorithmParameterGenerator apg=AlgorithmParameterGenerator.getInstance(KEY_ALGORITHM);
		//Initialize the parameter generator
		apg.init(KEY_SIZE);
		//generate algorithm parameters
		AlgorithmParameters params=apg.generateParameters();
		//build parameter material
		DHParameterSpec elParams=(DHParameterSpec)params.getParameterSpec(DHParameterSpec.class);
                //--------------------------------------------------------------------------------------------
                 //Instantiate the key factory
		KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
		//Initialize the public key
		//Key material conversion
		X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key);
		//generate public key
		PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);
		
		//data encryption
		Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.ENCRYPT_MODE, pubKey);
		return cipher.doFinal(data);
	}

The decryption method is the same, just add the code supported by ElGamal.

Finally, I attached my modified ElGamalCoder.java: This class generates a public key and a private key by calling the ElGamalCoder.getKeyFile() method. The public key file is publicKey, and the private key file is privateKey.

Encryption: String miwen = ElGamalCoder.decrypt("pass in plaintext here", "publicKey"); //publicKey is the path where the public key file is located (including the file name)

Decryption: String mingwen = ElGamalCoder.encrypt("pass in the encrypted ciphertext here","privateKey");//privateKey is the path where the private key file is located

java file download: ElGamalCoder.java

-end-

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324851914&siteId=291194637