Summarize some encryption algorithms commonly used in Java

  • 2021-09-16 07:00:37
  • OfStack

Catalog 1. Classification of Encryption Algorithms 2. Application of Encryption Algorithms 3. Implementation of Symmetric Encryption Algorithms 3.1 DES Introduction 3.2 IDEA Introduction 4. Irreversible Encryption Algorithms 4.1 MD5 Introduction 4.2 SHA1 Introduction 4.3 HMAC Introduction 5. Asymmetric Encryption 5.1 RSA Introduction 5.2 ECC Introduction

1. Classification of encryption algorithms

Encryption algorithms are usually divided into three categories:

Symmetric encryption

Refers to an encryption algorithm that uses the same key for encryption and decryption. Symmetric encryption algorithm has the advantage of high encryption and decryption efficiency and easy implementation.

Irreversible encryption

The characteristic of irreversible encryption algorithm is that the encryption process does not need a key, and the encrypted data cannot be decrypted. Only the same input data can get the same encrypted data through the same irreversible algorithm.

Asymmetric encryption

Refers to encryption algorithms that use different keys for encryption and decryption, also known as public and private key encryption.

2. Application of encryption algorithm

1. Digital signature: Authentication and data integrity verification, mainly using asymmetric key encryption technology and digital digest technology.

2. Digital certificate: It is mainly used to ensure that the digital signature is safe and valid, and the digital certificate is issued by an independent certificate issuing authority. Digital certificates are different, and each certificate can provide different levels of credibility. The certificate contains the user's personal information and his public key information, and also attaches the signature information of the certification authority.

3. MD5: Encrypt and save the user password.

4. Network data encryption: Ensure the safety of transmitted data. Even if the message is intercepted, the true content of the message cannot be known without the key.

5. SSL protocol: Asymmetric encryption is used in handshake stage and symmetric encryption is used in transmission stage, that is to say, the data transmitted on SSL is encrypted with symmetric key. At the same time, HTTPS is also a network protocol constructed by SSL+HTTP protocol, which can encrypt transmission and authenticate (confirm whether the target host connected by the client is a true and correct host).

3. Implementation of Symmetric Encryption Algorithm

Advantages: The algorithm is open to both sides of the message, with less computation, fast encryption speed and high encryption efficiency. Disadvantages: Before data transmission, the sender and receiver must agree on the secret key, and then both parties keep the secret key. If the secret key of one party is leaked, the encrypted information will be cracked.

3.1 Introduction to DES

DES is called Data Encryption Standard, that is, data encryption standard. It is a block algorithm using key encryption. In 1977, it was identified as the Federal Data Processing Standard (FIPS) by the National Bureau of Standards of the federal government of the United States, and authorized to be used in non-confidential government communications. Subsequently, the algorithm has been widely spread in the world. But it's a little out of date now.

Java code implementation:


import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.SecretKeyFactory;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;

/**
 * DES Introduction to Encryption  DES Yes 1 A symmetric encryption algorithm, the so-called symmetric encryption algorithm is: encryption and decryption using the same key algorithm. DES The encryption algorithm comes from IBM The research, 
 *  It was officially adopted by the US government, and then it began to spread widely, but it has been used less and less in recent years because DES Use 56 Bit key, with modern computing power, 
 * 24 It can be cracked within hours. Nevertheless, in some simple applications, we can still use the DES Encryption algorithm, briefly explained in this paper DES Adj. JAVA Realization   . 
 *  Note: DES During encryption and decryption, the key length must be 8 Multiple of 
 */
public class DesDemo {
	public DesDemo() {
	}

