internal static void Receive(DHHandshakeContext context, I2PKeysAndCert ri) { var responselength = ri.Certificate.SignatureLength; responselength += BufUtils.Get16BytePadding(responselength); var data = context.Client.BlockReceive(responselength); context.Dectryptor.ProcessBytes(data); var signature = new I2PSignature(new BufRefLen(data), context.RemoteRI.Certificate); if (!I2PSignature.SupportedSignatureType(context.RemoteRI.Certificate.SignatureType)) { throw new SignatureCheckFailureException("NTCP SessionConfirmB recv not supported signature type: " + context.RemoteRI.Certificate.SignatureType.ToString()); } var ok = I2PSignature.DoVerify(context.RemoteRI.SigningPublicKey, signature, context.X.Key, context.Y.Key, RouterContext.Inst.MyRouterIdentity.IdentHash.Hash, BufUtils.Flip32BL(context.TimestampA), BufUtils.Flip32BL(context.TimestampB)); #if LOG_ALL_TRANSPORT DebugUtils.Log("SessionConfirmB: " + context.RemoteRI.Certificate.SignatureType.ToString() + " signature check: " + ok.ToString()); #endif if (!ok) { throw new SignatureCheckFailureException("NTCP SessionConfirmB recv sig check failure"); } }
internal static BufLen Send(DHHandshakeContext context) { context.TimestampA = (uint)Math.Ceiling((DateTime.UtcNow - I2PDate.RefDate).TotalSeconds); var cleartext = new List <byte>(); var ri = RouterContext.Inst.MyRouterIdentity.ToByteArray(); cleartext.AddRange(BufUtils.Flip16B((ushort)ri.Length)); cleartext.AddRange(ri); cleartext.AddRange(BufUtils.Flip32B(context.TimestampA)); #if LOG_ALL_TRANSPORT DebugUtils.Log("SessionConfirmA send TimestampA: " + (I2PDate.RefDate.AddSeconds(context.TimestampA).ToString())); DebugUtils.Log("SessionConfirmA send TimestampB: " + (I2PDate.RefDate.AddSeconds(context.TimestampB).ToString())); #endif var sign = I2PSignature.DoSign(RouterContext.Inst.PrivateSigningKey, context.X.Key, context.Y.Key, context.RemoteRI.IdentHash.Hash, BufUtils.Flip32BL(context.TimestampA), BufUtils.Flip32BL(context.TimestampB)); var padsize = BufUtils.Get16BytePadding(sign.Length + cleartext.Count); cleartext.AddRange(BufUtils.Random(padsize)); cleartext.AddRange(sign); var buf = new BufLen(cleartext.ToArray()); context.Encryptor.ProcessBytes(buf); return(buf); }
public GarlicAESBlock(BufRefLen reader) { var start = new BufLen(reader); TagCount = reader.ReadBufLen(2); var tags = TagCount.PeekFlip16(0); if (tags > 0) { if (tags * I2PSessionTag.TagLength > start.Length) { throw new ArgumentException("GarlicAESBlock: Not enough data for the tags supplied."); } for (int i = 0; i < tags; ++i) { Tags.Add(reader.ReadBufLen(I2PSessionTag.TagLength)); } } PayloadSize = reader.ReadBufLen(4); PayloadHash = reader.ReadBufLen(32); Flag = reader.ReadBufLen(1); if (Flag[0] != 0) { NewSessionKey = reader.ReadBufLen(32); } var pllen = PayloadSize.PeekFlip32(0); if (pllen > reader.Length) { throw new ArgumentException("GarlicAESBlock: Not enough data payload supplied."); } Payload = reader.ReadBufLen((int)pllen); Padding = reader.ReadBufLen(BufUtils.Get16BytePadding(reader - start)); }
internal static BufLen Send(DHHandshakeContext context) { context.TimestampA = (uint)Math.Ceiling((DateTime.UtcNow - I2PDate.RefDate).TotalSeconds); var cleartext = new BufRefStream(); var ri = RouterContext.Inst.MyRouterIdentity.ToByteArray(); cleartext.Write(BufUtils.Flip16B((ushort)ri.Length)); cleartext.Write(ri); cleartext.Write(BufUtils.Flip32B(context.TimestampA)); Logging.LogDebugData($"SessionConfirmA send TimestampA: {I2PDate.RefDate.AddSeconds( context.TimestampA )}"); Logging.LogDebugData($"SessionConfirmA send TimestampB: {I2PDate.RefDate.AddSeconds( context.TimestampB )}"); var sign = I2PSignature.DoSign(RouterContext.Inst.PrivateSigningKey, context.X.Key, context.Y.Key, context.RemoteRI.IdentHash.Hash, BufUtils.Flip32BL(context.TimestampA), BufUtils.Flip32BL(context.TimestampB)); var padsize = BufUtils.Get16BytePadding((int)(sign.Length + cleartext.Length)); cleartext.Write(BufUtils.RandomBytes(padsize)); cleartext.Write(sign); var buf = new BufLen(cleartext.ToArray()); context.Encryptor.ProcessBytes(buf); return(buf); }
public BufLen GenerateData(I2NPMessage msg) { if (NTCPContext == null) { throw new Exception("NTCP Session not negotiated!"); } if (NTCPContext.Encryptor == null) { throw new Exception("NTCP encryptor not available"); } var data = msg != null ? msg.Header16.HeaderAndPayload: null; var datalength = msg == null ? 4 : data.Length; var buflen = 2 + datalength + 4; var padlength = BufUtils.Get16BytePadding(buflen); buflen += padlength; var buf = new BufLen(new byte[buflen]); var writer = new BufRefLen(buf); // Length if (msg == null) { // Send timestamp writer.Write16(0); writer.WriteFlip32((uint)(DateTime.UtcNow - I2PDate.RefDate).TotalSeconds); } else { if (data.Length > 16378) { throw new ArgumentException("NTCP data can be max 16378 bytes long!"); } writer.WriteFlip16((ushort)data.Length); writer.Write(data); } // Pad writer.Write(BufUtils.Random(writer.Length - 4)); // Checksum var checkbuf = new BufLen(buf, 0, writer - buf); var checksum = LZUtils.Adler32(1, checkbuf); writer.WriteFlip32(checksum); // Encrypt NTCPContext.Encryptor.ProcessBytes(buf); return(buf); }
private void SendUnfragmentedSessionConfirmed() { var ri = new BufLen(Session.MyRouterContext.MyRouterInfo.ToByteArray()); SendMessage( SSUHeader.MessageTypes.SessionConfirmed, Session.MACKey, Session.SharedKey, (start, writer) => { writer.Write8((byte)((0 << 4) + 1)); writer.WriteFlip16((ushort)ri.Length); writer.Write(ri); Session.SignOnTimeA = BufUtils.Flip32(SSUHost.SSUTime(DateTime.UtcNow)); writer.Write32(Session.SignOnTimeA); var padding = BufUtils.Get16BytePadding(Session.MyRouterContext.Certificate.SignatureLength + (writer - start)); writer.Write(BufUtils.Random(padding)); var baddr = new BufLen(Session.RemoteEP.Address.GetAddressBytes()); var bport = BufUtils.Flip16BL((ushort)Session.RemoteEP.Port); #if LOG_ALL_TRANSPORT Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: X for signature {1}.", Session.DebugId, Request.X.Key)); Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: Y for signature {1}.", Session.DebugId, Request.Y.Key)); Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: Alice address for signature {1}. Port {2}.", Session.DebugId, Request.SCMessage.Address, Request.SCMessage.Port)); Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: Bob address for signature {1}. Port {2}.", Session.DebugId, baddr, bport)); Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: Relay tag {1}. Signon time {2}.", Session.DebugId, Request.SCMessage.RelayTag, (BufLen)Session.SignOnTimeA)); #endif var sign = I2PSignature.DoSign(Session.MyRouterContext.PrivateSigningKey, Request.X.Key, Request.Y.Key, Request.SCMessage.Address, Request.SCMessage.Port, baddr, bport, Request.SCMessage.RelayTag, (BufLen)Session.SignOnTimeA ); writer.Write(sign); #if LOG_ALL_TRANSPORT Logging.LogTransport(string.Format("SessionConfirmedState {0}: sending unfragmented SessionConfirmed. {1} bytes [0x{1:X}].", Session.DebugId, writer - start - SSUHeader.FIXED_HEADER_SIZE)); #endif return(true); }); }
public GarlicAESBlock( BufRefLen reader, IList <I2PSessionTag> tags, I2PSessionKey newsessionkey, BufRefLen payload) { var start = new BufLen(reader); // Allocate TagCount = reader.ReadBufLen(2); if (tags != null) { for (int i = 0; i < tags.Count; ++i) { Tags.Add(reader.ReadBufLen(I2PSessionTag.TagLength)); } } PayloadSize = reader.ReadBufLen(4); PayloadHash = reader.ReadBufLen(32); Flag = reader.ReadBufLen(1); if (newsessionkey != null) { reader.ReadBufLen(32); } var pllen = Math.Min(reader.Length, payload.Length); Payload = reader.ReadBufLen(pllen); Padding = reader.ReadBufLen(BufUtils.Get16BytePadding(reader - start)); // Write TagCount.PokeFlip16((ushort)(tags == null ? 0 : tags.Count), 0); if (tags != null) { for (int i = 0; i < tags.Count; ++i) { Tags[i].Poke(tags[i].Value, 0); } } Flag[0] = (byte)(newsessionkey != null ? 0x01 : 0); if (newsessionkey != null) { NewSessionKey.Poke(newsessionkey.Key, 0); } Payload.Poke(new BufLen(payload, 0, pllen), 0); payload.Seek(pllen); PayloadSize.PokeFlip32((uint)pllen, 0); PayloadHash.Poke(I2PHashSHA256.GetHash(Payload), 0); Padding.Randomize(); DataBuf = new BufLen(start, 0, reader - start); }
public SessionCreated(BufRef reader, I2PCertificate cert) { Certificate = cert; Y = reader.ReadBufLen(Certificate.PublicKeyLength); var ipsize = reader.Read8(); Address = reader.ReadBufLen(ipsize); Port = reader.ReadBufLen(2); RelayTag = reader.ReadBufLen(4); SignOnTime = reader.ReadBufLen(4); var paddedsignlen = cert.SignatureLength + BufUtils.Get16BytePadding(cert.SignatureLength); SignatureEncrBuf = reader.ReadBufLen(paddedsignlen); Signature = new BufLen(SignatureEncrBuf, 0, cert.SignatureLength); }
private BufLen ReadBlock() { var inbufend = 2 + BlockLength + 4; inbufend += BufUtils.Get16BytePadding(inbufend); while (InBufPos < inbufend) { if (MySocket.Available > 0) { var len = MySocket.Receive(InBuf, InBufPos, inbufend - InBufPos, SocketFlags.None); if (len == 0) { throw new EndOfStreamEncounteredException(); } InBufPos += len; } else { Thread.Sleep(400); if (!MySocket.Connected) { throw new EndOfStreamEncounteredException(); } } } Cipher.ProcessBytes(new BufLen(InBuf, 16, InBufPos - 16)); var checksum = LZUtils.Adler32(1, new BufLen(InBuf, 0, InBufPos - 4)); var blocksum = BufUtils.Flip32(InBuf, InBufPos - 4); if (checksum != blocksum) { throw new ChecksumFailureException("NTCPReader: Received Adler checksum mismatch."); } var result = new BufLen(InBuf, 2, BlockLength); BlockLength = -1; #if LOG_ALL_TRANSPORT Logging.LogTransport(string.Format("NTCPReader +{1}+ block received: {0} bytes [0x{0:X}]", result.Length, Context.TransportInstance)); #endif return(result.Clone()); }
private void SendUnfragmentedSessionConfirmed() { var ri = new BufLen(Session.MyRouterContext.MyRouterInfo.ToByteArray()); SendMessage( SSUHeader.MessageTypes.SessionConfirmed, Session.MACKey, Session.SharedKey, (start, writer) => { writer.Write8((byte)((0 << 4) + 1)); writer.WriteFlip16((ushort)ri.Length); writer.Write(ri); Session.SignOnTimeA = BufUtils.Flip32(SSUHost.SSUTime(DateTime.UtcNow)); writer.Write32(Session.SignOnTimeA); var padding = BufUtils.Get16BytePadding(Session.MyRouterContext.Certificate.SignatureLength + (writer - start)); writer.Write(BufUtils.RandomBytes(padding)); var baddr = new BufLen(Session.RemoteEP.Address.GetAddressBytes()); var bport = BufUtils.Flip16BL((ushort)Session.RemoteEP.Port); #if LOG_MUCH_TRANSPORT Logging.LogTransport($"SSU {this}: X for signature {Request.X.Key}."); Logging.LogTransport($"SSU {this}: Y for signature {Request.Y.Key}."); Logging.LogTransport($"SSU {this}: Alice address for signature {Request.SCMessage.Address}. Port {Request.SCMessage.Port}."); Logging.LogTransport($"SSU {this}: Bob address for signature {baddr}. Port {bport}."); Logging.LogTransport($"SSU {this}: Relay tag {Request.SCMessage.RelayTag}. Signon time {(BufLen)Session.SignOnTimeA}."); #endif var sign = I2PSignature.DoSign(Session.MyRouterContext.PrivateSigningKey, Request.X.Key, Request.Y.Key, Request.SCMessage.Address, Request.SCMessage.Port, baddr, bport, Request.SCMessage.RelayTag, BufUtils.To32BL(Session.SignOnTimeA) ); writer.Write(sign); Logging.LogTransport($"SSU {this}: {Session.RemoteEP} " + $"sending unfragmented SessionConfirmed [0x{writer - start - SSUHeader.FIXED_HEADER_SIZE:X}] bytes."); return(true); }); }
internal static byte[] Send(DHHandshakeContext context) { var msglen = RouterContext.Inst.MyRouterIdentity.Certificate.SignatureLength; msglen += BufUtils.Get16BytePadding(msglen); var writer = new BufRefLen(new byte[msglen]); var SigBuf = I2PSignature.DoSign(RouterContext.Inst.PrivateSigningKey, context.XBuf, context.YBuf, context.RemoteRI.IdentHash.Hash, (BufLen)BufUtils.Flip32(context.TimestampA), (BufLen)BufUtils.Flip32(context.TimestampB)); writer.Write(SigBuf); writer.Write(BufUtils.Random(writer.Length)); writer.Reset(); context.Encryptor.ProcessBytes((BufLen)writer); return(writer.ToByteArray()); }
private void SendSessionCreated() { SendMessage( SSUHeader.MessageTypes.SessionCreated, Session.MyRouterContext.IntroKey, Session.MyRouterContext.IntroKey, (start, writer) => { writer.Write(Y.Key); AAddr = Session.RemoteEP.Address.GetAddressBytes(); writer.Write8((byte)AAddr.Length); writer.Write(AAddr); APort = BufUtils.Flip16((ushort)Session.RemoteEP.Port); writer.Write16(APort); writer.WriteFlip32(RelayTag); Session.SignOnTimeB = BufUtils.Flip32(SSUHost.SSUTime(DateTime.UtcNow)); writer.Write32(Session.SignOnTimeB); var sign = I2PSignature.DoSign(Session.MyRouterContext.PrivateSigningKey, Request.X, Y.Key, new BufLen(AAddr), (BufLen)APort, Request.Address, (BufLen)BufUtils.Flip16((ushort)Session.MyRouterContext.UDPPort), (BufLen)RelayTag, (BufLen)Session.SignOnTimeB); var signstart = new BufLen(writer); writer.Write(sign); var padding = BufUtils.Get16BytePadding(writer - signstart); writer.Write(BufUtils.Random(padding)); var cipher = new CbcBlockCipher(new AesEngine()); var signcryptbuf = new BufLen(signstart, 0, writer - signstart); cipher.Init(true, Session.SharedKey.ToParametersWithIV(new BufLen(start, 16, 16))); cipher.ProcessBytes(signcryptbuf); return(true); }); }
private void SendFragmentedSessionConfirmed() { var ri = new BufLen(Session.MyRouterContext.MyRouterInfo.ToByteArray()); var rireader = new BufRefLen(ri); var datafragments = new List <BufLen>(); while (rireader.Length > 0) { datafragments.Add(rireader.ReadBufLen(Math.Min(rireader.Length, 472))); } for (int i = 0; i < datafragments.Count; ++i) { #if LOG_ALL_TRANSPORT Logging.LogTransport(string.Format("SessionConfirmedState {0}: sending fragment {1} of {2}, {3} bytes [0x{3:X}].", Session.DebugId, i + 1, datafragments.Count + 1, datafragments[i].Length)); #endif SendMessage( SSUHeader.MessageTypes.SessionConfirmed, Session.MACKey, Session.SharedKey, (start, writer) => { writer.Write8((byte)((i << 4) + datafragments.Count + 1)); writer.WriteFlip16((ushort)datafragments[i].Length); writer.Write(datafragments[i]); return(true); }); } SendMessage( SSUHeader.MessageTypes.SessionConfirmed, Session.MACKey, Session.SharedKey, (start, writer) => { var frag = datafragments.Count; writer.Write8((byte)((frag << 4) + frag + 1)); writer.WriteFlip16(0); Session.SignOnTimeA = BufUtils.Flip32(SSUHost.SSUTime(DateTime.UtcNow)); writer.Write32(Session.SignOnTimeA); var padding = BufUtils.Get16BytePadding(Session.MyRouterContext.Certificate.SignatureLength + (writer - start)); writer.Write(BufUtils.Random(padding)); var baddr = new BufLen(Session.RemoteEP.Address.GetAddressBytes()); var sign = I2PSignature.DoSign(Session.MyRouterContext.PrivateSigningKey, Request.X.Key, Request.Y.Key, Request.SCMessage.Address, Request.SCMessage.Port, baddr, BufUtils.Flip16BL((ushort)Session.RemoteEP.Port), Request.SCMessage.RelayTag, (BufLen)Session.SignOnTimeA ); writer.Write(sign); #if LOG_ALL_TRANSPORT Logging.LogTransport(string.Format("SessionConfirmedState {0}: sending fragment {1} of {2}, {3} bytes [0x{3:X}].", Session.DebugId, frag + 1, datafragments.Count + 1, writer - start - SSUHeader.FIXED_HEADER_SIZE)); #endif return(true); }); }
internal static void Receive(DHHandshakeContext context, BufLen datastart) { var origbuf = new BufRefLen(datastart); var reader = new BufRefLen(datastart); context.Dectryptor.ProcessBytes(datastart); var rilen = reader.ReadFlip16(); var ribuf = reader.ReadBufRefLen(rilen); context.TimestampA = reader.ReadFlip32(); #if LOG_ALL_TRANSPORT DebugUtils.Log("SessionConfirmA recv TimestampA: " + (I2PDate.RefDate.AddSeconds(context.TimestampA).ToString())); DebugUtils.Log("SessionConfirmA recv TimestampB: " + (I2PDate.RefDate.AddSeconds(context.TimestampB).ToString())); #endif context.RemoteRI = new I2PRouterIdentity(ribuf); context.RunContext.RemoteRouterIdentity = context.RemoteRI; var sizeofpayload = 2 + rilen + 4 + context.RemoteRI.Certificate.SignatureLength; var paddingsize = BufUtils.Get16BytePadding(sizeofpayload); reader.Seek(paddingsize); var sigstart = new BufLen(reader, 0, context.RemoteRI.Certificate.SignatureLength); var needbytes = 2 + context.RemoteRI.Certificate.RouterIdentitySize + 4 + context.RemoteRI.Certificate.SignatureLength; needbytes += BufUtils.Get16BytePadding(needbytes); var writer = new BufRef(origbuf, origbuf.Length); var gotbytes = writer - origbuf; if (gotbytes < needbytes) { #if LOG_ALL_TRANSPORT DebugUtils.Log("SessionConfirmA recv not enough data: " + datastart.Length.ToString() + ". I want " + needbytes.ToString() + " bytes."); #endif var buf = context.Client.BlockReceive(needbytes - gotbytes); writer.Write(buf); } if (needbytes - datastart.Length > 0) { context.Dectryptor.ProcessBytes(new BufLen(datastart, datastart.Length, needbytes - datastart.Length)); } var signature = new I2PSignature(new BufRefLen(sigstart), context.RemoteRI.Certificate); if (!I2PSignature.SupportedSignatureType(context.RemoteRI.Certificate.SignatureType)) { throw new SignatureCheckFailureException("NTCP SessionConfirmA recv not supported signature type: " + context.RemoteRI.Certificate.SignatureType.ToString()); } var sigok = I2PSignature.DoVerify( context.RemoteRI.SigningPublicKey, signature, context.XBuf, context.YBuf, RouterContext.Inst.MyRouterIdentity.IdentHash.Hash, new BufLen(BufUtils.Flip32B(context.TimestampA)), new BufLen(BufUtils.Flip32B(context.TimestampB)) ); #if LOG_ALL_TRANSPORT DebugUtils.Log("SessionConfirmA recv: " + context.RemoteRI.Certificate.SignatureType.ToString() + " signature check: " + sigok.ToString() + "."); #endif if (!sigok) { throw new SignatureCheckFailureException("NTCP SessionConfirmA recv signature check fail"); } }
/** * From PacketBuilder.java * -----8<----- * @param packet prepared packet with the first 32 bytes empty and a length * whose size is mod 16. * As of 0.9.7, length non-mod-16 is allowed; the * last 1-15 bytes are included in the MAC calculation but are not encrypted. * -----8<----- */ protected void SendMessage( IPEndPoint dest, SSUHeader.MessageTypes message, BufLen mackey, BufLen cryptokey, SendMessageGenerator gen, SendMessageGenerator genextrapadding) { var start = Session.Host.SendBuffers.Pop(); var writer = new BufRefLen(start); var header = new SSUHeader(writer, message); if (!gen(start, writer)) { return; } // Do not cut to datalen & ~0xf as that might make data at the end unencrypted var datapadding = BufUtils.Get16BytePadding(writer - start); writer.Write(BufUtils.RandomBytes(datapadding)); var datalen = writer - start; var encryptedbuf = new BufLen(start, 32, datalen - 32); // TODO: Adding extra padding does not seem to work if (genextrapadding != null) { if (!genextrapadding(start, writer)) { return; } } var packetlen = writer - start; var data = new BufLen(start, 0, packetlen); var hmac = new BufLen(data, 32); SendMessageCipher.Init(true, cryptokey.ToParametersWithIV(header.IV)); SendMessageCipher.ProcessBytes(encryptedbuf); I2PHMACMD5Digest.Generate(new BufLen[] { hmac, header.IV, BufUtils.Flip16BL((ushort)((ushort)hmac.Length ^ I2PConstants.SSU_PROTOCOL_VERSION)) }, mackey, header.MAC); #if LOG_MUCH_TRANSPORT Logging.LogTransport(string.Format("SSUState SendMessage {0}: encrlen {1} bytes [0x{1:X}] (padding {2} bytes [0x{2:X}]), " + "hmac {3} bytes [0x{3:X}], sendlen {4} bytes [0x{4:X}]", Session.DebugId, encryptedbuf.Length, datapadding, hmac.Length, data.Length)); #endif DataSent(); Send(dest, data); }
private void SendFragmentedSessionConfirmed() { var ri = new BufLen(Session.MyRouterContext.MyRouterInfo.ToByteArray()); var rireader = new BufRefLen(ri); var datafragments = new List <BufLen>(); while (rireader.Length > 0) { datafragments.Add(rireader.ReadBufLen(Math.Min(rireader.Length, 472))); } for (int i = 0; i < datafragments.Count; ++i) { Logging.LogTransport($"SSU {this}: {Session.RemoteEP} " + $"sending fragment {i + 1} of {datafragments.Count + 1}, [0x{datafragments[i].Length:X}] bytes."); SendMessage( SSUHeader.MessageTypes.SessionConfirmed, Session.MACKey, Session.SharedKey, (start, writer) => { writer.Write8((byte)((i << 4) + datafragments.Count + 1)); writer.WriteFlip16((ushort)datafragments[i].Length); writer.Write(datafragments[i]); return(true); }); } SendMessage( SSUHeader.MessageTypes.SessionConfirmed, Session.MACKey, Session.SharedKey, (start, writer) => { var frag = datafragments.Count; writer.Write8((byte)((frag << 4) + frag + 1)); writer.WriteFlip16(0); Session.SignOnTimeA = BufUtils.Flip32(SSUHost.SSUTime(DateTime.UtcNow)); writer.Write32(Session.SignOnTimeA); var padding = BufUtils.Get16BytePadding(Session.MyRouterContext.Certificate.SignatureLength + (writer - start)); writer.Write(BufUtils.RandomBytes(padding)); var baddr = new BufLen(Session.RemoteEP.Address.GetAddressBytes()); var sign = I2PSignature.DoSign(Session.MyRouterContext.PrivateSigningKey, Request.X.Key, Request.Y.Key, Request.SCMessage.Address, Request.SCMessage.Port, baddr, BufUtils.Flip16BL((ushort)Session.RemoteEP.Port), Request.SCMessage.RelayTag, BufUtils.To32BL(Session.SignOnTimeA) ); writer.Write(sign); Logging.LogTransport($"SSU {this}: {Session.RemoteEP} " + $"sending fragment {frag + 1} of {datafragments.Count + 1}, [0x{writer - start - SSUHeader.FIXED_HEADER_SIZE:X}] bytes."); return(true); }); }