void Save(bool onlyupdated) { var created = 0; var updated = 0; var deleted = 0; var sw = new Stopwatch(); sw.Start(); var inactive = Statistics.GetInactive(); RemoveRouterInfo(inactive); using (var s = GetStore()) { lock ( RouterInfos ) { foreach (var one in RouterInfos.ToArray()) { try { if (one.Value.Value.Deleted) { if (one.Value.Value.StoreIx > 0) { s.Delete(one.Value.Value.StoreIx); } RouterInfos.Remove(one.Key); ++deleted; continue; } if (!onlyupdated || (onlyupdated && one.Value.Value.Updated)) { var rec = new BufLen[] { (BufLen)(int)StoreRecordId.StoreIdRouterInfo, new BufLen(one.Value.Key.ToByteArray()) }; if (one.Value.Value.StoreIx > 0) { s.Write(rec, one.Value.Value.StoreIx); ++updated; } else { one.Value.Value.StoreIx = s.Write(rec); ++created; } one.Value.Value.Updated = false; } } catch (Exception ex) { Logging.LogDebug("NetDb: Save: Store exception: " + ex.ToString()); one.Value.Value.StoreIx = -1; } } } var lookup = s.GetMatching(e => (StoreRecordId)e[0] == StoreRecordId.StoreIdConfig, 1); Dictionary <I2PString, int> str2ix = new Dictionary <I2PString, int>(); foreach (var one in lookup) { var reader = new BufRefLen(one.Value); reader.Read32(); var key = new I2PString(reader); str2ix[key] = one.Key; } AccessConfig(delegate(Dictionary <I2PString, I2PString> settings) { foreach (var one in settings) { var rec = new BufLen[] { (BufLen)(int)StoreRecordId.StoreIdConfig, new BufLen(one.Key.ToByteArray()), new BufLen(one.Value.ToByteArray()) }; if (str2ix.ContainsKey(one.Key)) { s.Write(rec, str2ix[one.Key]); } else { s.Write(rec); } } }); } Logging.Log($"NetDb.Save( {( onlyupdated ? "updated" : "all" )} ): " + $"{created} created, {updated} updated, {deleted} deleted."); Statistics.RemoveOldStatistics(); UpdateSelectionProbabilities(); sw.Stop(); Logging.Log($"NetDB: Save: {sw.Elapsed}"); }
public I2PKeyType(BufRef buf, I2PCertificate cert) { Certificate = cert; Key = buf.ReadBufLen(KeySizeBytes); }
public I2PCertificate(BufRef buf) { Data = new BufLen(buf, 0, 3); Data = buf.ReadBufLen(CertLength); }
public I2PSignature() { Certificate = I2PSigningKey.DefaultSigningKeyCert; Sig = new BufLen(new byte[Certificate.SignatureLength]); }
/** * 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.Random(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_ALL_TRANSPORT DebugUtils.Log(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(); Session.Host.Send(dest, data); }
public AesEGBuildRequestRecord(EGBuildRequestRecord src, BufferedBlockCipher cipher) { Data = new BufLen(cipher.ProcessBytes(src.Data.BaseArray, src.Data.BaseArrayOffset, src.Data.Length)); }
public BuildResponseRecord(EGBuildRequestRecord request) { // Replace it Data = request.Data; Data.Randomize(); }
public I2PSessionKey(BufRef buf) { Key = buf.ReadBufLen(32); }
public I2PSessionKey(BufLen buf) { Key = buf; }
public I2PSessionKey(byte[] buf) { Key = new BufLen(buf, 0, 32); }
public I2PSessionKey(I2PSessionKey src) { Key = new BufLen(src.Key); }
public I2PSessionKey() { Key = new BufLen(BufUtils.Random(32)); }
public BuildRequestRecord(BufRef buf) { Data = buf.ReadBufLen(Length); ReducedHash = CreateReducedHash(); }
public BuildRequestRecord() { Data = new BufLen(new byte[Length]); ReducedHash = CreateReducedHash(); }
public AesEGBuildRequestRecord(BufRef buf) { Data = buf.ReadBufLen(Length); }
public I2PPrivateKey(I2PCertificate cert) : base(cert) { Key = new BufLen(BufUtils.RandomBytes(KeySizeBytes)); Key[0] |= 0x80; Key[Key.Length - 1] |= 0x01; }
public AesEGBuildRequestRecord(BufLen dest, EGBuildRequestRecord src, BufferedBlockCipher cipher) { Data = dest; cipher.ProcessBytes(src.Data.BaseArray, src.Data.BaseArrayOffset, src.Data.Length, Data.BaseArray, Data.BaseArrayOffset); }
public override SSUState HandleMessage(SSUHeader header, BufRefLen reader) { var tstime = SSUHost.SSUDateTime(header.TimeStamp); if (header.MessageType != SSUHeader.MessageTypes.SessionCreated) { #if LOG_ALL_TRANSPORT DebugUtils.Log("SSU SessionRequestState: Received unexpected message " + tstime.ToString() + " : " + header.Flag.ToString()); #endif return(this); } SCMessage = new SessionCreated(reader, Session.RemoteRouter.Certificate); Session.RelayTag = SCMessage.RelayTag; Y = new I2PPublicKey((BufRefLen)SCMessage.Y, Session.RemoteRouter.Certificate); BufUtils.DHI2PToSessionAndMAC(out Session.SharedKey, out Session.MACKey, Y.ToBigInteger().ModPow(PrivateKey.ToBigInteger(), I2PConstants.ElGamalP)); var ipaddr = new IPAddress(SCMessage.Address.ToByteArray()); ushort port = SCMessage.Port.PeekFlip16(0); Session.SignOnTimeB = SCMessage.SignOnTime.Peek32(0); var btime = SSUHost.SSUDateTime(BufUtils.Flip32(Session.SignOnTimeB)); #if LOG_ALL_TRANSPORT DebugUtils.Log("SSU SessionRequestState " + Session.DebugId + " : Received SessionCreated. " + tstime.ToString() + " : " + btime.ToString()); #endif Session.Host.ReportedAddress(ipaddr); if (!I2PSignature.SupportedSignatureType(Session.RemoteRouter.Certificate.SignatureType)) { throw new SignatureCheckFailureException("SSU SessionRequestState " + Session.DebugId + " : " + "Received non supported signature type: " + Session.RemoteRouter.Certificate.SignatureType.ToString()); } var cipher = new CbcBlockCipher(new AesEngine()); cipher.Init(false, Session.SharedKey.ToParametersWithIV(header.IV)); cipher.ProcessBytes(SCMessage.SignatureEncrBuf); var baddr = new BufLen(Session.RemoteEP.Address.GetAddressBytes()); var sign = new I2PSignature((BufRefLen)SCMessage.Signature, Session.RemoteRouter.Certificate); var sok = I2PSignature.DoVerify( Session.RemoteRouter.SigningPublicKey, sign, X.Key, Y.Key, SCMessage.Address, SCMessage.Port, baddr, BufUtils.Flip16BL((ushort)Session.RemoteEP.Port), SCMessage.RelayTag, SCMessage.SignOnTime); #if LOG_ALL_TRANSPORT DebugUtils.Log("SSU SessionRequestState: Signature check: " + sok.ToString() + ". " + Session.RemoteRouter.Certificate.SignatureType.ToString()); #endif if (!sok) { throw new SignatureCheckFailureException("SSU SessionRequestState " + Session.DebugId + ": Received SessionCreated signature check failed." + Session.RemoteRouter.Certificate.ToString()); } var relaytag = SCMessage.RelayTag.PeekFlip32(0); if (relaytag != 0) { Session.Host.IntroductionRelayOffered( new IntroducerInfo( Session.RemoteEP.Address, (ushort)Session.RemoteEP.Port, Session.IntroKey, relaytag)); } DebugUtils.Log("SSU SessionRequestState: Session " + Session.DebugId + " created. Moving to SessionConfirmedState."); Session.ReportConnectionEstablished(); return(new SessionConfirmedState(Session, this)); }
public BuildResponseRecord(BufRef buf) { Data = buf.ReadBufLen(Length); }
static void MyOrigin_DataReceived(ClientDestination dest, BufLen data) { Logging.LogInformation($"Program {MyOrigin}: data received. {data:15}"); }
public BuildResponseRecord(AesEGBuildRequestRecord request) { // Reuse it Data = request.Data; }
static void Main(string[] args) { PeriodicAction SendInterval = new PeriodicAction(TickSpan.Seconds(20)); Logging.ReadAppConfig(); Logging.LogToDebug = false; Logging.LogToConsole = true; RouterContext.RouterSettingsFile = "I2PDemo.bin"; MyDestinationInfo = new I2PDestinationInfo(I2PSigningKey.SigningKeyTypes.EdDSA_SHA512_Ed25519); for (int i = 0; i < args.Length; ++i) { switch (args[i]) { case "--addr": case "--address": if (args.Length > i + 1) { RouterContext.Inst.DefaultExtAddress = IPAddress.Parse(args[++i]); Console.WriteLine($"addr {RouterContext.Inst.DefaultExtAddress}"); } else { Console.WriteLine("--addr require ip number"); return; } break; case "--port": if (args.Length > i + 1) { var port = int.Parse(args[++i]); RouterContext.Inst.DefaultTCPPort = port; RouterContext.Inst.DefaultUDPPort = port; Console.WriteLine($"port {port}"); } else { Console.WriteLine("--port require port number"); return; } break; case "--nofw": RouterContext.Inst.IsFirewalled = false; Console.WriteLine($"Firewalled {RouterContext.Inst.IsFirewalled}"); break; case "--mkdest": case "--create-destination": var certtype = 0; if (args.Length > i + 1) { certtype = int.Parse(args[++i]); } I2PSigningKey.SigningKeyTypes ct; I2PDestinationInfo d; switch (certtype) { default: case 0: ct = I2PSigningKey.SigningKeyTypes.EdDSA_SHA512_Ed25519; d = new I2PDestinationInfo(ct); break; case 1: ct = I2PSigningKey.SigningKeyTypes.DSA_SHA1; d = new I2PDestinationInfo(ct); break; case 2: ct = I2PSigningKey.SigningKeyTypes.ECDSA_SHA256_P256; d = new I2PDestinationInfo(ct); break; case 3: ct = I2PSigningKey.SigningKeyTypes.ECDSA_SHA384_P384; d = new I2PDestinationInfo(ct); break; } Console.WriteLine($"New destination {ct}: {d.ToBase64()}"); return; case "--destination": if (args.Length > i + 1) { MyDestinationInfo = new I2PDestinationInfo(args[++i]); Console.WriteLine($"Destination {MyDestinationInfo}"); } else { Console.WriteLine("Base64 encoded Destination required"); return; } break; default: Console.WriteLine(args[i]); Console.WriteLine("Usage: I2P.exe --addr 12.34.56.78 --port 8081 --nofw --create-destination [0-3] --destination b64..."); break; } } RouterContext.Inst.ApplyNewSettings(); var pnp = new UPnp(); Thread.Sleep(5000); // Give UPnp a chance Router.Start(); // Create new identities for this run MyDestination = MyDestinationInfo.Destination; #if MANUAL_SIGN PublishedDestination = Router.CreateDestination( MyDestination, MyDestinationInfo.PrivateKey, true, out _); // Publish our destinaiton PublishedDestination.SignLeasesRequest += MyDestination_SignLeasesRequest; #else PublishedDestination = Router.CreateDestination(MyDestinationInfo, true, out _); // Publish our destinaiton #endif PublishedDestination.DataReceived += MyDestination_DataReceived; PublishedDestination.Name = "PublishedDestination"; MyOriginInfo = new I2PDestinationInfo(I2PSigningKey.SigningKeyTypes.DSA_SHA1); MyOrigin = Router.CreateDestination(MyOriginInfo, false, out _); MyOrigin.ClientStateChanged += MyOrigin_ClientStateChanged; MyOrigin.DataReceived += MyOrigin_DataReceived; MyOrigin.Name = "MyOrigin"; Logging.LogInformation($"MyDestination: {PublishedDestination.Destination.IdentHash} {MyDestinationInfo.Destination.Certificate}"); while (true) { try { Connected = true; MyOrigin.LookupDestination(PublishedDestination.Destination.IdentHash, LookupResult); var sendevents = 0; while (Connected) { Thread.Sleep(2000); if (LookedUpDestination != null && MyOrigin.ClientState == ClientDestination.ClientStates.Established) { SendInterval.Do(() => { if (sendevents++ < 10) { // Send some data to the MyDestination DataSent = new BufLen( BufUtils.RandomBytes( (int)(1 + BufUtils.RandomDouble(25) * 1024))); var ok = MyOrigin.Send(LookedUpDestination, DataSent); Logging.LogInformation($"Program {MyOrigin}: Send[{sendevents}] {ok}, {DataSent:15}"); } if (sendevents > 100) { sendevents = 0; } }); } } } catch (SocketException ex) { Logging.Log(ex); } catch (IOException ex) { Logging.Log(ex); } catch (Exception ex) { Logging.Log(ex); } } }
public I2PSignature(BufRef buf, I2PCertificate cert) { Certificate = cert; Sig = buf.ReadBufLen(cert.SignatureLength); }
public EGGarlic(BufRef reader) { Data = reader.ReadBufLen((int)reader.PeekFlip32(0) + 4); }
bool RandomExtraPadding(BufLen start, BufRefLen writer) { writer.Write(BufUtils.Random(BufUtils.RandomInt(16))); return(true); }
public DataMessage(BufLen data) { AllocateBuffer(4 + data.Length); Payload.PokeFlip32((uint)data.Length, 0); Payload.Poke(data, 4); }
public override SSUState HandleMessage(SSUHeader header, BufRefLen reader) { switch (header.MessageType) { case SSUHeader.MessageTypes.Data: try { var datamsg = new SSUDataMessage(reader, Session.Defragmenter); if (datamsg.ExplicitAcks != null) { Session.Fragmenter.GotAck(datamsg.ExplicitAcks); } if (datamsg.AckBitfields != null) { Session.Fragmenter.GotAck(datamsg.AckBitfields); } if (datamsg.NewMessages != null) { foreach (var msg in datamsg.NewMessages) { var i2npmsg = I2NPMessage.ReadHeader16((BufRefLen)msg.GetPayload()); #if LOG_MUCH_TRANSPORT Logging.LogDebugData($"SSU {this} complete message " + $"{msg.MessageId}: {i2npmsg.Expiration}"); #endif if (i2npmsg.MessageType == I2NPMessage.MessageTypes.DeliveryStatus) { if (((DeliveryStatusMessage)i2npmsg.Message).IsNetworkId((ulong)I2PConstants.I2P_NETWORK_ID)) { continue; } } Session.MessageReceived(i2npmsg); } } } catch (Exception ex) { Logging.Log("EstablishedState: SSUHost.SSUMessageTypes.Data", ex); } break; case SSUHeader.MessageTypes.PeerTest: HandleIncomingPeerTestPackage(reader); break; case SSUHeader.MessageTypes.RelayResponse: Logging.LogTransport($"SSU EstablishedState {Session.DebugId}: RelayResponse received from {Session.RemoteEP}."); var response = new RelayResponse(reader); Session.Host.ReportRelayResponse(header, response, Session.RemoteEP); break; case SSUHeader.MessageTypes.RelayIntro: var intro = new RelayIntro(reader); Logging.LogTransport($"SSU EstablishedState {Session.DebugId}: RelayIntro received from {Session.RemoteEP} for {intro.AliceEndpoint}."); var data = new BufLen(new byte[12]); data.Randomize(); Send(intro.AliceEndpoint, data); ++Session.Host.EPStatisitcs[Session.RemoteEP].RelayIntrosReceived; ++Session.RelayIntroductionsReceived; break; case SSUHeader.MessageTypes.RelayRequest: // TODO: Implement // if ( !SSUHost.IntroductionSupported ) throw new Exception( "SSU relay introduction not supported" ); Logging.LogTransport(string.Format("SSU EstablishedState {0}: Relay introduction not supported.", Session.DebugId)); break; case SSUHeader.MessageTypes.SessionRequest: Logging.LogTransport(string.Format("SSU EstablishedState {0}: SessionRequest received. Ending session.", Session.DebugId)); SendSessionDestroyed(); return(null); default: Logging.LogTransport(string.Format("SSU EstablishedState {0}: Unexpected message received: {1}.", Session.DebugId, header.MessageType)); break; } return(this); }
GarlicCreationInfo GenerateNewSessionTags(uint trackingid, GarlicCloveDelivery[] cloves) { var newtags = new List <I2PSessionTag>(); for (int i = 0; i < 50; ++i) { newtags.Add(new I2PSessionTag()); } lock ( SessionTags ) { SessionTags.AddRange(newtags); } // Add a ACK message DeliveryStatusMessage ackmsg; var msg = AddExplAck(cloves, out ackmsg); var payload = msg.ToByteArray(); var dest = new BufLen(new byte[61000]); var writer = new BufRefLen(dest, 4); // Reserve 4 bytes for GarlicMessageLength // ElGamal block var egbuf = new BufLen(writer, 0, 222); var sessionkeybuf = new BufLen(egbuf, 0, 32); var preivbuf = new BufLen(egbuf, 32, 32); var egpadding = new BufLen(egbuf, 64); sessionkeybuf.Poke(SessionKey.Key, 0); preivbuf.Randomize(); egpadding.Randomize(); var preiv = preivbuf.Clone(); var eg = new ElGamalCrypto(Destination.PublicKey); eg.Encrypt(writer, egbuf, true); // AES block var aesstart = new BufLen(writer); var aesblock = new GarlicAESBlock(writer, newtags, null, new BufRefLen(payload)); var pivh = I2PHashSHA256.GetHash(preiv); Cipher.Init(true, SessionKey.Key.ToParametersWithIV(new BufLen(pivh, 0, 16))); Cipher.ProcessBytes(aesblock.DataBuf); var length = writer - dest; dest.PokeFlip32((uint)(length - 4), 0); LatestEGAckMessageId = ackmsg.MessageId; #if LOG_ALL_TUNNEL_TRANSFER Logging.LogDebug(() => string.Format( "DestinationSession: Garlic generated with ElGamal encryption, {0} cloves. {1} tags available. Ack MessageId: {2}.", msg.Cloves.Count, SessionTags.Count, LatestEGAckMessageId)); #endif return(new GarlicCreationInfo( Destination.IdentHash, cloves, new EGGarlic(new BufRefLen(dest, 0, length)), GarlicCreationInfo.KeyUsed.ElGamal, SessionTags.Count(), trackingid, ackmsg.MessageId, LatestEGAckMessageId)); }
public I2PCertificate() { Data = new BufLen(new byte[3]); CType = CertTypes.NULL; }
public SSUDataMessage(BufRef reader, DataDefragmenter fragments) { var dataflags = (DataMessageFlags)reader.Read8(); #if LOG_MUCH_TRANSPORT Logging.LogTransport("SSU DataMessage rececived flag: " + dataflags.ToString()); #endif var explicitacks = (dataflags & DataMessageFlags.ExplicitAcks) != 0; var acksbitfields = (dataflags & DataMessageFlags.BitfieldAcks) != 0; ECN = (dataflags & DataMessageFlags.ECN) != 0; var extdata = (dataflags & DataMessageFlags.ExtendedDataIncluded) != 0; if (explicitacks) { ExplicitAcks = new List <uint>(); var acks = reader.Read8(); for (int i = 0; i < acks; ++i) { ExplicitAcks.Add(reader.Read32()); } } if (acksbitfields) { var bitfields = reader.Read8(); AckBitfields = new List <KeyValuePair <uint, List <byte> > >(bitfields); for (int i = 0; i < bitfields; ++i) { var msgid = reader.Read32(); var bfs = new List <byte>(10); byte bf; while (true) { bf = reader.Read8(); bfs.Add((byte)(bf & 0x7f)); if ((bf & 0x80) == 0) { break; } } AckBitfields.Add(new KeyValuePair <uint, List <byte> >(msgid, bfs)); } } if (extdata) { var datasize = reader.Read8(); ExtData = reader.ReadBufLen(datasize); } var fragcount = reader.Read8(); for (int i = 0; i < fragcount; ++i) { var frag = new DataFragment(reader); var newmessage = fragments.Add(frag); if (newmessage != null) { if (NewMessages == null) { NewMessages = new List <RebuildI2NPMessage>(); } NewMessages.Add(newmessage); } } }