	//  Test 
	public static void main(String args[]) {
		//  Content to be encrypted 
		String str = "cryptology";
		//  Password, if the length is 8 Multiple of 
		String password = "95880288";

		byte[] result;
		try {
			result = DesDemo.encrypt(str.getBytes(), password);
			System.out.println(" After encryption: " + result);
			byte[] decryResult = DesDemo.decrypt(result, password);
			System.out.println(" After decryption: " + new String(decryResult));
		} catch (UnsupportedEncodingException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}

	//  Decrypt the above contents directly 

	/**
	 *  Encryption 
	 * 
	 * @param datasource
	 *            byte[]
	 * @param password
	 *            String
	 * @return byte[]
	 */
	public static byte[] encrypt(byte[] datasource, String password) {
		try {
			SecureRandom random = new SecureRandom();
			DESKeySpec desKey = new DESKeySpec(password.getBytes());
			//  Create 1 A key factory, and then use it to put DESKeySpec Convert to 
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			SecretKey securekey = keyFactory.generateSecret(desKey);
			// Cipher Object actually completes the encryption operation 
			Cipher cipher = Cipher.getInstance("DES");
			//  Initialize with a key Cipher Object ,ENCRYPT_MODE Used to set the  Cipher  Constant initialized to cryptographic mode 
			cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
			//  Now, get the data and encrypt it 
			//  Formally perform encryption operations 
			return cipher.doFinal(datasource); //  Encrypt or decrypt data in a single-part operation, or end 1 Multipart operations 
		} catch (Throwable e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 *  Decryption 
	 * 
	 * @param src
	 *            byte[]
	 * @param password
	 *            String
	 * @return byte[]
	 * @throws Exception
	 */
	public static byte[] decrypt(byte[] src, String password) throws Exception {
		// DES The algorithm requires the following 1 Trusted random number sources 
		SecureRandom random = new SecureRandom();
		//  Create 1 A DESKeySpec Object 
		DESKeySpec desKey = new DESKeySpec(password.getBytes());
		//  Create 1 Key factory 
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");//  Object that implements the specified transformation 
																			// Cipher
																			//  Object 
		//  Will DESKeySpec Object is converted to SecretKey Object 
		SecretKey securekey = keyFactory.generateSecret(desKey);
		// Cipher Object actually completes the decryption operation 
		Cipher cipher = Cipher.getInstance("DES");
		//  Initialize with a key Cipher Object 
		cipher.init(Cipher.DECRYPT_MODE, securekey, random);
		//  Really start the decryption operation 
		return cipher.doFinal(src);
	}
}

3.2 Introduction to IDEA

This algorithm is developed on the basis of DES algorithm, which is similar to triple DES. IDEA was developed because DES felt that the key was too short. The DEA has a 128-bit key, which should be secure for several years to come. It is enough to know little about what is used in actual projects.

Java code implementation


import java.security.Key;
import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class IDEADemo {
	public static void main(String args[]) {
		bcIDEA();
	}
	public static void bcIDEA() {
	    String src = "www.xttblog.com security idea";
	    try {
	        Security.addProvider(new BouncyCastleProvider());
	         
	        // Generate key
	        KeyGenerator keyGenerator = KeyGenerator.getInstance("IDEA");
	        keyGenerator.init(128);
	        SecretKey secretKey = keyGenerator.generateKey();
	        byte[] keyBytes = secretKey.getEncoded();
	         
	        // Conversion key 
	        Key key = new SecretKeySpec(keyBytes, "IDEA");
	         
	        // Encryption 
	        Cipher cipher = Cipher.getInstance("IDEA/ECB/ISO10126Padding");
	        cipher.init(Cipher.ENCRYPT_MODE, key);
	        byte[] result = cipher.doFinal(src.getBytes());
	        System.out.println("bc idea encrypt : " + Base64.encodeBase64String(result));
	         
	        // Decryption 
	        cipher.init(Cipher.DECRYPT_MODE, key);
	        result = cipher.doFinal(result);
	        System.out.println("bc idea decrypt : " + new String(result));
	    } catch (Exception e) {
	        e.printStackTrace();
	    }
	}
}

4. Irreversible encryption algorithm

Advantages: Irreversible, easy to calculate and characteristic Disadvantages: Possible hash conflicts

4.1 Introduction to MD5

The function of MD5 is to "compress" large amounts of information into a secure format before signing the private key with digital signature software
That is to say, a byte string of arbitrary length is converted into a 106-digit string of fixed length.

It mainly has the following characteristics:

1. Compressibility: For any length of data, the calculated length of MD5 value is fixed. 2. Easy to calculate: It is easy to calculate MD5 value from the original data. 3. Modification resistance: Any modification of the original data, even if only one byte is modified, the resulting MD5 value is quite different. 4. Strong anti-collision: Given the original data and its MD5 value, it is very difficult to find a data with the same MD5 value (i.e., forged data).

Implementation of Java code


import java.security.MessageDigest;

// Utilization JDK Provide java.security.MessageDigest Class implementation MD5 Algorithm 
public class MD5Demo {

    public static void main(String[] args) {
        System.out.println(getMD5Code(" Irreversible encryption algorithm "));
    }

    private MD5Demo() {
    }

    // md5 Encryption 
    public static String getMD5Code(String message) {
        String md5Str = "";
        try {
        	// Create MD5 Algorithm message digest 
            MessageDigest md = MessageDigest.getInstance("MD5");
            // Byte array of generated hash values 
            byte[] md5Bytes = md.digest(message.getBytes());
            md5Str = bytes2Hex(md5Bytes);
        }catch(Exception e) {
            e.printStackTrace();
        }
        return md5Str;
    }

    // 2 Binary conversion 16 Binary system 
    public static String bytes2Hex(byte[] bytes) {
        StringBuffer result = new StringBuffer();
        int temp;
        try {
            for (int i = 0; i < bytes.length; i++) {
                temp = bytes[i];
                if(temp < 0) {
                    temp += 256;
                }
                if (temp < 16) {
                    result.append("0");
                }
                result.append(Integer.toHexString(temp));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result.toString();
    }
}

4.2 Introduction to SHA1

For messages less than 2 ^ 64 bits in length, SHA1 generates a 160-bit (40-character) message digest. When a message is received, this message digest can be used to verify the integrity of the data. In the process of transmission, the data is likely to change, so different message digest will be produced at this time.

SHA1 has the following characteristics:

Information cannot be recovered from the message digest; Two different messages do not produce the same message digest (but there is a 1 in 48 chance that the same message digest will appear in 1x, which is ignored when used).

Implementation of Java code


import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SHA1Demo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(getSha1(" Irreversible encryption algorithm "));
	
	}

	public static String getSha1(String str) {
		if (null == str || 0 == str.length()) {
			return null;
		}
		char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
		try {
			// Create SHA1 Algorithm message digest object 
			MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
			// Updates the summary with the specified byte array. 
			mdTemp.update(str.getBytes("UTF-8"));
			// Byte array of generated hash values 
			byte[] md = mdTemp.digest();
			//SHA1 Key process of generating information summary by algorithm 
			int j = md.length;
		    char[] buf = new char[j * 2];
			int k = 0;
			for (int i = 0; i < j; i++) {
				byte byte0 = md[i];
				buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
				buf[k++] = hexDigits[byte0 & 0xf];
			}
			return new String(buf);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return "0";
		
	}
}

4.3 Introduction to HMAC

HMAC is a key-related hash operation message authentication code (Hash-based Message Authentication Code). HMAC operation uses hash algorithm (MD5, SHA1, etc.), takes one key and one message as input, and generates one message digest as output.

HMAC both the sender and the receiver have key for calculation, but without the third party of key, the correct hash value cannot be calculated, which can prevent data from being tampered with.

Java code implementation


import net.pocrd.annotation.NotThreadSafe;
import net.pocrd.define.ConstField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;


@NotThreadSafe
public class HMacHelper {
    private static final Logger logger = LoggerFactory.getLogger(HMacHelper.class);
    private Mac mac;

    /**
     * MAC The following algorithms can be selected 
     * HmacMD5/HmacSHA1/HmacSHA256/HmacSHA384/HmacSHA512
     */
    private static final String KEY_MAC = "HmacMD5";
    public HMacHelper(String key) {
        try {
            SecretKey secretKey = new SecretKeySpec(key.getBytes(ConstField.UTF8), KEY_MAC);
            mac = Mac.getInstance(secretKey.getAlgorithm());
            mac.init(secretKey);
        } catch (Exception e) {
            logger.error("create hmac helper failed.", e);
        }
    }
    public byte[] sign(byte[] content) {
        return mac.doFinal(content);
    }

    public boolean verify(byte[] signature, byte[] content) {
        try {
            byte[] result = mac.doFinal(content);
            return Arrays.equals(signature, result);
        } catch (Exception e) {
            logger.error("verify sig failed.", e);
        }
        return false;
    }
}

5. Asymmetric encryption

Advantages: Compared with symmetric encryption, asymmetric encryption has better security, and it is difficult to crack as long as the private key is not leaked. Disadvantages: Encryption and decryption takes a long time and is slow, which is only suitable for encrypting a small amount of data.

5.1 Introduction to RSA

RSA is the most influential and commonly used public key encryption algorithm. It can resist most known cryptographic attacks so far, and has been recommended as the public key data encryption standard by ISO. The principle of RSA public key cryptosystem is: According to the number theory, it is relatively simple to find two large prime numbers, but it is extremely difficult to factorize their product, so the product can be publicly used as the encryption key

Implementation of Java code


import org.apache.commons.codec.binary.Base64;

import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;

/**
 * Created by humf. Need dependency  commons-codec  Bag 
 */
public class RSADemo {

	public static void main(String[] args) throws Exception {
		Map<String, Key> keyMap = initKey();
		String publicKey = getPublicKey(keyMap);
		String privateKey = getPrivateKey(keyMap);

		System.out.println(keyMap);
		System.out.println("-----------------------------------");
		System.out.println(publicKey);
		System.out.println("-----------------------------------");
		System.out.println(privateKey);
		System.out.println("-----------------------------------");
		byte[] encryptByPrivateKey = encryptByPrivateKey("123456".getBytes(), privateKey);
		byte[] encryptByPublicKey = encryptByPublicKey("123456", publicKey);
		System.out.println(encryptByPrivateKey);
		System.out.println("-----------------------------------");
		System.out.println(encryptByPublicKey);
		System.out.println("-----------------------------------");
		String sign = sign(encryptByPrivateKey, privateKey);
		System.out.println(sign);
		System.out.println("-----------------------------------");
		boolean verify = verify(encryptByPrivateKey, publicKey, sign);
		System.out.println(verify);
		System.out.println("-----------------------------------");
		byte[] decryptByPublicKey = decryptByPublicKey(encryptByPrivateKey, publicKey);
		byte[] decryptByPrivateKey = decryptByPrivateKey(encryptByPublicKey, privateKey);
		System.out.println(decryptByPublicKey);
		System.out.println("-----------------------------------");
		System.out.println(decryptByPrivateKey);

	}

	public static final String KEY_ALGORITHM = "RSA";
	public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

	private static final String PUBLIC_KEY = "RSAPublicKey";
	private static final String PRIVATE_KEY = "RSAPrivateKey";

	public static byte[] decryptBASE64(String key) {
		return Base64.decodeBase64(key);
	}

	public static String encryptBASE64(byte[] bytes) {
		return Base64.encodeBase64String(bytes);
	}

	/**
	 *  Generate a digital signature for information with a private key 
	 *
	 * @param data
	 *             Encrypted data 
	 * @param privateKey
	 *             Private key 
	 * @return
	 * @throws Exception
	 */
	public static String sign(byte[] data, String privateKey) throws Exception {
		//  Decrypt by base64 Encoded private key 
		byte[] keyBytes = decryptBASE64(privateKey);
		//  Structure PKCS8EncodedKeySpec Object 
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
		// KEY_ALGORITHM  Specified encryption algorithm 
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		//  Private key object 
		PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
		//  Generate a digital signature for information with a private key 
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		signature.initSign(priKey);
		signature.update(data);
		return encryptBASE64(signature.sign());
	}

	/**
	 *  Verification digital signature 
	 *
	 * @param data
	 *             Encrypted data 
	 * @param publicKey
	 *             Public key 
	 * @param sign
	 *             Digital signature 
	 * @return  Successful verification returns true  Failure return false
	 * @throws Exception
	 */
	public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
		//  Decrypt by base64 Encoded public key 
		byte[] keyBytes = decryptBASE64(publicKey);
		//  Structure X509EncodedKeySpec Object 
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
		// KEY_ALGORITHM  Specified encryption algorithm 
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		//  Take the public key object 
		PublicKey pubKey = keyFactory.generatePublic(keySpec);
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		signature.initVerify(pubKey);
		signature.update(data);
		//  Verify that the signature is normal 
		return signature.verify(decryptBASE64(sign));
	}

	public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception {
		//  Decrypt the key 
		byte[] keyBytes = decryptBASE64(key);
		//  Get the 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);
	}

	/**
	 *  Decryption <br>
	 *  Decrypt with private key 
	 *
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] decryptByPrivateKey(String data, String key) throws Exception {
		return decryptByPrivateKey(decryptBASE64(data), key);
	}

	/**
	 *  Decryption <br>
	 *  Decrypt with public key 
	 *
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] decryptByPublicKey(byte[] data, String key) throws Exception {
		//  Decrypt the key 
		byte[] keyBytes = decryptBASE64(key);
		//  Get the public key 
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		Key publicKey = keyFactory.generatePublic(x509KeySpec);
		//  Decrypt data 
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.DECRYPT_MODE, publicKey);
		return cipher.doFinal(data);
	}

	/**
	 *  Encryption <br>
	 *  Encryption with public key 
	 *
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptByPublicKey(String data, String key) throws Exception {
		//  Decryption of public key 
		byte[] keyBytes = decryptBASE64(key);
		//  Get the 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.getBytes());
	}

	/**
	 *  Encryption <br>
	 *  Encryption with private key 
	 *
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception {
		//  Decrypt the key 
		byte[] keyBytes = decryptBASE64(key);
		//  Get the private key 
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
		//  Encrypt data 
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
		return cipher.doFinal(data);
	}

	/**
	 *  Get the private key 
	 *
	 * @param keyMap
	 * @return
	 * @throws Exception
	 */
	public static String getPrivateKey(Map<String, Key> keyMap) throws Exception {
		Key key = (Key) keyMap.get(PRIVATE_KEY);
		return encryptBASE64(key.getEncoded());
	}

	/**
	 *  Get the public key 
	 *
	 * @param keyMap
	 * @return
	 * @throws Exception
	 */
	public static String getPublicKey(Map<String, Key> keyMap) throws Exception {
		Key key = keyMap.get(PUBLIC_KEY);
		return encryptBASE64(key.getEncoded());
	}

	/**
	 *  Initialization key 
	 *
	 * @return
	 * @throws Exception
	 */
	public static Map<String, Key> initKey() throws Exception {
		KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
		keyPairGen.initialize(1024);
		KeyPair keyPair = keyPairGen.generateKeyPair();
		Map<String, Key> keyMap = new HashMap(2);
		keyMap.put(PUBLIC_KEY, keyPair.getPublic());//  Public key 
		keyMap.put(PRIVATE_KEY, keyPair.getPrivate());//  Private key 
		return keyMap;
	}

}

5.2 Introduction to ECC

ECC It is also an asymmetric encryption algorithm, and its main advantage is that it uses a smaller key than other methods in some cases, such as RSA Encryption algorithm, providing equivalent or higher security level. However, one disadvantage is that encryption and decryption operations take longer to implement than other mechanisms (compared with RSA Algorithm, which pairs the CPU Heavy consumption).

Implementation of Java code


import net.pocrd.annotation.NotThreadSafe;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.Security;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

@NotThreadSafe
public class EccHelper {
    private static final Logger logger = LoggerFactory.getLogger(EccHelper.class);
    private static final int SIZE = 4096;
    private BCECPublicKey  publicKey;
    private BCECPrivateKey privateKey;

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public EccHelper(String publicKey, String privateKey) {
        this(Base64Util.decode(publicKey), Base64Util.decode(privateKey));
    }

    public EccHelper(byte[] publicKey, byte[] privateKey) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
            if (publicKey != null && publicKey.length > 0) {
                this.publicKey = (BCECPublicKey)keyFactory.generatePublic(new X509EncodedKeySpec(publicKey));
            }
            if (privateKey != null && privateKey.length > 0) {
                this.privateKey = (BCECPrivateKey)keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey));
            }
        } catch (ClassCastException e) {
            throw new RuntimeException("", e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public EccHelper(String publicKey) {
        this(Base64Util.decode(publicKey));
    }

    public EccHelper(byte[] publicKey) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
            if (publicKey != null && publicKey.length > 0) {
                this.publicKey = (BCECPublicKey)keyFactory.generatePublic(new X509EncodedKeySpec(publicKey));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public byte[] encrypt(byte[] content) {
        if (publicKey == null) {
            throw new RuntimeException("public key is null.");
        }
        try {
            Cipher cipher = Cipher.getInstance("ECIES", "BC");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            int size = SIZE;
            ByteArrayOutputStream baos = new ByteArrayOutputStream((content.length + size - 1) / size * (size + 45));
            int left = 0;
            for (int i = 0; i < content.length; ) {
                left = content.length - i;
                if (left > size) {
                    cipher.update(content, i, size);
                    i += size;
                } else {
                    cipher.update(content, i, left);
                    i += left;
                }
                baos.write(cipher.doFinal());
            }
            return baos.toByteArray();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public byte[] decrypt(byte[] secret) {
        if (privateKey == null) {
            throw new RuntimeException("private key is null.");
        }
        try {
            Cipher cipher = Cipher.getInstance("ECIES", "BC");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            int size = SIZE + 45;
            ByteArrayOutputStream baos = new ByteArrayOutputStream((secret.length + size + 44) / (size + 45) * size);
            int left = 0;
            for (int i = 0; i < secret.length; ) {
                left = secret.length - i;
                if (left > size) {
                    cipher.update(secret, i, size);
                    i += size;
                } else {
                    cipher.update(secret, i, left);
                    i += left;
                }
                baos.write(cipher.doFinal());
            }
            return baos.toByteArray();
        } catch (Exception e) {
            logger.error("ecc decrypt failed.", e);
        }
        return null;
    }

    public byte[] sign(byte[] content) {
        if (privateKey == null) {
            throw new RuntimeException("private key is null.");
        }
        try {
            Signature signature = Signature.getInstance("SHA1withECDSA", "BC");
            signature.initSign(privateKey);
            signature.update(content);
            return signature.sign();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public boolean verify(byte[] sign, byte[] content) {
        if (publicKey == null) {
            throw new RuntimeException("public key is null.");
        }
        try {
            Signature signature = Signature.getInstance("SHA1withECDSA", "BC");
            signature.initVerify(publicKey);
            signature.update(content);
            return signature.verify(sign);
        } catch (Exception e) {
            logger.error("ecc verify failed.", e);
        }
        return false;
    }
}

Related articles: