diff --git a/core/java/src/net/i2p/I2PAppContext.java b/core/java/src/net/i2p/I2PAppContext.java
index 025378d8c41985c4f883e51edfb45cd7952bf65f..86c1dc907e53c18f8cd732d990e80332dd0c7846 100644
--- a/core/java/src/net/i2p/I2PAppContext.java
+++ b/core/java/src/net/i2p/I2PAppContext.java
@@ -388,9 +388,13 @@ public class I2PAppContext {
      * The session key manager which coordinates the sessionKey / sessionTag
      * data.  This component allows transparent operation of the 
      * ElGamal/AES+SessionTag algorithm, and contains all of the session tags
-     * for one particular application.  If you want to seperate multiple apps
-     * to have their own sessionTags and sessionKeys, they should use different
-     * I2PAppContexts, and hence, different sessionKeyManagers.
+     * for one particular application.
+     *
+     * This is deprecated for client use, it should be used only by the router
+     * as its own key manager. Not that clients are doing end-to-end crypto anyway.
+     *
+     * For client crypto within the router,
+     * use RouterContext.clientManager.getClientSessionKeyManager(dest)
      *
      */
     public SessionKeyManager sessionKeyManager() { 
diff --git a/core/java/src/net/i2p/crypto/ElGamalAESEngine.java b/core/java/src/net/i2p/crypto/ElGamalAESEngine.java
index 3e191faaa4d6f335021dfcad87830e3b000e1a30..98e9e62cc4134b1c6455830c9394dfae96c3d276 100644
--- a/core/java/src/net/i2p/crypto/ElGamalAESEngine.java
+++ b/core/java/src/net/i2p/crypto/ElGamalAESEngine.java
@@ -59,14 +59,18 @@ public class ElGamalAESEngine {
     }
 
     /**
-     * Decrypt the message using the given private key using tags from the given key manager.
+     * Decrypt the message using the given private key using tags from the default key manager.
+     *
+     * @deprecated specify the key manager!
      */
     public byte[] decrypt(byte data[], PrivateKey targetPrivateKey) throws DataFormatException {
         return decrypt(data, targetPrivateKey, _context.sessionKeyManager());
     }
 
     /**
-     * Decrypt the message using the given private key.  This works according to the
+     * Decrypt the message using the given private key
+     * and using tags from the specified key manager.
+     * This works according to the
      * ElGamal+AES algorithm in the data structure spec.
      *
      */
diff --git a/core/java/src/net/i2p/data/SessionKey.java b/core/java/src/net/i2p/data/SessionKey.java
index 1b2ae8a1e018265caec46458d3d1ad1679204b70..17190ef3f0018898c56070a5ec4b5ed32feb9ad0 100644
--- a/core/java/src/net/i2p/data/SessionKey.java
+++ b/core/java/src/net/i2p/data/SessionKey.java
@@ -89,6 +89,8 @@ public class SessionKey extends DataStructureImpl {
 
     @Override
     public String toString() { 
+        return "SessionKey " + toBase64();
+      /****
         if (true) return super.toString(); 
         StringBuilder buf = new StringBuilder(64);
         buf.append("[SessionKey: ");
@@ -103,5 +105,6 @@ public class SessionKey extends DataStructureImpl {
         }
         buf.append("]");
         return buf.toString();
+      ****/
     }
 }
diff --git a/core/java/src/net/i2p/data/SessionTag.java b/core/java/src/net/i2p/data/SessionTag.java
index 54826e7e3f057fcfcd4ec31bf75a1475f701526d..d50b392b49c902d789788f74d1ebed7c42143539 100644
--- a/core/java/src/net/i2p/data/SessionTag.java
+++ b/core/java/src/net/i2p/data/SessionTag.java
@@ -58,4 +58,8 @@ public class SessionTag extends ByteArray {
         out.write(getData());
     }
 
-}
\ No newline at end of file
+    @Override
+    public String toString() {
+        return "SessionTag " + toBase64();
+    }
+}
diff --git a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java
index 90c7fe23bf6b1c69265adf3afcf43288916bdbe3..e5aa1b5abb4d2a9af84ff6f2d6a57c2178581ed5 100644
--- a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java
+++ b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java
@@ -18,6 +18,7 @@ import java.util.Map;
 import java.util.Set;
 
 import net.i2p.crypto.SessionKeyManager;
