diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java
index 2b269e6665e9f59c2d128994228591683be3afed..0b06c1ef91ce1c039081b96cb19290d96056e33e 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java
@@ -1223,7 +1223,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
     }
 
     /**
-     * Generate a new keypair
+     * Generate a new keypair.
+     * Does NOT support non-default sig types.
      * Deprecated - only used by CLI
      *
      * Sets the event "genkeysResult" = "ok" or "error" after the generation is complete
@@ -1266,7 +1267,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
     }
 
     /**
-     * Generate a new keypair
+     * Generate a new keypair.
+     * Does NOT support non-default sig types.
      * Deprecated - only used by CLI
      *
      * Sets the event "privateKey" = base64 of the privateKey stream and
@@ -1275,7 +1277,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
      * @param l logger to receive events and output
      */
     private static void runGenTextKeys(Logging l) {
-        ByteArrayOutputStream privkey = new ByteArrayOutputStream(512);
+        ByteArrayOutputStream privkey = new ByteArrayOutputStream(1024);
         ByteArrayOutputStream pubkey = new ByteArrayOutputStream(512);
         makeKey(privkey, pubkey, l);
         l.log("Private key: " + Base64.encode(privkey.toByteArray()));
@@ -1527,10 +1529,11 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
 
     /**
      * Create a new destination, storing the destination and its private keys where 
-     * instructed
+     * instructed.
+     * Does NOT support non-default sig types.
      * Deprecated - only used by CLI
      *
-     * @param writeTo location to store the private keys
+     * @param writeTo location to store the destination and private keys
      * @param pubDest location to store the destination
      * @param l logger to send messages to
      */
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java
index 1b1fdefcfabf14576c874702e68ae93e5f56d407..5936b6936fcd01aaeeec76f8f1b799c034357c49 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java
@@ -7,11 +7,13 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+
 import net.i2p.I2PAppContext;
 import net.i2p.I2PException;
 import net.i2p.client.I2PClient;
 import net.i2p.client.I2PClientFactory;
 import net.i2p.client.I2PSession;
+import net.i2p.crypto.SigType;
 import net.i2p.data.Base32;
 import net.i2p.data.Destination;
 import net.i2p.i2ptunnel.socks.I2PSOCKSTunnel;
@@ -49,8 +51,8 @@ public class TunnelController implements Logging {
      * the prefix should be used (and, in turn, that prefix should be stripped off
      * before being interpreted by this controller)
      * 
-     * @param config original key=value mapping
-     * @param prefix beginning of key values that are relevent to this tunnel
+     * @param config original key=value mapping non-null
+     * @param prefix beginning of key values that are relevant to this tunnel
      */
     public TunnelController(Properties config, String prefix) {
         this(config, prefix, true);
@@ -58,6 +60,8 @@ public class TunnelController implements Logging {
 
     /**
      * 
+     * @param config original key=value mapping non-null
+     * @param prefix beginning of key values that are relevant to this tunnel
      * @param createKey for servers, whether we want to create a brand new destination
      *                  with private keys at the location specified or not (does not
      *                  overwrite existing ones)
@@ -99,7 +103,16 @@ public class TunnelController implements Logging {
         FileOutputStream fos = null;
         try {
             fos = new SecureFileOutputStream(keyFile);
-            Destination dest = client.createDestination(fos);
+            SigType stype = I2PClient.DEFAULT_SIGTYPE;
+            String st = _config.getProperty("option." + I2PClient.PROP_SIGTYPE);
+            if (st != null) {
+                SigType type = SigType.parseSigType(st);
+                if (type != null)
+                    stype = type;
+                else
+                    log("Unsupported sig type " + st);
+            }
+            Destination dest = client.createDestination(fos, stype);
             String destStr = dest.toBase64();
             log("Private key created and saved in " + keyFile.getAbsolutePath());
             log("You should backup this file in a secure place.");
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPClientBase.java
index 425cfb9ca2c089e7419c59a5594379f346aec81d..f1e8abaabeb88adb3eb4931c1b151eb4626c8fb1 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPClientBase.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPClientBase.java
@@ -12,6 +12,7 @@ import net.i2p.client.I2PClient;
 import net.i2p.client.I2PClientFactory;
 import net.i2p.client.I2PSession;
 import net.i2p.client.I2PSessionException;
+import net.i2p.crypto.SigType;
 import net.i2p.data.Destination;
 import net.i2p.i2ptunnel.I2PTunnel;
 import net.i2p.i2ptunnel.I2PTunnelTask;
@@ -78,8 +79,17 @@ import net.i2p.util.EventDispatcher;
         I2PClient client = I2PClientFactory.createClient();
         byte[] key;
         try {
-            ByteArrayOutputStream out = new ByteArrayOutputStream(512);
-            client.createDestination(out);
+            ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
+            SigType stype = I2PClient.DEFAULT_SIGTYPE;
+            String st = tunnel.getClientOptions().getProperty(I2PClient.PROP_SIGTYPE);
+            if (st != null) {
+                SigType type = SigType.parseSigType(st);
+                if (type != null)
+                    stype = type;
+                else
+                    l.log("Unsupported sig type " + st);
+            }
+            client.createDestination(out, stype);
             key = out.toByteArray();
         } catch(Exception exc) {
             throw new RuntimeException("failed to create i2p-destination", exc);
diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerFactory.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerFactory.java
index ebfb0c707f0fb86ff4fa4c6edf7d8b808588d975..493a0d272622465d4b0f0004b5100612ca643ece 100644
--- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerFactory.java
+++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerFactory.java
@@ -14,6 +14,7 @@ import net.i2p.client.I2PClient;
 import net.i2p.client.I2PClientFactory;
 import net.i2p.client.I2PSession;
 import net.i2p.client.I2PSessionException;
+import net.i2p.crypto.SigType;
 import net.i2p.util.Log;
 
 /**
@@ -26,7 +27,7 @@ public class I2PSocketManagerFactory {
 
     public static final String PROP_MANAGER = "i2p.streaming.manager";
     public static final String DEFAULT_MANAGER = "net.i2p.client.streaming.I2PSocketManagerFull";
-    
+
     /**
      * Create a socket manager using a brand new destination connected to the
      * I2CP router on the local machine on the default port (7654).
@@ -79,9 +80,9 @@ public class I2PSocketManagerFactory {
      */
     public static I2PSocketManager createManager(String i2cpHost, int i2cpPort, Properties opts) {
         I2PClient client = I2PClientFactory.createClient();
-        ByteArrayOutputStream keyStream = new ByteArrayOutputStream(512);
+        ByteArrayOutputStream keyStream = new ByteArrayOutputStream(1024);
         try {
-            client.createDestination(keyStream);
+            client.createDestination(keyStream, getSigType(opts));
             ByteArrayInputStream in = new ByteArrayInputStream(keyStream.toByteArray());
             return createManager(in, i2cpHost, i2cpPort, opts);
         } catch (IOException ioe) {
@@ -168,9 +169,9 @@ public class I2PSocketManagerFactory {
                                                              int i2cpPort, Properties opts) throws I2PSessionException {
         if (myPrivateKeyStream == null) {
             I2PClient client = I2PClientFactory.createClient();
-            ByteArrayOutputStream keyStream = new ByteArrayOutputStream(512);
+            ByteArrayOutputStream keyStream = new ByteArrayOutputStream(1024);
             try {
-                client.createDestination(keyStream);
+                client.createDestination(keyStream, getSigType(opts));
             } catch (Exception e) {
                 throw new I2PSessionException("Error creating keys", e);
             }
@@ -257,6 +258,23 @@ public class I2PSocketManagerFactory {
         return i2cpPort;
     }
 
+    /**
+     *  @param opts may be null
+     *  @since 0.9.11
+     */
+    private static SigType getSigType(Properties opts) {
+        if (opts != null) {
+            String st = opts.getProperty(I2PClient.PROP_SIGTYPE);
+            if (st != null) {
+                SigType rv = SigType.parseSigType(st);
+                if (rv != null)
+                    return rv;
+                getLog().error("Unsupported sig type " + st);
+            }
+        }
+        return I2PClient.DEFAULT_SIGTYPE;
+    }
+
     /** @since 0.9.7 */
     private static Log getLog() {
         return I2PAppContext.getGlobalContext().logManager().getLog(I2PSocketManagerFactory.class);
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/Packet.java b/apps/streaming/java/src/net/i2p/client/streaming/Packet.java
index 1ecdc0771b6cb01f8e3cac49f1e35cfd440fd267..411e66105951a43d6ce2e4f3519d78f6de9ebcde 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/Packet.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/Packet.java
@@ -397,13 +397,14 @@ class Packet {
      * @throws IllegalStateException if there is data missing or otherwise b0rked
      */
     public int writePacket(byte buffer[], int offset) throws IllegalStateException {
-        return writePacket(buffer, offset, true);
+        return writePacket(buffer, offset, 0);
     }
+
     /**
-     * @param includeSig if true, include the real signature, otherwise put zeroes
-     *                   in its place.
+     * @param fakeSigLen if 0, include the real signature in _optionSignature;
+     *                   if nonzero, leave space for that many bytes
      */
-    private int writePacket(byte buffer[], int offset, boolean includeSig) throws IllegalStateException {
+    private int writePacket(byte buffer[], int offset, int fakeSigLen) throws IllegalStateException {
         int cur = offset;
         DataHelper.toLong(buffer, cur, 4, (_sendStreamId >= 0 ? _sendStreamId : STREAM_ID_UNKNOWN));
         cur += 4;
@@ -438,7 +439,12 @@ class Packet {
         if (isFlagSet(FLAG_MAX_PACKET_SIZE_INCLUDED))
             optionSize += 2;
         if (isFlagSet(FLAG_SIGNATURE_INCLUDED)) {
-            optionSize += _optionSignature.length();
+            if (fakeSigLen > 0)
+                optionSize += fakeSigLen;
+            else if (_optionSignature != null)
+                optionSize += _optionSignature.length();
+            else
+                throw new IllegalStateException();
         }
         
         DataHelper.toLong(buffer, cur, 2, optionSize);
@@ -456,11 +462,14 @@ class Packet {
             cur += 2;
         }
         if (isFlagSet(FLAG_SIGNATURE_INCLUDED)) {
-            if (includeSig)
+            if (fakeSigLen == 0) {
+                // we're signing (or validating)
                 System.arraycopy(_optionSignature.getData(), 0, buffer, cur, _optionSignature.length());
-            else // we're signing (or validating)
-                Arrays.fill(buffer, cur, cur + _optionSignature.length(), (byte)0x0);
-            cur += _optionSignature.length();
+                cur += _optionSignature.length();
+            } else {
+                Arrays.fill(buffer, cur, cur + fakeSigLen, (byte)0x0);
+                cur += fakeSigLen;
+            }
         }
         
         if (_payload != null) {
@@ -661,7 +670,7 @@ class Packet {
         
         if (buffer == null)
             buffer = new byte[size];
-        int written = writePacket(buffer, 0, false);
+        int written = writePacket(buffer, 0, from.getSigningPublicKey().getType().getSigLen());
         if (written != size) {
             ctx.logManager().getLog(Packet.class).error("Written " + written + " size " + size + " for " + toString(), new Exception("moo"));
             return false;
@@ -692,7 +701,7 @@ class Packet {
      */
     public int writeSignedPacket(byte buffer[], int offset, I2PAppContext ctx, SigningPrivateKey key) throws IllegalStateException {
         setFlag(FLAG_SIGNATURE_INCLUDED);
-        int size = writePacket(buffer, offset, false);
+        int size = writePacket(buffer, offset, key.getType().getSigLen());
         _optionSignature = ctx.dsa().sign(buffer, offset, size, key);
         //if (false) {
         //    Log l = ctx.logManager().getLog(Packet.class);
@@ -760,7 +769,7 @@ class Packet {
         if (isFlagSet(FLAG_CLOSE)) buf.append(" CLOSE");
         if (isFlagSet(FLAG_DELAY_REQUESTED)) buf.append(" DELAY ").append(_optionDelay);
         if (isFlagSet(FLAG_ECHO)) buf.append(" ECHO");
-        if (isFlagSet(FLAG_FROM_INCLUDED)) buf.append(" FROM");
+        if (isFlagSet(FLAG_FROM_INCLUDED)) buf.append(" FROM ").append(_optionFrom.size());
         if (isFlagSet(FLAG_MAX_PACKET_SIZE_INCLUDED)) buf.append(" MS ").append(_optionMaxSize);
         if (isFlagSet(FLAG_PROFILE_INTERACTIVE)) buf.append(" INTERACTIVE");
         if (isFlagSet(FLAG_RESET)) buf.append(" RESET");
diff --git a/core/java/src/net/i2p/client/I2PClient.java b/core/java/src/net/i2p/client/I2PClient.java
index 84bcf50d2af68c8215124d89f52f7d6f1935f76f..bbfd6811aeaae96e992a09f04fd9287ca396a91f 100644
--- a/core/java/src/net/i2p/client/I2PClient.java
+++ b/core/java/src/net/i2p/client/I2PClient.java
@@ -41,6 +41,11 @@ public interface I2PClient {
     /** @since 0.8.1 */
     public final static String PROP_RELIABILITY_NONE = "none";
 
+    /** @since 0.9.11 */
+    public static final String PROP_SIGTYPE = "i2cp.destination.sigType";
+    /** @since 0.9.11 */
+    public static final SigType DEFAULT_SIGTYPE = SigType.DSA_SHA1;
+
     /**
      * For router->client payloads.
      *
diff --git a/core/java/src/net/i2p/client/I2PClientImpl.java b/core/java/src/net/i2p/client/I2PClientImpl.java
index 7fac17e10d7532508ddaf2a91c7f1ca145022c3d..e29cdc342658ea1eaebc72112a0aca3122b7fc9e 100644
--- a/core/java/src/net/i2p/client/I2PClientImpl.java
+++ b/core/java/src/net/i2p/client/I2PClientImpl.java
@@ -47,7 +47,7 @@ class I2PClientImpl implements I2PClient {
      *                      format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
      */
     public Destination createDestination(OutputStream destKeyStream) throws I2PException, IOException {
-        return createDestination(destKeyStream, SigType.DSA_SHA1);
+        return createDestination(destKeyStream, DEFAULT_SIGTYPE);
     }
 
     /**
diff --git a/core/java/src/net/i2p/crypto/DSAEngine.java b/core/java/src/net/i2p/crypto/DSAEngine.java
index dce8843e624b80004ccc8dde4123dc9ae3db1135..16c63e8ea9e7b46efcfa49b75515423c02fbb879 100644
--- a/core/java/src/net/i2p/crypto/DSAEngine.java
+++ b/core/java/src/net/i2p/crypto/DSAEngine.java
@@ -89,13 +89,20 @@ public class DSAEngine {
      *  Uses TheCrypto code for DSA-SHA1 unless configured to use the java.security libraries.
      */
     public boolean verifySignature(Signature signature, byte signedData[], SigningPublicKey verifyingKey) {
+        return verifySignature(signature, signedData, 0, signedData.length, verifyingKey);
+    }
+
+    /**
+     *  Verify using any sig type as of 0.9.11 (DSA only prior to that)
+     */
+    public boolean verifySignature(Signature signature, byte signedData[], int offset, int size, SigningPublicKey verifyingKey) {
         boolean rv;
         SigType type = signature.getType();
         if (type != verifyingKey.getType())
             throw new IllegalArgumentException("type mismatch sig=" + signature.getType() + " key=" + verifyingKey.getType());
         if (type != SigType.DSA_SHA1) {
             try {
-                rv = altVerifySig(signature, signedData, verifyingKey);
+                rv = altVerifySig(signature, signedData, offset, size, verifyingKey);
                 if ((!rv) && _log.shouldLog(Log.WARN))
                     _log.warn(type + " Sig Verify Fail");
                 return rv;
@@ -107,7 +114,7 @@ public class DSAEngine {
         }
         if (_useJavaLibs) {
             try {
-                rv = altVerifySigSHA1(signature, signedData, verifyingKey);
+                rv = altVerifySigSHA1(signature, signedData, offset, size, verifyingKey);
                 if ((!rv) && _log.shouldLog(Log.WARN))
                     _log.warn("Lib DSA Sig Verify Fail");
                 return rv;
@@ -117,19 +124,12 @@ public class DSAEngine {
                 // now try TheCrypto
             }
         }
-        rv = verifySignature(signature, signedData, 0, signedData.length, verifyingKey);
+        rv = verifySignature(signature, calculateHash(signedData, offset, size), verifyingKey);
         if ((!rv) && _log.shouldLog(Log.WARN))
             _log.warn("TheCrypto DSA Sig Verify Fail");
         return rv;
     }
 
-    /**
-     *  Verify using DSA-SHA1 ONLY
-     */
-    public boolean verifySignature(Signature signature, byte signedData[], int offset, int size, SigningPublicKey verifyingKey) {
-        return verifySignature(signature, calculateHash(signedData, offset, size), verifyingKey);
-    }
-
     /**
      *  Verify using DSA-SHA1 ONLY
      */
@@ -256,16 +256,26 @@ public class DSAEngine {
     }
 
     /**
-     *  Sign using DSA-SHA1 or ECDSA.
+     *  Sign using any key type.
      *  Uses TheCrypto code unless configured to use the java.security libraries.
      *
      *  @return null on error
      */
     public Signature sign(byte data[], SigningPrivateKey signingKey) {
+        return sign(data, 0, data.length, signingKey);
+    }
+
+    /**
+     *  Sign using any key type as of 0.9.11 (DSA-SHA1 only prior to that)
+     *
+     *  @return null on error
+     */
+    public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) {
+        if ((signingKey == null) || (data == null) || (data.length <= 0)) return null;
         SigType type = signingKey.getType();
         if (type != SigType.DSA_SHA1) {
             try {
-                return altSign(data, signingKey);
+                return altSign(data, offset, length, signingKey);
             } catch (GeneralSecurityException gse) {
                 if (_log.shouldLog(Log.WARN))
                     _log.warn(type + " Sign Fail", gse);
@@ -274,23 +284,13 @@ public class DSAEngine {
         }
         if (_useJavaLibs) {
             try {
-                return altSignSHA1(data, signingKey);
+                return altSignSHA1(data, offset, length, signingKey);
             } catch (GeneralSecurityException gse) {
                 if (_log.shouldLog(Log.WARN))
                     _log.warn("Lib Sign Fail, privkey = " + signingKey, gse);
                 // now try TheCrypto
             }
         }
-        return sign(data, 0, data.length, signingKey);
-    }
-
-    /**
-     *  Sign using DSA-SHA1 ONLY
-     *
-     *  @return null on error
-     */
-    public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) {
-        if ((signingKey == null) || (data == null) || (data.length <= 0)) return null;
         SHA1Hash h = calculateHash(data, offset, length);
         return sign(h, signingKey);
     }
@@ -495,20 +495,20 @@ public class DSAEngine {
     /**
      *  Generic verify DSA_SHA1, ECDSA, or RSA
      *  @throws GeneralSecurityException if algorithm unvailable or on other errors
-     *  @since 0.9.9
+     *  @since 0.9.9 added off/len 0.9.11
      */
-    private boolean altVerifySig(Signature signature, byte[] data, SigningPublicKey verifyingKey)
+    private boolean altVerifySig(Signature signature, byte[] data, int offset, int len, SigningPublicKey verifyingKey)
                         throws GeneralSecurityException {
         SigType type = signature.getType();
         if (type != verifyingKey.getType())
             throw new IllegalArgumentException("type mismatch sig=" + type + " key=" + verifyingKey.getType());
         if (type == SigType.DSA_SHA1)
-            return altVerifySigSHA1(signature, data, verifyingKey);
+            return altVerifySigSHA1(signature, data, offset, len, verifyingKey);
 
         java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
         PublicKey pubKey = SigUtil.toJavaKey(verifyingKey);
         jsig.initVerify(pubKey);
-        jsig.update(data);
+        jsig.update(data, offset, len);
         boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
         return rv;
     }
@@ -555,13 +555,14 @@ public class DSAEngine {
     /**
      *  Alternate to verifySignature() using java.security libraries.
      *  @throws GeneralSecurityException if algorithm unvailable or on other errors
-     *  @since 0.8.7
+     *  @since 0.8.7 added off/len 0.9.11
      */
-    private boolean altVerifySigSHA1(Signature signature, byte[] data, SigningPublicKey verifyingKey) throws GeneralSecurityException {
+    private boolean altVerifySigSHA1(Signature signature, byte[] data, int offset,
+                                     int len, SigningPublicKey verifyingKey) throws GeneralSecurityException {
         java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
         PublicKey pubKey = SigUtil.toJavaDSAKey(verifyingKey);
         jsig.initVerify(pubKey);
-        jsig.update(data);
+        jsig.update(data, offset, len);
         boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
         //if (!rv) {
         //    System.out.println("BAD SIG\n" + net.i2p.util.HexDump.dump(signature.getData()));
@@ -573,17 +574,18 @@ public class DSAEngine {
     /**
      *  Generic sign DSA_SHA1, ECDSA, or RSA
      *  @throws GeneralSecurityException if algorithm unvailable or on other errors
-     *  @since 0.9.9
+     *  @since 0.9.9 added off/len 0.9.11
      */
-    private Signature altSign(byte[] data, SigningPrivateKey privateKey) throws GeneralSecurityException {
+    private Signature altSign(byte[] data, int offset, int len,
+                              SigningPrivateKey privateKey) throws GeneralSecurityException {
         SigType type = privateKey.getType();
         if (type == SigType.DSA_SHA1)
-            return altSignSHA1(data, privateKey);
+            return altSignSHA1(data, offset, len, privateKey);
 
         java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
         PrivateKey privKey = SigUtil.toJavaKey(privateKey);
         jsig.initSign(privKey, _context.random());
-        jsig.update(data);
+        jsig.update(data, offset, len);
         return SigUtil.fromJavaSig(jsig.sign(), type);
     }
 
@@ -622,13 +624,14 @@ public class DSAEngine {
     /**
      *  Alternate to sign() using java.security libraries.
      *  @throws GeneralSecurityException if algorithm unvailable or on other errors
-     *  @since 0.8.7
+     *  @since 0.8.7 added off/len args 0.9.11
      */
-    private Signature altSignSHA1(byte[] data, SigningPrivateKey privateKey) throws GeneralSecurityException {
+    private Signature altSignSHA1(byte[] data, int offset, int len,
+                                  SigningPrivateKey privateKey) throws GeneralSecurityException {
         java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
         PrivateKey privKey = SigUtil.toJavaDSAKey(privateKey);
         jsig.initSign(privKey, _context.random());
-        jsig.update(data);
+        jsig.update(data, offset, len);
         return SigUtil.fromJavaSig(jsig.sign(), SigType.DSA_SHA1);
     }
 
diff --git a/core/java/src/net/i2p/data/Destination.java b/core/java/src/net/i2p/data/Destination.java
index 4d8affc870570310a5a0e0302902b7cb296aa3a1..7268be640c71062b4bbf8e243c5de3a218f595ed 100644
--- a/core/java/src/net/i2p/data/Destination.java
+++ b/core/java/src/net/i2p/data/Destination.java
@@ -57,6 +57,16 @@ public class Destination extends KeysAndCert {
         PublicKey pk = PublicKey.create(in);
         SigningPublicKey sk = SigningPublicKey.create(in);
         Certificate c = Certificate.create(in);
+        byte[] padding;
+        if (c.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
+            // convert SPK to new SPK and padding
+            KeyCertificate kcert = c.toKeyCertificate();
+            padding = sk.getPadding(kcert);
+            sk = sk.toTypedKey(kcert);
+            c = kcert;
+        } else {
+            padding = null;
+        }
         Destination rv;
         synchronized(_cache) {
             rv = _cache.get(sk);
@@ -67,7 +77,7 @@ public class Destination extends KeysAndCert {
             }
             //if (STATS)
             //    I2PAppContext.getGlobalContext().statManager().addRateData("DestCache", 0);
-            rv = new Destination(pk, sk, c);
+            rv = new Destination(pk, sk, c, padding);
             _cache.put(sk, rv);
         }
         return rv;
@@ -86,10 +96,11 @@ public class Destination extends KeysAndCert {
     /**
      * @since 0.9.9
      */
-    private Destination(PublicKey pk, SigningPublicKey sk, Certificate c) {
+    private Destination(PublicKey pk, SigningPublicKey sk, Certificate c, byte[] padding) {
         _publicKey = pk;
         _signingKey = sk;
         _certificate = c;
+        _padding = padding;
     }
 
     /**
@@ -138,7 +149,16 @@ public class Destination extends KeysAndCert {
 ****/
 
     public int size() {
-        return PublicKey.KEYSIZE_BYTES + _signingKey.length() + _certificate.size();
+        int rv = PublicKey.KEYSIZE_BYTES + _signingKey.length();
+        if (_certificate.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
+            // cert data included in keys
+            rv += 7;
+            if (_padding != null)
+                rv += _padding.length;
+        } else {
+            rv += _certificate.size();
+        }
+        return rv;
     }
 
     /**