· 6 years ago · Sep 30, 2019, 11:48 PM
1import java.io.UnsupportedEncodingException;
2import java.security.InvalidAlgorithmParameterException;
3import java.security.InvalidKeyException;
4import java.security.Key;
5import java.security.KeyPair;
6import java.security.KeyPairGenerator;
7import java.security.NoSuchAlgorithmException;
8import java.security.NoSuchProviderException;
9import java.security.PrivateKey;
10import java.security.PublicKey;
11import java.security.SecureRandom;
12import java.util.Enumeration;
13
14import javax.crypto.BadPaddingException;
15import javax.crypto.Cipher;
16import javax.crypto.IllegalBlockSizeException;
17import javax.crypto.KeyAgreement;
18import javax.crypto.NoSuchPaddingException;
19import javax.crypto.SecretKey;
20import javax.crypto.ShortBufferException;
21import javax.crypto.spec.IvParameterSpec;
22import javax.crypto.spec.SecretKeySpec;
23
24import org.bouncycastle.jce.ECNamedCurveTable;
25import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
26
27public class Test {
28 public static byte[] iv = new SecureRandom().generateSeed(16);
29
30 public static void main(String[] args) {
31 String plainText = "Look mah, I'm a message!";
32 System.out.println("Original plaintext message: " + plainText);
33
34 // Initialize two key pairs
35 KeyPair keyPairA = generateECKeys();
36 KeyPair keyPairB = generateECKeys();
37
38 // Create two AES secret keys to encrypt/decrypt the message
39 SecretKey secretKeyA = generateSharedSecret(keyPairA.getPrivate(),
40 keyPairB.getPublic());
41 SecretKey secretKeyB = generateSharedSecret(keyPairB.getPrivate(),
42 keyPairA.getPublic());
43
44 // Encrypt the message using 'secretKeyA'
45 String cipherText = encryptString(secretKeyA, plainText);
46 System.out.println("Encrypted cipher text: " + cipherText);
47
48 // Decrypt the message using 'secretKeyB'
49 String decryptedPlainText = decryptString(secretKeyB, cipherText);
50 System.out.println("Decrypted cipher text: " + decryptedPlainText);
51 }
52
53 public static KeyPair generateECKeys() {
54 try {
55 ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("brainpoolp256r1");
56 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
57 "ECDH", "BC");
58
59 keyPairGenerator.initialize(parameterSpec);
60 KeyPair keyPair = keyPairGenerator.generateKeyPair();
61
62 return keyPair;
63 } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException
64 | NoSuchProviderException e) {
65 e.printStackTrace();
66 return null;
67 }
68 }
69
70 public static SecretKey generateSharedSecret(PrivateKey privateKey,
71 PublicKey publicKey) {
72 try {
73 KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "BC");
74 keyAgreement.init(privateKey);
75 keyAgreement.doPhase(publicKey, true);
76
77 SecretKey key = keyAgreement.generateSecret("AES");
78 return key;
79 } catch (InvalidKeyException | NoSuchAlgorithmException
80 | NoSuchProviderException e) {
81 // TODO Auto-generated catch block
82 e.printStackTrace();
83 return null;
84 }
85 }
86
87 public static String encryptString(SecretKey key, String plainText) {
88 try {
89 IvParameterSpec ivSpec = new IvParameterSpec(iv);
90 Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
91 byte[] plainTextBytes = plainText.getBytes("UTF-8");
92 byte[] cipherText;
93
94 cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
95 cipherText = new byte[cipher.getOutputSize(plainTextBytes.length)];
96 int encryptLength = cipher.update(plainTextBytes, 0,
97 plainTextBytes.length, cipherText, 0);
98 encryptLength += cipher.doFinal(cipherText, encryptLength);
99
100 return bytesToHex(cipherText);
101 } catch (NoSuchAlgorithmException | NoSuchProviderException
102 | NoSuchPaddingException | InvalidKeyException
103 | InvalidAlgorithmParameterException
104 | UnsupportedEncodingException | ShortBufferException
105 | IllegalBlockSizeException | BadPaddingException e) {
106 e.printStackTrace();
107 return null;
108 }
109 }
110
111 public static String decryptString(SecretKey key, String cipherText) {
112 try {
113 Key decryptionKey = new SecretKeySpec(key.getEncoded(),
114 key.getAlgorithm());
115 IvParameterSpec ivSpec = new IvParameterSpec(iv);
116 Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
117 byte[] cipherTextBytes = hexToBytes(cipherText);
118 byte[] plainText;
119
120 cipher.init(Cipher.DECRYPT_MODE, decryptionKey, ivSpec);
121 plainText = new byte[cipher.getOutputSize(cipherTextBytes.length)];
122 int decryptLength = cipher.update(cipherTextBytes, 0,
123 cipherTextBytes.length, plainText, 0);
124 decryptLength += cipher.doFinal(plainText, decryptLength);
125
126 return new String(plainText, "UTF-8");
127 } catch (NoSuchAlgorithmException | NoSuchProviderException
128 | NoSuchPaddingException | InvalidKeyException
129 | InvalidAlgorithmParameterException
130 | IllegalBlockSizeException | BadPaddingException
131 | ShortBufferException | UnsupportedEncodingException e) {
132 e.printStackTrace();
133 return null;
134 }
135 }
136
137 public static String bytesToHex(byte[] data, int length) {
138 String digits = "0123456789ABCDEF";
139 StringBuffer buffer = new StringBuffer();
140
141 for (int i = 0; i != length; i++) {
142 int v = data[i] & 0xff;
143
144 buffer.append(digits.charAt(v >> 4));
145 buffer.append(digits.charAt(v & 0xf));
146 }
147
148 return buffer.toString();
149 }
150
151 public static String bytesToHex(byte[] data) {
152 return bytesToHex(data, data.length);
153 }
154
155 public static byte[] hexToBytes(String string) {
156 int length = string.length();
157 byte[] data = new byte[length / 2];
158 for (int i = 0; i < length; i += 2) {
159 data[i / 2] = (byte) ((Character.digit(string.charAt(i), 16) << 4) + Character
160 .digit(string.charAt(i + 1), 16));
161 }
162 return data;
163 }
164}