diff --git a/apps/addressbook/java/src/net/i2p/addressbook/HostTxtParser.java b/apps/addressbook/java/src/net/i2p/addressbook/HostTxtParser.java index 325e38ad9..bfdb55fc7 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/HostTxtParser.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/HostTxtParser.java @@ -236,21 +236,28 @@ class HostTxtParser { } /** - * Usage: HostTxtParser validate example.i2p=b64dest[#!key1=val1#key2=val2] + * Usage: HostTxtParser [-q] validate example.i2p=b64dest[#!key1=val1#key2=val2] */ public static void main(String[] args) throws Exception { + boolean quiet = false; + if (args.length > 0 && args[0].equals("-q")) { + quiet = true; + args = java.util.Arrays.copyOfRange(args, 1, args.length); + } if (args.length != 2 || !args[0].equals("validate")) { System.err.println("Usage: HostTxtParser validate example.i2p=b64dest[#!key1=val1#key2=val2]"); System.exit(1); } HostTxtEntry e = parse(args[1].trim(), false); if (e == null) { - System.err.println("Bad format"); - System.exit(1); + if (!quiet) + System.err.println("Bad format"); + System.exit(2); } if (!e.hasValidSig()) { - System.err.println("Bad signature"); - System.exit(1); + if (!quiet) + System.err.println("Bad signature"); + System.exit(3); } Properties p = e.getProps(); if (p != null) { @@ -259,12 +266,14 @@ class HostTxtParser { p.containsKey(HostTxtEntry.PROP_OLDNAME) || p.containsKey(HostTxtEntry.PROP_OLDSIG)) { if (!e.hasValidSig()) { - System.err.println("Bad inner signature"); - System.exit(1); + if (!quiet) + System.err.println("Bad inner signature"); + System.exit(4); } } } - System.err.println("Good signature for " + e.getName()); + if (!quiet) + System.err.println("Good signature for " + e.getName()); System.exit(0); } diff --git a/core/java/src/net/i2p/data/PrivateKeyFile.java b/core/java/src/net/i2p/data/PrivateKeyFile.java index 0fc4741c6..6c6023b43 100644 --- a/core/java/src/net/i2p/data/PrivateKeyFile.java +++ b/core/java/src/net/i2p/data/PrivateKeyFile.java @@ -8,6 +8,7 @@ import java.io.FileInputStream; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; import java.util.Locale; @@ -23,9 +24,11 @@ import net.i2p.client.I2PClient; import net.i2p.client.I2PClientFactory; import net.i2p.client.I2PSession; import net.i2p.client.I2PSessionException; +import net.i2p.client.naming.HostTxtEntry; import net.i2p.crypto.DSAEngine; import net.i2p.crypto.KeyGenerator; import net.i2p.crypto.SigType; +import net.i2p.util.OrderedProperties; import net.i2p.util.RandomSource; import net.i2p.util.SecureFileOutputStream; @@ -72,9 +75,10 @@ public class PrivateKeyFile { public static void main(String args[]) { int hashEffort = HASH_EFFORT; String stype = null; + String hostname = null; int mode = 0; boolean error = false; - Getopt g = new Getopt("pkf", args, "t:nuxhse:c:"); + Getopt g = new Getopt("pkf", args, "t:nuxhse:c:a:"); int c; while ((c = g.getopt()) != -1) { switch (c) { @@ -97,6 +101,14 @@ public class PrivateKeyFile { error = true; break; + case 'a': + hostname = g.getOptarg(); + if (mode == 0) + mode = c; + else + error = true; + break; + case 'e': hashEffort = Integer.parseInt(g.getOptarg()); break; @@ -171,6 +183,7 @@ public class PrivateKeyFile { PrivateKeyFile pkf2 = new PrivateKeyFile(args[g.getOptind() + 1]); pkf.setSignedCert(pkf2); System.out.println("New destination with signed cert is:"); + break; case 't': // KeyCert @@ -181,6 +194,18 @@ public class PrivateKeyFile { System.out.println("New destination with key cert is:"); break; + case 'a': + // addressbook auth + OrderedProperties props = new OrderedProperties(); + HostTxtEntry he = new HostTxtEntry(hostname, d.toBase64(), props); + he.sign(pkf.getSigningPrivKey()); + System.out.println("Addressbook Authentication String:"); + OutputStreamWriter out = new OutputStreamWriter(System.out); + he.write(out); + out.flush(); + System.out.println(""); + return; + default: // shouldn't happen usage(); @@ -202,6 +227,7 @@ public class PrivateKeyFile { private static void usage() { System.err.println("Usage: PrivateKeyFile [-c sigtype] filename (generates if nonexistent, then prints)\n" + + " PrivateKeyFile -a example.i2p filename (generate addressbook authentication string)\n" + " PrivateKeyFile -h filename (generates if nonexistent, adds hashcash cert)\n" + " PrivateKeyFile -h -e effort filename (specify HashCash effort instead of default " + HASH_EFFORT + ")\n" + " PrivateKeyFile -n filename (changes to null cert)\n" + diff --git a/history.txt b/history.txt index f2275f035..4884880ec 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,7 @@ +2017-02-23 zzz + * HostTxtParser: Add -q command line option, enhance return codes + * PrivateKeyFile: Add option to generate addressbook authentication + 2017-02-20 zzz * GeoIP and blocklist update diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 47667df53..895e8eb46 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 9; + public final static long BUILD = 10; /** for example "-test" */ public final static String EXTRA = "-rc";