diff --git a/Cargo.toml b/Cargo.toml
index ffef7cb801a232da512f9bc8db16c09ec5687b43..e9a518af1bbb00402d1d4d1f412373b2a61fb713 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,7 +14,7 @@ members = [
 
 [profile.release]
 opt-level = 's'
-# lto = "fat"
+lto = "fat"
 debug = 1
 
 [patch."https://github.com/mkj/ed25519-dalek"]
diff --git a/sshproto/src/cliauth.rs b/sshproto/src/cliauth.rs
index fbdb977249b9bacf8069f68714c3fd49af5ebf61..421105216f179faff89936ac12221c4a61684c86 100644
--- a/sshproto/src/cliauth.rs
+++ b/sshproto/src/cliauth.rs
@@ -14,7 +14,7 @@ use crate::{packets::UserauthPkOk, *};
 use behaviour::CliBehaviour;
 use client::*;
 use conn::RespPackets;
-use packets::{AuthMethod, MethodPubKey, ParseContext, UserauthRequest};
+use packets::{MessageNumber, AuthMethod, MethodPubKey, ParseContext, UserauthRequest};
 use packets::{Packet, Signature, Userauth60};
 use sign::{SignKey, OwnedSig};
 use sshnames::*;
@@ -169,11 +169,12 @@ impl CliAuth {
                     sig: None,
                     signing_now: true,
                 }),
