diff --git a/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java index d525cdccd6..b669f1447c 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java @@ -415,7 +415,9 @@ public class NetDbRenderer { // shouldnt happen buf.append("" + _("Published") + ": in ").append(DataHelper.formatDuration2(0-age)).append("???
\n"); } - buf.append("" + _("Address(es)") + ": "); + buf.append("").append(_("Signing Key")).append(": ") + .append(info.getIdentity().getSigningPublicKey().getType().toString()); + buf.append("
\n" + _("Address(es)") + ": "); String country = _context.commSystem().getCountry(info.getIdentity().getHash()); if(country != null) { buf.append(" + * - Magic "I2Pkeys2" + * - 2 byte crypto type, always 0000 for now + * - 2 byte sig type, see SigType + * - 28 bytes unused + * - Private key (256 bytes) + * - Signing Private key (20 bytes or see SigType) + * - Public key (256 bytes) + * - Random padding for Signing Public Key if less than 128 bytes + * - Signing Public key (128 bytes or see SigTpe) + * Total 660 bytes + * + * + * Old router.keys file format: Note that this is NOT the * same "eepPriv.dat" format used by the client code. *
      *   - Private key (256 bytes)
@@ -74,6 +103,7 @@ public class CreateRouterInfoJob extends JobImpl {
      *  Caller must hold Router.routerInfoFileLock.
      */
     RouterInfo createRouterInfo() {
+        SigType type = getSigTypeConfig(getContext());
         RouterInfo info = new RouterInfo();
         OutputStream fos1 = null;
         OutputStream fos2 = null;
@@ -86,21 +116,26 @@ public class CreateRouterInfoJob extends JobImpl {
             // not necessary, in constructor
             //info.setPeers(new HashSet());
             info.setPublished(getCurrentPublishDate(getContext()));
-            RouterIdentity ident = new RouterIdentity();
-            Certificate cert = getContext().router().createCertificate();
-            ident.setCertificate(cert);
-            PublicKey pubkey = null;
-            PrivateKey privkey = null;
-            SigningPublicKey signingPubKey = null;
-            SigningPrivateKey signingPrivKey = null;
             Object keypair[] = getContext().keyGenerator().generatePKIKeypair();
-            pubkey = (PublicKey)keypair[0];
-            privkey = (PrivateKey)keypair[1];
-            Object signingKeypair[] = getContext().keyGenerator().generateSigningKeypair();
-            signingPubKey = (SigningPublicKey)signingKeypair[0];
-            signingPrivKey = (SigningPrivateKey)signingKeypair[1];
+            PublicKey pubkey = (PublicKey)keypair[0];
+            PrivateKey privkey = (PrivateKey)keypair[1];
+            SimpleDataStructure signingKeypair[] = getContext().keyGenerator().generateSigningKeys(type);
+            SigningPublicKey signingPubKey = (SigningPublicKey)signingKeypair[0];
+            SigningPrivateKey signingPrivKey = (SigningPrivateKey)signingKeypair[1];
+            RouterIdentity ident = new RouterIdentity();
+            Certificate cert = createCertificate(getContext(), signingPubKey);
+            ident.setCertificate(cert);
             ident.setPublicKey(pubkey);
             ident.setSigningPublicKey(signingPubKey);
+            byte[] padding;
+            int padLen = SigningPublicKey.KEYSIZE_BYTES - signingPubKey.length();
+            if (padLen > 0) {
+                padding = new byte[padLen];
+                getContext().random().nextBytes(padding);
+                ident.setPadding(padding);
+            } else {
+                padding = null;
+            }
             info.setIdentity(ident);
             
             info.sign(signingPrivKey);
@@ -108,23 +143,35 @@ public class CreateRouterInfoJob extends JobImpl {
             if (!info.isValid())
                 throw new DataFormatException("RouterInfo we just built is invalid: " + info);
             
-            String infoFilename = getContext().getProperty(Router.PROP_INFO_FILENAME, Router.PROP_INFO_FILENAME_DEFAULT);
-            File ifile = new File(getContext().getRouterDir(), infoFilename);
+            // remove router.keys
+            (new File(getContext().getRouterDir(), KEYS_FILENAME)).delete();
+
+            // write router.info
+            File ifile = new File(getContext().getRouterDir(), INFO_FILENAME);
             fos1 = new BufferedOutputStream(new SecureFileOutputStream(ifile));
             info.writeBytes(fos1);
             
-            String keyFilename = getContext().getProperty(Router.PROP_KEYS_FILENAME, Router.PROP_KEYS_FILENAME_DEFAULT);
-            File kfile = new File(getContext().getRouterDir(), keyFilename);
+            // write router.keys2
+            File kfile = new File(getContext().getRouterDir(), KEYS2_FILENAME);
             fos2 = new BufferedOutputStream(new SecureFileOutputStream(kfile));
+            fos2.write(KEYS2_MAGIC);
+            DataHelper.writeLong(fos2, 2, 0);
+            DataHelper.writeLong(fos2, 2, type.getCode());
+            fos2.write(new byte[KEYS2_UNUSED_BYTES]);
             privkey.writeBytes(fos2);
             signingPrivKey.writeBytes(fos2);
             pubkey.writeBytes(fos2);
+            if (padding != null)
+                fos2.write(padding);
             signingPubKey.writeBytes(fos2);
             
             getContext().keyManager().setKeys(pubkey, privkey, signingPubKey, signingPrivKey);
             
-            _log.info("Router info created and stored at " + ifile.getAbsolutePath() + " with private keys stored at " + kfile.getAbsolutePath() + " [" + info + "]");
+            if (_log.shouldLog(Log.INFO))
+                _log.info("Router info created and stored at " + ifile.getAbsolutePath() + " with private keys stored at " + kfile.getAbsolutePath() + " [" + info + "]");
             getContext().router().eventLog().addEvent(EventLog.REKEYED, ident.calculateHash().toBase64());
+        } catch (GeneralSecurityException gse) {
+            _log.log(Log.CRIT, "Error building the new router information", gse);
         } catch (DataFormatException dfe) {
             _log.log(Log.CRIT, "Error building the new router information", dfe);
         } catch (IOException ioe) {
@@ -136,6 +183,20 @@ public class CreateRouterInfoJob extends JobImpl {
         return info;
     }
     
+    /**
+     *  The configured SigType to expect on read-in
+     *  @since 0.9.16
+     */
+    public static SigType getSigTypeConfig(RouterContext ctx) {
+        SigType cstype = CreateRouterInfoJob.DEFAULT_SIGTYPE;
+        String sstype = ctx.getProperty(PROP_ROUTER_SIGTYPE);
+        if (sstype != null) {
+            SigType ntype = SigType.parseSigType(sstype);
+            if (ntype != null && ntype.isAvailable())
+                cstype = ntype;
+        }
+        return cstype;
+    }
     
     /**
      * We probably don't want to expose the exact time at which a router published its info.
@@ -146,4 +207,22 @@ public class CreateRouterInfoJob extends JobImpl {
         //_log.info("Setting published date to /now/");
         return context.clock().now();
     }
+
+    /**
+     *  Only called at startup via LoadRouterInfoJob and RebuildRouterInfoJob.
+     *  Not called by periodic RepublishLocalRouterInfoJob.
+     *  We don't want to change the cert on the fly as it changes the router hash.
+     *  RouterInfo.isHidden() checks the capability, but RouterIdentity.isHidden() checks the cert.
+     *  There's no reason to ever add a hidden cert?
+     *
+     *  @return the certificate for a new RouterInfo - probably a null cert.
+     *  @since 0.9.16 moved from Router
+     */
+    static Certificate createCertificate(RouterContext ctx, SigningPublicKey spk) {
+        if (spk.getType() != SigType.DSA_SHA1)
+            return new KeyCertificate(spk);
+        if (ctx.getBooleanProperty(Router.PROP_HIDDEN))
+            return new Certificate(Certificate.CERTIFICATE_TYPE_HIDDEN, null);
+        return Certificate.NULL_CERT;
+    }
 }
diff --git a/router/java/src/net/i2p/router/startup/LoadRouterInfoJob.java b/router/java/src/net/i2p/router/startup/LoadRouterInfoJob.java
index 016b77bc33..4b5ffdf4fb 100644
--- a/router/java/src/net/i2p/router/startup/LoadRouterInfoJob.java
+++ b/router/java/src/net/i2p/router/startup/LoadRouterInfoJob.java
@@ -15,7 +15,9 @@ import java.io.InputStream;
 import java.io.IOException;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import net.i2p.crypto.SigType;
 import net.i2p.data.DataFormatException;
+import net.i2p.data.DataHelper;
 import net.i2p.data.PrivateKey;
 import net.i2p.data.PublicKey;
 import net.i2p.data.router.RouterInfo;
@@ -26,7 +28,11 @@ import net.i2p.router.Router;
 import net.i2p.router.RouterContext;
 import net.i2p.util.Log;
 
-public class LoadRouterInfoJob extends JobImpl {
+/**
+ *  Run once or twice at startup by StartupJob,
+ *  and then runs BootCommSystemJob
+ */
+class LoadRouterInfoJob extends JobImpl {
     private final Log _log;
     private RouterInfo _us;
     private static final AtomicBoolean _keyLengthChecked = new AtomicBoolean();
@@ -45,6 +51,7 @@ public class LoadRouterInfoJob extends JobImpl {
         if (_us == null) {
             RebuildRouterInfoJob r = new RebuildRouterInfoJob(getContext());
             r.rebuildRouterInfo(false);
+            // run a second time
             getContext().jobQueue().addJob(this);
             return;
         } else {
@@ -54,15 +61,19 @@ public class LoadRouterInfoJob extends JobImpl {
         }
     }
     
+    /**
+     *  Loads router.info and router.keys2 or router.keys.
+     *
+     *  See CreateRouterInfoJob for file formats
+     */
     private void loadRouterInfo() {
-        String routerInfoFile = getContext().getProperty(Router.PROP_INFO_FILENAME, Router.PROP_INFO_FILENAME_DEFAULT);
         RouterInfo info = null;
-        String keyFilename = getContext().getProperty(Router.PROP_KEYS_FILENAME, Router.PROP_KEYS_FILENAME_DEFAULT);
-        
-        File rif = new File(getContext().getRouterDir(), routerInfoFile);
+        File rif = new File(getContext().getRouterDir(), CreateRouterInfoJob.INFO_FILENAME);
         boolean infoExists = rif.exists();
-        File rkf = new File(getContext().getRouterDir(), keyFilename);
+        File rkf = new File(getContext().getRouterDir(), CreateRouterInfoJob.KEYS_FILENAME);
         boolean keysExist = rkf.exists();
+        File rkf2 = new File(getContext().getRouterDir(), CreateRouterInfoJob.KEYS2_FILENAME);
+        boolean keys2Exist = rkf2.exists();
         
         InputStream fis1 = null;
         InputStream fis2 = null;
@@ -73,7 +84,7 @@ public class LoadRouterInfoJob extends JobImpl {
             // CRIT   ...sport.udp.EstablishmentManager: Error in the establisher java.lang.NullPointerException
             // at net.i2p.router.transport.udp.PacketBuilder.buildSessionConfirmedPacket(PacketBuilder.java:574)
             // so pretend the RI isn't there if there is no keyfile
-            if (infoExists && keysExist) {
+            if (infoExists && (keys2Exist || keysExist)) {
                 fis1 = new BufferedInputStream(new FileInputStream(rif));
                 info = new RouterInfo();
                 info.readBytes(fis1);
@@ -85,11 +96,37 @@ public class LoadRouterInfoJob extends JobImpl {
                 _us = info;
             }
             
-            if (keysExist) {
-                fis2 = new BufferedInputStream(new FileInputStream(rkf));
+            if (keys2Exist || keysExist) {
+                SigType stype;
+                if (keys2Exist) {
+                    fis2 = new BufferedInputStream(new FileInputStream(rkf2));
+                    // read keys2 headers
+                    byte[] magic = new byte[CreateRouterInfoJob.KEYS2_MAGIC.length];
+                    DataHelper.read(fis2, magic);
+                    if (!DataHelper.eq(magic, CreateRouterInfoJob.KEYS2_MAGIC))
+                        throw new IOException("Bad magic");
+                    int ctype = (int) DataHelper.readLong(fis2, 2);
+                    if (ctype != 0)
+                        throw new IOException("Unsupported RI crypto type " + ctype);
+                    int sstype = (int) DataHelper.readLong(fis2, 2);
+                    stype = SigType.getByCode(sstype);
+                    if (stype == null || !stype.isAvailable())
+                        throw new IOException("Unsupported RI sig type " + stype);
+                    DataHelper.skip(fis2, CreateRouterInfoJob.KEYS2_UNUSED_BYTES);
+                } else {
+                    fis2 = new BufferedInputStream(new FileInputStream(rkf));
+                    stype = SigType.DSA_SHA1;
+                }
+
+                // check if the sigtype config changed
+                SigType cstype = CreateRouterInfoJob.getSigTypeConfig(getContext());
+                boolean sigTypeChanged = stype != cstype;
+
                 PrivateKey privkey = new PrivateKey();
                 privkey.readBytes(fis2);
-                if (shouldRebuild(privkey)) {
+                if (sigTypeChanged || shouldRebuild(privkey)) {
+                    if (sigTypeChanged)
+                        _log.logAlways(Log.WARN, "Rebuilding RouterInfo with new signature type " + cstype);
                     _us = null;
                     // windows... close before deleting
                     if (fis1 != null) {
@@ -100,13 +137,19 @@ public class LoadRouterInfoJob extends JobImpl {
                     fis2 = null;
                     rif.delete();
                     rkf.delete();
+                    rkf2.delete();
                     return;
                 }
-                SigningPrivateKey signingPrivKey = new SigningPrivateKey();
+                SigningPrivateKey signingPrivKey = new SigningPrivateKey(stype);
                 signingPrivKey.readBytes(fis2);
                 PublicKey pubkey = new PublicKey();
                 pubkey.readBytes(fis2);
-                SigningPublicKey signingPubKey = new SigningPublicKey();
+                SigningPublicKey signingPubKey = new SigningPublicKey(stype);
+                int padLen = SigningPublicKey.KEYSIZE_BYTES - signingPubKey.length();
+                if (padLen > 0) {
+                    // we lose the padding as keymanager doesn't store it, what to do?
+                    DataHelper.skip(fis2, padLen);
+                }
                 signingPubKey.readBytes(fis2);
                 
                 getContext().keyManager().setKeys(pubkey, privkey, signingPubKey, signingPrivKey);
@@ -125,6 +168,7 @@ public class LoadRouterInfoJob extends JobImpl {
             }
             rif.delete();
             rkf.delete();
+            rkf2.delete();
         } catch (DataFormatException dfe) {
             _log.log(Log.CRIT, "Corrupt router info or keys at " + rif.getAbsolutePath() + " / " + rkf.getAbsolutePath(), dfe);
             _us = null;
@@ -139,6 +183,7 @@ public class LoadRouterInfoJob extends JobImpl {
             }
             rif.delete();
             rkf.delete();
+            rkf2.delete();
         } finally {
             if (fis1 != null) try { fis1.close(); } catch (IOException ioe) {}
             if (fis2 != null) try { fis2.close(); } catch (IOException ioe) {}
diff --git a/router/java/src/net/i2p/router/startup/RebuildRouterInfoJob.java b/router/java/src/net/i2p/router/startup/RebuildRouterInfoJob.java
index f531971495..59f822bdaa 100644
--- a/router/java/src/net/i2p/router/startup/RebuildRouterInfoJob.java
+++ b/router/java/src/net/i2p/router/startup/RebuildRouterInfoJob.java
@@ -8,14 +8,18 @@ package net.i2p.router.startup;
  *
  */
 
+import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.InputStream;
 import java.io.IOException;
 import java.util.Properties;
 
+import net.i2p.crypto.SigType;
 import net.i2p.data.Certificate;
 import net.i2p.data.DataFormatException;
+import net.i2p.data.DataHelper;
 import net.i2p.data.PrivateKey;
 import net.i2p.data.PublicKey;
 import net.i2p.data.router.RouterIdentity;
@@ -44,7 +48,7 @@ import net.i2p.util.SecureFileOutputStream;
  * router.info.rebuild file is deleted
  *
  */
-public class RebuildRouterInfoJob extends JobImpl {
+class RebuildRouterInfoJob extends JobImpl {
     private final Log _log;
     
     private final static long REBUILD_DELAY = 45*1000; // every 30 seconds
@@ -57,11 +61,11 @@ public class RebuildRouterInfoJob extends JobImpl {
     public String getName() { return "Rebuild Router Info"; }
     
     public void runJob() {
+        throw new UnsupportedOperationException();
+/****
         _log.debug("Testing to rebuild router info");
-        String infoFile = getContext().getProperty(Router.PROP_INFO_FILENAME, Router.PROP_INFO_FILENAME_DEFAULT);
-        File info = new File(getContext().getRouterDir(), infoFile);
-        String keyFilename = getContext().getProperty(Router.PROP_KEYS_FILENAME, Router.PROP_KEYS_FILENAME_DEFAULT);
-        File keyFile = new File(getContext().getRouterDir(), keyFilename);
+        File info = new File(getContext().getRouterDir(), CreateRouterInfoJob.INFO_FILENAME);
+        File keyFile = new File(getContext().getRouterDir(), CreateRouterInfoJob.KEYS2_FILENAME);
         
         if (!info.exists() || !keyFile.exists()) {
             _log.info("Router info file [" + info.getAbsolutePath() + "] or private key file [" + keyFile.getAbsolutePath() + "] deleted, rebuilding");
@@ -71,41 +75,72 @@ public class RebuildRouterInfoJob extends JobImpl {
         }
         getTiming().setStartAfter(getContext().clock().now() + REBUILD_DELAY);
         getContext().jobQueue().addJob(this);
+****/
     }
     
     void rebuildRouterInfo() {
         rebuildRouterInfo(true);
     }
 
+    /**
+     *  @param alreadyRunning unused
+     */
     void rebuildRouterInfo(boolean alreadyRunning) {
         _log.debug("Rebuilding the new router info");
         RouterInfo info = null;
-        String infoFilename = getContext().getProperty(Router.PROP_INFO_FILENAME, Router.PROP_INFO_FILENAME_DEFAULT);
-        File infoFile = new File(getContext().getRouterDir(), infoFilename);
-        String keyFilename = getContext().getProperty(Router.PROP_KEYS_FILENAME, Router.PROP_KEYS_FILENAME_DEFAULT);
-        File keyFile = new File(getContext().getRouterDir(), keyFilename);
+        File infoFile = new File(getContext().getRouterDir(), CreateRouterInfoJob.INFO_FILENAME);
+        File keyFile = new File(getContext().getRouterDir(), CreateRouterInfoJob.KEYS_FILENAME);
+        File keyFile2 = new File(getContext().getRouterDir(), CreateRouterInfoJob.KEYS2_FILENAME);
         
-        if (keyFile.exists()) {
+        if (keyFile2.exists() || keyFile.exists()) {
             // ok, no need to rebuild a brand new identity, just update what we can
             RouterInfo oldinfo = getContext().router().getRouterInfo();
             if (oldinfo == null) {
                 info = new RouterInfo();
-                FileInputStream fis = null;
+                InputStream fis = null;
                 try {
-                    fis = new FileInputStream(keyFile);
+                    SigType stype;
+                    if (keyFile2.exists()) {
+                        fis = new BufferedInputStream(new FileInputStream(keyFile2));
+                        byte[] magic = new byte[CreateRouterInfoJob.KEYS2_MAGIC.length];
+                        DataHelper.read(fis, magic);
+                        if (!DataHelper.eq(magic, CreateRouterInfoJob.KEYS2_MAGIC))
+                            throw new IOException("Bad magic");
+                        int ctype = (int) DataHelper.readLong(fis, 2);
+                        if (ctype != 0)
+                            throw new IOException("Unsupported RI crypto type " + ctype);
+                        int sstype = (int) DataHelper.readLong(fis, 2);
+                        stype = SigType.getByCode(sstype);
+                        if (stype == null || !stype.isAvailable())
+                            throw new IOException("Unsupported RI sig type " + stype);
+                        DataHelper.skip(fis, CreateRouterInfoJob.KEYS2_UNUSED_BYTES);
+                    } else {
+                        fis = new BufferedInputStream(new FileInputStream(keyFile));
+                        stype = SigType.DSA_SHA1;
+                    }
                     PrivateKey privkey = new PrivateKey();
                     privkey.readBytes(fis);
-                    SigningPrivateKey signingPrivKey = new SigningPrivateKey();
+                    SigningPrivateKey signingPrivKey = new SigningPrivateKey(stype);
                     signingPrivKey.readBytes(fis);
                     PublicKey pubkey = new PublicKey();
                     pubkey.readBytes(fis);
-                    SigningPublicKey signingPubKey = new SigningPublicKey();
+                    SigningPublicKey signingPubKey = new SigningPublicKey(stype);
+                    byte[] padding;
+                    int padLen = SigningPublicKey.KEYSIZE_BYTES - signingPubKey.length();
+                    if (padLen > 0) {
+                        padding = new byte[padLen];
+                        DataHelper.read(fis, padding);
+                    } else {
+                        padding = null;
+                    }
                     signingPubKey.readBytes(fis);
                     RouterIdentity ident = new RouterIdentity();
-                    Certificate cert = getContext().router().createCertificate();
+                    Certificate cert = CreateRouterInfoJob.createCertificate(getContext(), signingPubKey);
                     ident.setCertificate(cert);
                     ident.setPublicKey(pubkey);
                     ident.setSigningPublicKey(signingPubKey);
+                    if (padding != null)
+                        ident.setPadding(padding);
                     info.setIdentity(ident);
                 } catch (Exception e) {
                     _log.log(Log.CRIT, "Error reading in the key data from " + keyFile.getAbsolutePath(), e);
@@ -160,12 +195,14 @@ public class RebuildRouterInfoJob extends JobImpl {
             _log.warn("Private key file " + keyFile.getAbsolutePath() + " deleted!  Rebuilding a brand new router identity!");
             // this proc writes the keys and info to the file as well as builds the latest and greatest info
             CreateRouterInfoJob j = new CreateRouterInfoJob(getContext(), null);
-            info = j.createRouterInfo();
+            synchronized (getContext().router().routerInfoFileLock) {
+                info = j.createRouterInfo();
+            }
         }
         
         //MessageHistory.initialize();
         getContext().router().setRouterInfo(info);
-        _log.info("Router info rebuilt and stored at " + infoFilename + " [" + info + "]");
+        _log.info("Router info rebuilt and stored at " + infoFile + " [" + info + "]");
     }
     
 }
diff --git a/router/java/src/net/i2p/router/startup/StartAcceptingClientsJob.java b/router/java/src/net/i2p/router/startup/StartAcceptingClientsJob.java
index 50d840d432..672bf702aa 100644
--- a/router/java/src/net/i2p/router/startup/StartAcceptingClientsJob.java
+++ b/router/java/src/net/i2p/router/startup/StartAcceptingClientsJob.java
@@ -12,7 +12,7 @@ import net.i2p.router.JobImpl;
 import net.i2p.router.RouterContext;
 
 /** start I2CP interface */
-public class StartAcceptingClientsJob extends JobImpl {
+class StartAcceptingClientsJob extends JobImpl {
     
     public StartAcceptingClientsJob(RouterContext context) {
         super(context);
diff --git a/router/java/src/net/i2p/router/startup/WorkingDir.java b/router/java/src/net/i2p/router/startup/WorkingDir.java
index 3763f2e7a7..15a3e7fb44 100644
--- a/router/java/src/net/i2p/router/startup/WorkingDir.java
+++ b/router/java/src/net/i2p/router/startup/WorkingDir.java
@@ -147,7 +147,7 @@ public class WorkingDir {
         // Check for a router.keys file or logs dir, if either exists it's an old install,
         // and only migrate the data files if told to do so
         // (router.keys could be deleted later by a killkeys())
-        test = new File(oldDirf, "router.keys");
+        test = new File(oldDirf, CreateRouterInfoJob.KEYS_FILENAME);
         boolean oldInstall = test.exists();
         if (!oldInstall) {
             test = new File(oldDirf, "logs");
diff --git a/router/java/src/net/i2p/router/tasks/PersistRouterInfoJob.java b/router/java/src/net/i2p/router/tasks/PersistRouterInfoJob.java
index 7a8868985c..6a14a51346 100644
--- a/router/java/src/net/i2p/router/tasks/PersistRouterInfoJob.java
+++ b/router/java/src/net/i2p/router/tasks/PersistRouterInfoJob.java
@@ -15,8 +15,8 @@ import java.io.IOException;
 import net.i2p.data.DataFormatException;
 import net.i2p.data.router.RouterInfo;
 import net.i2p.router.JobImpl;
-import net.i2p.router.Router;
 import net.i2p.router.RouterContext;
+import net.i2p.router.startup.CreateRouterInfoJob;
 import net.i2p.util.Log;
 import net.i2p.util.SecureFileOutputStream;
 
@@ -37,8 +37,7 @@ public class PersistRouterInfoJob extends JobImpl {
         if (_log.shouldLog(Log.DEBUG))
             _log.debug("Persisting updated router info");
 
-        String infoFilename = getContext().getProperty(Router.PROP_INFO_FILENAME, Router.PROP_INFO_FILENAME_DEFAULT);
-        File infoFile = new File(getContext().getRouterDir(), infoFilename);
+        File infoFile = new File(getContext().getRouterDir(), CreateRouterInfoJob.INFO_FILENAME);
 
         RouterInfo info = getContext().router().getRouterInfo();