+import net.i2p.crypto.TransientSessionKeyManager;
 import net.i2p.data.Destination;
 import net.i2p.data.Hash;
 import net.i2p.data.LeaseSet;
@@ -188,11 +189,11 @@ public class ClientConnectionRunner {
         if (_log.shouldLog(Log.DEBUG))
             _log.debug("SessionEstablished called for destination " + _destHashCache.toBase64());
         _config = config;
-        // per-dest unimplemented
-        //if (_sessionKeyManager == null)
-        //    _sessionKeyManager = new TransientSessionKeyManager(_context);
-        //else
-        //    _log.error("SessionEstablished called for twice for destination " + _destHashCache.toBase64().substring(0,4));
+        // per-destination session key manager to prevent rather easy correlation
+        if (_sessionKeyManager == null)
+            _sessionKeyManager = new TransientSessionKeyManager(_context);
+        else
+            _log.error("SessionEstablished called for twice for destination " + _destHashCache.toBase64().substring(0,4));
         _manager.destinationEstablished(this);
     }
     
diff --git a/router/java/src/net/i2p/router/tunnel/pool/TestJob.java b/router/java/src/net/i2p/router/tunnel/pool/TestJob.java
index fc79c87f2589c00f0b0c4aaa4310f680d9892357..478ea4d6ee62891e377172e9512968b289d4f75c 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/TestJob.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/TestJob.java
@@ -28,6 +28,8 @@ class TestJob extends JobImpl {
     private TunnelInfo _outTunnel;
     private TunnelInfo _replyTunnel;
     private PooledTunnelCreatorConfig _otherTunnel;
+    /** save this so we can tell the SKM to kill it if the test fails */
+    private SessionTag _encryptTag;
     
     /** base to randomize the test delay on */
     private static final int TEST_DELAY = 30*1000;
@@ -128,12 +130,12 @@ class TestJob extends JobImpl {
         payload.setExpiration(m.getMessageExpiration());
 
         SessionKey encryptKey = getContext().keyGenerator().generateSessionKey();
-        SessionTag encryptTag = new SessionTag(true);
+        _encryptTag = new SessionTag(true);
         SessionKey sentKey = new SessionKey();
         Set sentTags = null;
         GarlicMessage msg = GarlicMessageBuilder.buildMessage(getContext(), payload, sentKey, sentTags, 
                                                               getContext().keyManager().getPublicKey(), 
-                                                              encryptKey, encryptTag);
+                                                              encryptKey, _encryptTag);
 
         if (msg == null) {
             // overloaded / unknown peers / etc
@@ -141,7 +143,8 @@ class TestJob extends JobImpl {
             return;
         }
         Set encryptTags = new HashSet(1);
-        encryptTags.add(encryptTag);
+        encryptTags.add(_encryptTag);
+        // Register the single tag with the SKM
         getContext().sessionKeyManager().tagsReceived(encryptKey, encryptTags);
 
         if (_log.shouldLog(Log.DEBUG))
@@ -307,8 +310,11 @@ class TestJob extends JobImpl {
         public void runJob() {
             if (_log.shouldLog(Log.WARN))
                 _log.warn("Timeout: found? " + _found, getAddedBy());
-            if (!_found)
+            if (!_found) {
+                // don't clog up the SKM with old one-tag tagsets
+                getContext().sessionKeyManager().consumeTag(_encryptTag);
                 testFailed(getContext().clock().now() - _started);
+            }
         }
         
         @Override