Skip to content

Instantly share code, notes, and snippets.

@Bombe
Last active October 25, 2016 12:15
Show Gist options
  • Save Bombe/5be29459824a0ecdbd9b to your computer and use it in GitHub Desktop.
Save Bombe/5be29459824a0ecdbd9b to your computer and use it in GitHub Desktop.
Use the power of threads!
/**
* GenerateVanityKey.java – generates keypairs with a prefix
* Copyright © 2014 David ‘Bombe’ Roden
* <p>
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* <p>
* GUID:1783028B-ECB6-462E-929E-A33A37D823BA
*/
package freenet.tools;
import static freenet.keys.InsertableClientSSK.createRandom;
import static java.lang.String.format;
import static java.lang.System.currentTimeMillis;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.atomic.AtomicLong;
import freenet.crypt.RandomSource;
import freenet.crypt.Yarrow;
import freenet.keys.FreenetURI;
import freenet.keys.InsertableClientSSK;
/**
* Generates a vanity key pair, i.e. a keypair with the public key starting
* with a specific set of characters.
*
* @author <a href="mailto:[email protected]">David ‘Bombe’ Roden</a>
*/
public class GenerateVanityKey {
public static void main(final String... arguments) throws Exception {
if (arguments.length == 0) {
System.err.println("Syntax: GenerateVanityKey <prefix> [<prefix> [...]]");
System.exit(1);
}
System.err.println("*** You should not really be using this script!");
System.err.println("*** If you manage to find a nice prefix for your site you make it easier");
System.err.println("*** for an attacker to impersonate you: he only needs to find a key with");
System.err.println("*** the same prefix because people are very lazy and won’t compare anthing");
System.err.println("*** but the prefix!");
final RandomSource randomSource = new Yarrow();
long firstOutput = currentTimeMillis();
long foundKeys = 0;
AtomicLong generatedKeys = new AtomicLong();
BlockingQueue<FreenetURI[]> resultKeypairs = new ArrayBlockingQueue<>(1);
KeyMatcher keyMatcher = createKeyMatcher(arguments);
Runnable keyFinder = createKeyFinder(randomSource, generatedKeys, resultKeypairs, keyMatcher);
for (int threadIndex = 0; threadIndex < 4; threadIndex++) {
new Thread(keyFinder).start();
}
while (true) {
FreenetURI[] keypair = resultKeypairs.poll(1000, MILLISECONDS);
if (keypair != null) {
System.out.println(format("\r%s <- %s", keypair[1], keypair[0]));
foundKeys++;
continue;
}
long timeSpent = currentTimeMillis() - firstOutput;
System.err.print(format("\r%d/s, %.3f/s",
generatedKeys.get() / MILLISECONDS.toSeconds(timeSpent),
(double) foundKeys / MILLISECONDS.toSeconds(timeSpent)));
}
}
private static KeyMatcher createKeyMatcher(final String[] arguments) {
return new KeyMatcher() {
@Override
public boolean matches(String requestUriWithoutKeyType) {
for (String argument : arguments) {
if (requestUriWithoutKeyType.toLowerCase().startsWith(argument.toLowerCase())) {
return true;
}
}
return false;
}
};
}
private static Runnable createKeyFinder(final RandomSource randomSource, final AtomicLong generatedKeys, final BlockingQueue<FreenetURI[]> resultKeypairs, final KeyMatcher keyMatcher) {
return new Runnable() {
@Override
public void run() {
try {
while (true) {
generateKey();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void generateKey() throws InterruptedException {
InsertableClientSSK clientSSK = createRandom(randomSource, "");
generatedKeys.incrementAndGet();
if (keyMatcher.matches(clientSSK.getURI().toString().substring(4))) {
resultKeypairs.put(new FreenetURI[]{clientSSK.getInsertURI(), clientSSK.getURI()});
}
}
};
}
private interface KeyMatcher {
boolean matches(String requestUri);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment