-
Notifications
You must be signed in to change notification settings - Fork 6
/
LamportGenThread.java
213 lines (205 loc) · 14.3 KB
/
LamportGenThread.java
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*
* Curecoin 2.0.0a Source Code
* Copyright (c) 2015 Curecoin Developers
* Distributed under MIT License
* Requires Apache Commons Library
* Supports Java 1.7+
*/
import java.security.*;
public class LamportGenThread extends Thread
{
private byte[][] seeds;
private int count;
private SecureRandom lmpPrivGen;
public String[] publicKeys;
private static final String CS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; //Character set used in Lamport Private Key Parts
private MessageDigest md;
private MessageDigest md512;
private org.apache.commons.codec.binary.Base64 base64 = new org.apache.commons.codec.binary.Base64();
public LamportGenThread()
{
try
{
md = MessageDigest.getInstance("SHA-256"); //Initializes md for SHA256 functions to use
md512 = MessageDigest.getInstance("SHA-512"); //Initializes md512 for SHA-512
} catch (Exception e)
{
System.out.println("CRITICAL ERROR: NO SHA-256 SUPPORT! EXITING APPLICATION");
e.printStackTrace();
System.exit(-1);
}
}
/**
* Sets the 2D-byte-array seeds and count
*
* @param seeds 2D byte array of seeds
* @param count Number of keys per thread to run
*/
public void setData(byte[][] seeds, int count)
{
if (publicKeys == null)
{
publicKeys = new String[count];
}
this.seeds = seeds;
this.count = count;
}
/**
* Returns the public keys of the Lamport Signature pair
*
* @return String[] Public keys
*/
public String[] getPublicKeys()
{
return publicKeys;
}
public void run()
{
try
{
for (int i = 0; i < count; i++)
{
publicKeys[i] = SHA256(getLamportPublicKey(seeds[i]));
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* Yeah, it's ugly. This is a manual unroll of the loops required to generate a Lamport Public Key. It used to be very pretty. This is 2x as fast.
* The ugly code is worth the speedup.
* This method takes a seed, creates a SecureRandom seeded with the input seed, and then directly generates the public key, without ever storing the
* private key, as that is unnecessary. Each Lamport Private Key Part is 20 psuedo-random (from seeded SecureRandom) characters. There are 200
* of these, to support signing a 100-bit message.
* The Lamport Public Key is the 200 SHA256Short hashes of the 200 Lamport Private Keys concatenated together in order.
* The Lamport Public Keys returned from calling this method many times build the bottom layer of the Merkle Tree.
* Uses SHA256Short in order to reduce the total size of a 200-part Lamport Public Key down to reduce the size of the blockchain.
*
* @param seed The byte array seed for the desired Lamport Signature Keypair
*
* @return String This is the Public key of the Lamport Signature defined by byte[] seed
*/
private String getLamportPublicKey(byte[] seed)
{
try
{
lmpPrivGen = SecureRandom.getInstance("SHA1PRNG");
} catch (Exception e)
{
System.out.println("ERROR GETTING SecureRandom OBJECT!");
e.printStackTrace();
}
lmpPrivGen.setSeed(seed);
return SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) +
SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA256Short(getLamportPrivateKey()) + SHA512(getLamportPrivateKey()) + SHA512(getLamportPrivateKey());
}
/**
* This method uses the lmpPrivGen object to generate the next Lamport Private Key part. Each Lamport Private Key Part is 20 psuedo-random characters.
*
* @return String The next 20-character Lamport Private Key part.
*/
private String getLamportPrivateKey()
{
int len = CS.length();
return "" + CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) +
CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) +
CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) +
CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len)) + CS.charAt(lmpPrivGen.nextInt(len));
}
/**
* This SHA256 function returns a 16-character, base64 String. The String is shortened to reduce space on the blockchain, and is sufficiently long for security purposes.
*
* @param toHash The String to hash using SHA256
*
* @return String The 16-character base64 String resulting from hashing toHash and truncating
*/
private String SHA256Short(String toHash) //Each hash is shortened to 16 characters based on a 64-character charset. 64^16=79,228,162,514,264,337,593,543,950,336 (Aka more than enough for Lamport)
{
try
{
return base64.encodeAsString(md.digest(toHash.getBytes("UTF-8"))).substring(0, 16);
} catch (Exception e)
{
e.printStackTrace();
}
return null;
}
/**
* This SHA256 function returns a base64 String repesenting the full SHA256 hash of the String toHash
* The full-length SHA256 hashes are used for the non-Lamport and non-Address levels of the Merkle Tree
*
* @param toHash The String to hash using SHA256
*
* @return String the base64 String representing the entire SHA256 hash of toHash
*/
private String SHA256(String toHash)
{
try
{
return base64.encodeAsString(md.digest(toHash.getBytes("UTF-8")));
} catch (Exception e)
{
e.printStackTrace();
}
return null;
}
/**
* This SHA512 function returns the full-length SHA512 hash of the String toHash.
* SHA512 is used for the last 2 elements of the Lamport Signature, in order to require any attacker to break one SHA512 hash if they were to crack a Lamport Public Key.
*
* @param toHash The String to hash using SHA512
*
* @return String the 128-character base64 String resulting from hashing toHash
*/
private String SHA512(String toHash)
{
try
{
return base64.encodeAsString(md512.digest(toHash.getBytes("UTF-8")));
} catch (Exception e)
{
e.printStackTrace();
}
return null;
}
}