-            }.into();
+            };
 
             let msg = auth::AuthSigMsg {
                 sess_id: BinString(sess_id.as_ref()),
-                p: sig_packet,
+                msg_num: MessageNumber::SSH_MSG_USERAUTH_REQUEST as u8,
+                u: sig_packet,
             };
             key.sign_serialize(&msg)
         } else {
diff --git a/sshproto/src/kex.rs b/sshproto/src/kex.rs
index 24d4c2cad68a4170052f2bff60ae2e6006809b36..a5f17e334ae7a0fbc5a24c6d154cdf6387c275f6 100644
--- a/sshproto/src/kex.rs
+++ b/sshproto/src/kex.rs
@@ -20,7 +20,8 @@ use namelist::LocalNames;
 use packets::{Packet, PubKey, Signature};
 use sign::SigType;
 use sshnames::*;
-use wireformat::{hash_mpint, hash_ser, hash_ser_length, BinString, Blob};
+use wireformat::{hash_mpint, BinString, Blob};
+use sshwire::{hash_ser, hash_ser_length};
 use behaviour::{CliBehaviour, Behaviour, ServBehaviour};
 
 // at present we only have curve25519 with sha256
diff --git a/sshproto/src/sign.rs b/sshproto/src/sign.rs
index 9e9acc466311c494d9f415aa6a4e58b73ab4cc8a..e6e2288ee1eda82180de4195fe07efbc8367476b 100644
--- a/sshproto/src/sign.rs
+++ b/sshproto/src/sign.rs
@@ -9,10 +9,11 @@ use rand::rngs::OsRng;
 use ed25519_dalek as dalek;
 use ed25519_dalek::{Verifier, Signer};
 
-use crate::*;
+use crate::{*, packets::ParseContext};
 use sshnames::*;
 use packets::{PubKey, Signature, Ed25519PubKey};
 use wireformat::BinString;
+use sshwire::SSHEncode;
 
 use pretty_hex::PrettyHex;
 
@@ -123,12 +124,15 @@ impl SignKey {
         k.try_into()
     }
 
-    pub(crate) fn sign_serialize<'s>(&self, msg: &'s impl serde::Serialize) -> Result<OwnedSig> {
+    // pub(crate) fn sign_serialize<'s>(&self, msg: &'s impl serde::Serialize) -> Result<OwnedSig> {
+    pub(crate) fn sign_serialize<'s>(&self, msg: &'s impl SSHEncode) -> Result<OwnedSig> {
         match self {
             SignKey::Ed25519(k) => {
                 let exk: dalek::ExpandedSecretKey = (&k.secret).into();
                 exk.sign_parts(|h| {
-                    wireformat::hash_ser(h, msg).map_err(|_| dalek::SignatureError::new())
+                    let mut ctx = ParseContext::default();
+                    ctx.method_pubkey_force_sig_bool = true;
+                    sshwire::hash_ser(h, Some(&ctx), msg).map_err(|_| dalek::SignatureError::new())
                 }, &k.public)
                 .trap()
                 .map(|s| s.into())
diff --git a/sshproto/src/sshwire.rs b/sshproto/src/sshwire.rs
index bfa5e0b7c60a34aa4d7bc75f875bf3788d8f8c29..8c30c7fb5c43f814a7a4a5f20835a5ca6b47db9c 100644
--- a/sshproto/src/sshwire.rs
+++ b/sshproto/src/sshwire.rs
@@ -71,6 +71,27 @@ where
     Ok(s.pos)
 }
 
+pub fn hash_ser_length<T>(hash_ctx: &mut impl digest::DynDigest,
+    value: &T) -> Result<()>
+where
+    T: SSHEncode,
+{
+    let len = length_enc(value)? as u32;
+    hash_ctx.update(&len.to_be_bytes());
+    hash_ser(hash_ctx, None, value)
+}
+
+pub fn hash_ser<T>(hash_ctx: &mut impl digest::DynDigest,
+    parse_ctx: Option<&ParseContext>,
+    value: &T) -> Result<()>
+where
+    T: SSHEncode,
+{
+    let mut s = EncodeHash { hash_ctx, parse_ctx: parse_ctx.cloned() };
+    value.enc(&mut s)?;
+    Ok(())
+}
+
 pub fn length_enc<T>(value: &T) -> Result<usize>
 where
     T: SSHEncode,
@@ -214,7 +235,7 @@ impl<'de> SSHDecode<'de> for bool {
 
 // TODO: inline seemed to help code size in wireformat?
 impl<'de> SSHDecode<'de> for u8 {
-    #[inline]
+    // #[inline]
     fn dec<S>(s: &mut S) -> Result<Self>
     where S: SSHSource<'de> {
         let t = s.take(core::mem::size_of::<u8>())?;
@@ -223,7 +244,7 @@ impl<'de> SSHDecode<'de> for u8 {
 }
 
 impl<'de> SSHDecode<'de> for u32 {
-    #[inline]
+    // #[inline]
     fn dec<S>(s: &mut S) -> Result<Self>
     where S: SSHSource<'de> {
         let t = s.take(core::mem::size_of::<u32>())?;
@@ -232,7 +253,7 @@ impl<'de> SSHDecode<'de> for u32 {
 }
 
 impl<'de: 'a, 'a> SSHDecode<'de> for &'a str {
-    #[inline]
+    // #[inline]
     fn dec<S>(s: &mut S) -> Result<Self>
     where S: SSHSource<'de> {
         let len = u32::dec(s)?;
diff --git a/sshproto/src/traffic.rs b/sshproto/src/traffic.rs
index 0ac6679411d88d0778a1a97cace7ca3229314273..31136728a98e16c78acc53ec3d3b761a55d4982b 100644
--- a/sshproto/src/traffic.rs
+++ b/sshproto/src/traffic.rs
@@ -180,10 +180,6 @@ impl<'a> Traffic<'a> {
             _ => Err(Error::bug())?,
         };
 
-        let mut z = [0u8; 1000];
-        let qlen = wireformat::write_ssh(&mut z, &p)?;
-        trace!("old {qlen} {:?}", (&z[..qlen]).hex_dump());
-
         // Use the remainder of our buffer to write the packet. Payload starts
         // after the length and padding bytes which get filled by encrypt()
         let wbuf = &mut self.buf[len..];
@@ -194,8 +190,6 @@ impl<'a> Traffic<'a> {
         trace!("Sending {p:?}");
         trace!("new {plen} {:?}", (&wbuf[SSH_PAYLOAD_START..SSH_PAYLOAD_START+plen]).hex_dump());
 
-        assert_eq!(z[..qlen], wbuf[SSH_PAYLOAD_START..SSH_PAYLOAD_START+plen]);
-
         // Encrypt in place
         let elen = keys.encrypt(plen, wbuf)?;
         self.state = TrafState::Write { idx, len: len+elen };
diff --git a/sshproto/src/wireformat.rs b/sshproto/src/wireformat.rs
index 3996647969de456cbca05d2779c33740932e061d..55169736e84dec7d66a3f8ea0bd60f094ec5e016 100644
--- a/sshproto/src/wireformat.rs
+++ b/sshproto/src/wireformat.rs
@@ -162,10 +162,12 @@ impl<B: Clone> Clone for Blob<B> {
     }
 }
 
-impl<B: Serialize + Debug> Debug for Blob<B> {
+impl<B: SSHEncode + Serialize + Debug> Debug for Blob<B> {
     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
-        let len = SeSSHBytes::get_length(&self.0)
+        let len = sshwire::length_enc(&self.0)
             .map_err(|_| ser::Error::custom(Error::bug()))?;
+        // let len = SeSSHBytes::get_length(&self.0)
+        //     .map_err(|_| ser::Error::custom(Error::bug()))?;
         write!(f, "Blob(len={len}, {:?})", self.0)
     }
 }
@@ -279,6 +281,7 @@ impl SeSSHBytes<'_> {
 
     /// Appends serialized data
     fn push(&mut self, v: &[u8]) -> Res {
+        panic!("push");
         match self {
             SeSSHBytes::WriteBytes { target, ref mut pos } => {
                 if *pos + v.len() > target.len() {
@@ -532,6 +535,7 @@ impl<'de> DeSSHBytes<'de> {
     }
 
     fn take(&mut self, len: usize) -> Result<&'de [u8]> {
+        panic!("take");
         if len > self.input.len() {
             return Err(Error::RanOut);
         }