diff --git a/apps/addressbook/java/src/net/i2p/addressbook/AddressBook.java b/apps/addressbook/java/src/net/i2p/addressbook/AddressBook.java
index faa9979d652def125cf8b94a3bddc4acae066a41..22e8e678b8813936e5a67d7f56d1f34d94a0fa6a 100644
--- a/apps/addressbook/java/src/net/i2p/addressbook/AddressBook.java
+++ b/apps/addressbook/java/src/net/i2p/addressbook/AddressBook.java
@@ -30,6 +30,7 @@ import java.util.Map;
 import java.util.regex.Pattern;
 
 import net.i2p.I2PAppContext;
+import net.i2p.client.naming.HostTxtEntry;
 import net.i2p.util.EepGet;
 import net.i2p.util.SecureFile;
 
diff --git a/apps/addressbook/java/src/net/i2p/addressbook/Daemon.java b/apps/addressbook/java/src/net/i2p/addressbook/Daemon.java
index 6f57754dd1519c50e5ce7455915366c1e0f8b57c..38283aab56e4d4b6b5851ac6b099d32ae0e8f8b9 100644
--- a/apps/addressbook/java/src/net/i2p/addressbook/Daemon.java
+++ b/apps/addressbook/java/src/net/i2p/addressbook/Daemon.java
@@ -32,6 +32,7 @@ import java.util.Properties;
 import java.util.Set;
 
 import net.i2p.I2PAppContext;
+import net.i2p.client.naming.HostTxtEntry;
 import net.i2p.client.naming.NamingService;
 import net.i2p.client.naming.SingleFileNamingService;
 import net.i2p.data.DataFormatException;
diff --git a/apps/addressbook/java/src/net/i2p/addressbook/HostTxtIterator.java b/apps/addressbook/java/src/net/i2p/addressbook/HostTxtIterator.java
index ef1b99103cfdab75563ebc6e7b24f7babff42723..6ba2dfbab26fb824a39066818b71667d735a387c 100644
--- a/apps/addressbook/java/src/net/i2p/addressbook/HostTxtIterator.java
+++ b/apps/addressbook/java/src/net/i2p/addressbook/HostTxtIterator.java
@@ -32,6 +32,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.NoSuchElementException;
 
+import net.i2p.client.naming.HostTxtEntry;
 import net.i2p.data.DataHelper;
 
 /**
diff --git a/apps/addressbook/java/src/net/i2p/addressbook/HostTxtParser.java b/apps/addressbook/java/src/net/i2p/addressbook/HostTxtParser.java
index cfcd7a62519f1d46124f732ee71d218dc98b833c..c907b3b8f6dd7e09832ab0a72dc5ac0fc9187747 100644
--- a/apps/addressbook/java/src/net/i2p/addressbook/HostTxtParser.java
+++ b/apps/addressbook/java/src/net/i2p/addressbook/HostTxtParser.java
@@ -14,6 +14,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
+import net.i2p.client.naming.HostTxtEntry;
 import net.i2p.data.DataHelper;
 import net.i2p.util.SecureFile;
 import net.i2p.util.SecureFileOutputStream;
diff --git a/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionIterator.java b/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionIterator.java
index 5a880f2b14d3d8df8e8f215fe6dc213d5fd74add..8ef67dd6117c86d21db108aac558bb1f89564eaf 100644
--- a/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionIterator.java
+++ b/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionIterator.java
@@ -26,6 +26,7 @@ import java.util.Iterator;
 import java.util.List;
 
 import net.i2p.I2PAppContext;
+import net.i2p.client.naming.HostTxtEntry;
 import net.i2p.util.PortMapper;
 
 /**
diff --git a/apps/addressbook/java/src/net/i2p/addressbook/HostTxtEntry.java b/core/java/src/net/i2p/client/naming/HostTxtEntry.java
similarity index 98%
rename from apps/addressbook/java/src/net/i2p/addressbook/HostTxtEntry.java
rename to core/java/src/net/i2p/client/naming/HostTxtEntry.java
index fe19277068d744c47cd7a73ea0581b9bcbb5d5ca..f510b03d7879d259ea752e68149344f5a8d124e2 100644
--- a/apps/addressbook/java/src/net/i2p/addressbook/HostTxtEntry.java
+++ b/core/java/src/net/i2p/client/naming/HostTxtEntry.java
@@ -1,4 +1,4 @@
-package net.i2p.addressbook;
+package net.i2p.client.naming;
 
 import java.io.BufferedWriter;
 import java.io.IOException;
@@ -13,25 +13,27 @@ import net.i2p.data.DataFormatException;
 import net.i2p.data.DataHelper;
 import net.i2p.data.Destination;
 import net.i2p.data.Signature;
+import net.i2p.data.SigningPrivateKey;
 import net.i2p.data.SigningPublicKey;
 import net.i2p.util.OrderedProperties;
 // for testing only
 import java.io.File;
 import java.io.OutputStreamWriter;
-import java.io.StringWriter;
 import java.util.Arrays;
 import net.i2p.data.Base32;
 import net.i2p.data.PrivateKeyFile;
-import net.i2p.data.SigningPrivateKey;
 import net.i2p.util.RandomSource;
 
 
 /**
  * A hostname, b64 destination, and optional properties.
+ * Includes methods to sign and verify the entry.
+ * Used by addressbook to parse subscription data,
+ * and by i2ptunnel to generate signed metadata.
  * 
  * @since 0.9.26
  */
-class HostTxtEntry {
+public class HostTxtEntry {
 
     private final String name;
     private final String dest;
@@ -344,7 +346,6 @@ class HostTxtEntry {
 
     /**
      * Sign and set the "sig" property
-     * for testing only
      */
     private void sign(SigningPrivateKey spk) {
         signIt(spk, PROP_SIG);
@@ -352,7 +353,6 @@ class HostTxtEntry {
 
     /**
      * Sign and set the "oldsig" property
-     * for testing only
      */
     private void signInner(SigningPrivateKey spk) {
         signIt(spk, PROP_OLDSIG);
@@ -383,7 +383,6 @@ class HostTxtEntry {
     }
 
     /**
-     * for testing only
      * @param sigprop The signature property to set
      */
     private void signIt(SigningPrivateKey spk, String sigprop) {
diff --git a/core/java/src/net/i2p/client/naming/SingleFileNamingService.java b/core/java/src/net/i2p/client/naming/SingleFileNamingService.java
index 5f69b919f50041124bd82301ca66f85fc642843e..4eb2536fb27636829a7667e88312de22b6f057d3 100644
--- a/core/java/src/net/i2p/client/naming/SingleFileNamingService.java
+++ b/core/java/src/net/i2p/client/naming/SingleFileNamingService.java
@@ -59,10 +59,6 @@ public class SingleFileNamingService extends NamingService {
     private long _lastWrite;
     private volatile boolean _isClosed;
 
-    private static final String RCVD_PROP_PREFIX = "=";
-    private static final String PROPS_SEPARATOR = "#!";
-    private static final char PROP_SEPARATOR = '#';
-
     public SingleFileNamingService(I2PAppContext context, String filename) {
         super(context);
         File file = new File(filename);
@@ -267,7 +263,7 @@ public class SingleFileNamingService extends NamingService {
     }
 
     /** 
-     *  Write the subscription options part of the line (after the #!).
+     *  Write the subscription options part of the line (including the #!).
      *  Only options starting with '=' (if any) are written (with the '=' stripped).
      *  Does not write a newline.
      *
@@ -278,15 +274,15 @@ public class SingleFileNamingService extends NamingService {
         boolean started = false;
         for (Map.Entry<Object, Object> e : options.entrySet()) {
             String k = (String) e.getKey();
-            if (!k.startsWith(RCVD_PROP_PREFIX))
+            if (!k.startsWith("="))
                 continue;
             k = k.substring(1);
             String v = (String) e.getValue();
             if (started) {
-                out.write(PROP_SEPARATOR);
+                out.write(HostTxtEntry.PROP_SEPARATOR);
             } else {
                 started = true;
-                out.write(PROPS_SEPARATOR);
+                out.write(HostTxtEntry.PROPS_SEPARATOR);
             }
             out.write(k);
             out.write('=');