-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathIES.java
More file actions
160 lines (148 loc) · 6.31 KB
/
Copy pathIES.java
File metadata and controls
160 lines (148 loc) · 6.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package crypto;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Scanner;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* Discrete Logarithm Integrated Encryption Scheme (IES) in pure Java. It
* combines the Diffie-Hellman key exchange with AES, where the AES secret key
* is generated using SHA-256.
*
* Whenever setting up a cryptosystem that uses the Discrete Logarithm
* Problem, use a prime p of the form 4k + 3 that is also a safe prime
* (p = 2q + 1, q is also a prime).
*
* @author Chris Lattman
*/
public class IES {
/*
* 2048-bit prime obtained from https://www.ietf.org/rfc/rfc3526.txt
* A generator of the prime is 2.
*/
private static final String prime = "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+ "C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404"
+ "DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E"
+ "7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C"
+ "4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
+ "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C35"
+ "4E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B27"
+ "83A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515"
+ "D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF";
/**
* The Integrated Encryption Scheme. IES uses a cryptographic hash
* function to create a secret key and a block cipher to encrypt messages.
* This implementation of IES uses SHA-256 and AES/CBC/PKCS5Padding
* (256-bit AES).
*
* The prime modulus p is given above in hex, which has a generator
* alpha = 2.
*
* Public: (p, alpha, g, h)
* Private: (a, b, s)
*
* @param args not used
* @throws Exception a whole host of exceptions can be thrown, although
* they are all non-issues in this implementation
*/
public static void main(String[] args) throws Exception {
/*
* Alice and Bob publicly agree to use prime p and generator alpha.
*/
BigInteger p = new BigInteger(prime, 16);
BigInteger alpha = BigInteger.TWO;
System.out.println("Public parameters:");
System.out.println("p = " + p.toString(16));
System.out.println("alpha = " + alpha.toString(16));
/*
* In this example, Alice sends a message to Bob, who set up this
* instance of IES.
*
* Alice generates a randomly and Bob generates b randomly. These are
* both secret.
*
* The range of a and b is [2, p - 2].
*
* If a or b are not in the acceptable range, new values of a and b
* are chosen until they fall in the valid range.
*/
SecureRandom random = SecureRandom.getInstanceStrong();
BigInteger a = new BigInteger(2048, random);
BigInteger b = new BigInteger(2048, random);
while (a.compareTo(BigInteger.TWO) < 0 ||
a.compareTo(p.subtract(BigInteger.TWO)) > 0 ||
b.compareTo(BigInteger.TWO) < 0 ||
b.compareTo(p.subtract(BigInteger.TWO)) > 0) {
a = new BigInteger(2048, random);
b = new BigInteger(2048, random);
}
/*
* Alice computes g = alpha^a (mod p) whereas Bob computes
* h = alpha^b (mod p). These are public paramaters, so Alice can see
* Bob's public key (and vice-versa).
*/
BigInteger g = alpha.modPow(a, p);
BigInteger h = alpha.modPow(b, p);
System.out.println("g = " + g.toString(16));
System.out.println("h = " + h.toString(16));
/*
* Alice would then compute h^a = (alpha^b)^a = alpha^(ab) (mod p),
* the shared secret. Bob can also generate this shared secret by
* computing g^b = (alpha^a)^b = alpha^(ab) (mod p).
*/
BigInteger secret = h.modPow(a, p);
/*
* hash is an instance of SHA-256, the cryptographic hash function
* used by IES
*/
MessageDigest hash = MessageDigest.getInstance("SHA-256");
/*
* Alice computes the secret key k for AES by hashing the shared
* secret = alpha^(ab) (mod p). Bob can do the same, since he knows
* the shared secret as well.
*/
byte[] kbytes = hash.digest(secret.toByteArray());
SecretKeySpec k = new SecretKeySpec(kbytes, "AES");
/*
* This is the message to be sent from Alice to Bob.
*/
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the message for Alice to encrypt: ");
String message = scanner.nextLine();
scanner.close();
/*
* cipher is an instance of 256-bit AES with CBC mode and PKCS5
* padding, the block cipher used by IES
*
* It is initialized to encrypt data using the secret key k and an
* initialization vector iv of {0} for AES's CBC mode.
*/
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[16];
IvParameterSpec ivspec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, k, ivspec);
/*
* The message is encrypted with AES and sent to Bob in ciphertext
* base64.
*
* The Base64 class is used due to padding.
*/
byte[] ciphertextbytes = cipher.doFinal(message.getBytes());
String base64 = Base64.getEncoder().encodeToString(ciphertextbytes);
System.out.println("Ciphertext (in base64): " + base64);
/*
* Bob then decrypts the message using the secret key k and the
* initialization vector iv (which were generated earlier).
*
* Here, the same block cipher is reused for decryption.
*/
cipher.init(Cipher.DECRYPT_MODE, k, ivspec);
byte[] cipherbytes = Base64.getDecoder().decode(base64);
byte[] plaintextbytes = cipher.doFinal(cipherbytes);
String plaintext = new String(plaintextbytes);
System.out.println("Plaintext: " + plaintext);
}
}