Exemple #1
0
        public static GarlicMessage AESEncryptGarlic(
            Garlic msg,
            I2PSessionKey sessionkey,
            I2PSessionTag tag,
            List <I2PSessionTag> newtags)
        {
            var cipher = new CbcBlockCipher(new AesEngine());

            var payload = msg.ToByteArray();
            var dest    = new BufLen(new byte[65536]);
            // Reserve header + 4 bytes for GarlicMessageLength
            var writer = new BufRefLen(dest, I2NPMaxHeaderSize + 4);

            // Tag as header
            writer.Write(tag.Value);

            // AES block
            var aesstart = new BufLen(writer);
            var aesblock = new GarlicAESBlock(writer, newtags, null, new BufRefLen(payload));

            var pivh = I2PHashSHA256.GetHash(tag.Value);

            cipher.Init(true, sessionkey.Key.ToParametersWithIV(new BufLen(pivh, 0, 16)));
            cipher.ProcessBytes(aesblock.DataBuf);

            var length = writer - dest;

            dest.PokeFlip32((uint)(length - 4), I2NPMaxHeaderSize);

            return(new GarlicMessage(new BufRefLen(dest, I2NPMaxHeaderSize, length)));
        }
Exemple #2
0
        public static void DHI2PToSessionAndMAC(out BufLen sessionkey, out BufLen mackey, BigInteger bi)
        {
            var result = new List <byte>();

            if (bi == BigInteger.Zero)
            {
                throw new FormatException("BigInteger == 0 for DH key!");
            }

            result.AddRange(bi.ToByteArray());

            if ((result[0] & 0x80) != 0)
            {
                result.Insert(0, 0);
            }

            while (result.Count < 32)
            {
                result.Add(0);
            }

            sessionkey = new BufLen(result.Take(32).ToArray());

            if (result.Count >= 64)
            {
                mackey = new BufLen(result.Skip(32).Take(32).ToArray());
            }
            else
            {
                mackey = new BufLen(I2PHashSHA256.GetHash(result.ToArray()));
            }
        }
Exemple #3
0
        public static (GarlicAESBlock, I2PSessionKey) EGDecryptGarlic(
            GarlicMessage garlic,
            I2PPrivateKey privkey)
        {
            var cipher = new CbcBlockCipher(new AesEngine());
            var egdata = garlic.EGData;

            var egbuf    = new BufLen(egdata, 0, 514);
            var egheader = ElGamalCrypto.Decrypt(egbuf, privkey, true);

            var sessionkey = new I2PSessionKey(new BufLen(egheader, 0, 32));
            var preiv      = new BufLen(egheader, 32, 32);
            var egpadding  = new BufLen(egheader, 64, 158);
            var aesbuf     = new BufLen(egdata, 514);

            var pivh = I2PHashSHA256.GetHash(preiv);

            cipher.Init(false, sessionkey.Key.ToParametersWithIV(new BufLen(pivh, 0, 16)));
            cipher.ProcessBytes(aesbuf);

            GarlicAESBlock aesblock =
                new GarlicAESBlock(new BufRefLen(aesbuf));

            if (!aesblock.VerifyPayloadHash())
            {
                throw new ChecksumFailureException("AES block hash check failed!");
            }

            return(aesblock, sessionkey);
        }
Exemple #4
0
        public void Encrypt(BufRef dest, BufLen data, bool zeropad)
        {
            if (data == null || data.Length > 222)
            {
                throw new InvalidParameterException("ElGamal data length can max be 222 bytes!");
            }

            var hashbuf = new BufRefLen(new byte[255]);

            hashbuf.Write8(0xFF);
            hashbuf.Write(I2PHashSHA256.GetHash(data));
            hashbuf.Write(data);
            hashbuf.Reset();

            var b = b1.Multiply(new BigInteger(1, hashbuf.ToByteArray())).Mod(I2PConstants.ElGamalP);

            if (zeropad)
            {
                dest.Write8(0);
                dest.Write(a.ToByteArray(256));
                dest.Write8(0);
                dest.Write(b.ToByteArray(256));
            }
            else
            {
                dest.Write(a.ToByteArray(256));
                dest.Write(b.ToByteArray(256));
            }
        }
Exemple #5
0
        public static void Encrypt(BufRef dest, BufLen data, I2PPublicKey key, bool zeropad)
        {
            if (data == null || data.Length > ClearTextLength)
            {
                throw new InvalidParameterException($"ElGamal data must be {ClearTextLength} bytes or less!");
            }

            var k  = new BigInteger(I2PConstants.ElGamalFullExponentBits, Rnd);
            var a  = I2PConstants.ElGamalG.ModPow(k, I2PConstants.ElGamalP);
            var b1 = key.ToBigInteger().ModPow(k, I2PConstants.ElGamalP);

            var start  = new BufLen(new byte[EGBlockLength]);
            var writer = new BufRefLen(start, 1);

            start[0] = 0xFF;

            writer.Write(I2PHashSHA256.GetHash(data));
            writer.Write(data);
            var egblock = new BufLen(start, 0, writer - start);
            var egint   = egblock.ToBigInteger();

            var b = b1.Multiply(egint).Mod(I2PConstants.ElGamalP);

            var targetlen = zeropad
                    ? EncryptedPaddedLength / 2
                    : EncryptedShortLength / 2;

            WriteToDest(dest, a, targetlen);
            WriteToDest(dest, b, targetlen);
        }
Exemple #6
0
        internal static byte[] Send(DHHandshakeContext context)
        {
            var dest   = new byte[288];
            var writer = new BufRefLen(dest);

            var keys = I2PPrivateKey.GetNewKeyPair();

            context.PrivateKey = keys.PrivateKey;
            context.X          = keys.PublicKey;
            context.XBuf       = context.X.Key;

            context.HXxorHI = new BufLen(I2PHashSHA256.GetHash(context.XBuf));

#if LOG_ALL_TRANSPORT
            Logging.LogTransport(
                "SessionRequest: Remote cert: " + context.RemoteRI.Certificate.ToString() + ". XBuf len: " + context.XBuf.Length.ToString());
#endif
            var idenhash = context.RemoteRI.IdentHash;
            for (int i = 0; i < context.HXxorHI.Length; ++i)
            {
                context.HXxorHI[i] ^= idenhash.Hash[i];
            }

            writer.Write(context.XBuf);
            writer.Write(context.HXxorHI);

            return(dest);
        }
Exemple #7
0
        internal static byte[] Send(DHHandshakeContext context)
        {
            var dest   = new byte[288];
            var writer = new BufRefLen(dest);

            var keys = I2PPrivateKey.GetNewKeyPair();

            context.PrivateKey = keys.PrivateKey;
            context.X          = keys.PublicKey;
            context.XBuf       = context.X.Key;

            context.HXxorHI = new BufLen(I2PHashSHA256.GetHash(context.XBuf));

            Logging.LogDebugData(
                $"SessionRequest: Remote cert: {context.RemoteRI.Certificate}. XBuf len: {context.XBuf.Length}");

            var idenhash = context.RemoteRI.IdentHash;

            for (int i = 0; i < context.HXxorHI.Length; ++i)
            {
                context.HXxorHI[i] ^= idenhash.Hash[i];
            }

            writer.Write(context.XBuf);
            writer.Write(context.HXxorHI);

            return(dest);
        }
Exemple #8
0
        GarlicCreationInfo UseExistingSessionTags(bool explack, uint trackingid, GarlicCloveDelivery[] cloves)
        {
            Garlic msg;
            DeliveryStatusMessage ackmsg = null;

            if (explack)
            {
                msg = AddExplAck(cloves, out ackmsg);
            }
            else
            {
                var exp = new I2PDate(DateTime.UtcNow.AddMinutes(5));
                msg = new Garlic(cloves.Select(d => new GarlicClove(d, exp)).ToArray());
            }

#if LOG_ALL_TUNNEL_TRANSFER
            Logging.LogDebug(() => string.Format(
                                 "DestinationSession: Garlic generated with {0} cloves. {1} tags available.",
                                 msg.Cloves.Count, SessionTags.Count));
#endif

            var payload = msg.ToByteArray();
            var dest    = new BufLen(new byte[61000]);
            var writer  = new BufRefLen(dest, 4);  // Reserve 4 bytes for GarlicMessageLength

            I2PSessionTag tag;
            lock ( SessionTags )
            {
                var ix = BufUtils.RandomInt(SessionTags.Count);
                tag = SessionTags[ix];
                SessionTags.RemoveAt(ix);
            }

            // Tag as header
            writer.Write(tag.Value);

            // AES block
            var aesstart = new BufLen(writer);
            var aesblock = new GarlicAESBlock(writer, null, null, new BufRefLen(payload));

            var pivh = I2PHashSHA256.GetHash(tag.Value);

            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);

            return(new GarlicCreationInfo(
                       Destination.IdentHash,
                       cloves,
                       new EGGarlic(new BufRefLen(dest, 0, length)),
                       GarlicCreationInfo.KeyUsed.Aes,
                       SessionTags.Count(),
                       trackingid,
                       explack ? (uint?)ackmsg.MessageId : null,
                       LatestEGAckMessageId));
        }
Exemple #9
0
        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);
        }
Exemple #10
0
            public I2NPHeader16(I2NPMessage msg, uint messageid) : base(msg.Header16Buf)
            {
                MessageRef = msg;

                MessageType = msg.MessageType;
                Expiration  = I2PDate.DefaultI2NPExpiration();
                MessageId   = messageid;

                PayloadLength = (ushort)msg.Payload.Length;

                var s = I2PHashSHA256.GetHash(msg.Payload);

                PayloadChecksum = s[0];
#if DEBUG
                DebugCheckMessageCreation(MessageRef);
#endif
            }
Exemple #11
0
        public static BufLen Decrypt(BufLen data, I2PPrivateKey pkey, bool zeropad)
        {
            if (data == null || (zeropad && data.Length != 514))
            {
                throw new ArgumentException("ElGamal padded data to decrypt must be exactly 514 bytes!");
            }
            if (!zeropad && data.Length != 512)
            {
                throw new ArgumentException("ElGamal data to decrypt must be exactly 512 bytes!");
            }

            var x = I2PConstants.ElGamalP.Subtract(pkey.ToBigInteger()).Subtract(BigInteger.One);

            BigInteger a, b;
            var        reader = new BufRefLen(data);

            if (zeropad)
            {
                reader.Seek(1);
                a = reader.ReadBigInteger(256);
                reader.Seek(1);
                b = reader.ReadBigInteger(256);
            }
            else
            {
                a = reader.ReadBigInteger(256);
                b = reader.ReadBigInteger(256);
            }

            var m2   = b.Multiply(a.ModPow(x, I2PConstants.ElGamalP));
            var m1   = m2.Mod(I2PConstants.ElGamalP);
            var m    = m1.ToByteArray(255);
            var hash = I2PHashSHA256.GetHash(m, 33, 222);

            if (!BufUtils.Equal(m, 1, hash, 0, 32))
            {
                throw new HashCheckFailException();
            }

            return(new BufLen(m, 33, 222));
        }
Exemple #12
0
        public static IEnumerable <TunnelDataMessage> MakeFragments(IEnumerable <TunnelMessage> messages, I2PTunnelId desttunnel)
        {
            var padcalc = CalculatePadding(messages, desttunnel);

            foreach (var one in padcalc.TDMessages)
            {
                //Logging.Log( "New message" );

                var writer = new BufRefLen(one.TunnelDataInstance.Payload);

                writer.Seek(24);   // TunnelID, IV, Checksum of "Tunnel Message (Decrypted)"
                if (one.PaddingNeeded > 0)
                {
                    //Logging.Log( "Padding " + one.PaddingNeeded.ToString() + " bytes" );
                    writer.Write(new BufRefLen(BufUtils.RandomNZ(one.PaddingNeeded)));
                }

                writer.Write8(0);   // The Zero
                one.TunnelDataInstance.SetFirstDeliveryInstructionPoint(writer.View);

                foreach (var frag in one.Fragments)
                {
                    var fragstart = new BufRefLen(writer);
                    frag.Append(writer);
                    //Logging.Log( "Fragment " + ( one.TunnelDataInstance.Writer - fragstart ).ToString() + " bytes" );
                }

                one.TunnelDataInstance.Checksum.Poke(I2PHashSHA256.GetHash(
                                                         one.TunnelDataInstance.FirstDeliveryInstruction,
                                                         one.TunnelDataInstance.IV), 0, 4);

                if (writer.Length != 0)
                {
                    Logging.LogCritical("TunnelData: MakeFragments. Tunnel block is not filled!");
                    throw new Exception("TunnelData message not filled. Something is wrong.");
                }
            }

            return(padcalc.TDMessages.Select(msg => msg.TunnelDataInstance));
        }
Exemple #13
0
        public static GarlicMessage EGEncryptGarlic(
            Garlic msg,
            I2PPublicKey pubkey,
            I2PSessionKey sessionkey,
            List <I2PSessionTag> newtags)
        {
            var cipher = new CbcBlockCipher(new AesEngine());

            var payload = msg.ToByteArray();
            var dest    = new BufLen(new byte[65536]);
            // Reserve header + 4 bytes for GarlicMessageLength
            var writer = new BufRefLen(dest, I2NPMaxHeaderSize + 4);

            // ElGamal block
            var egbuf         = new BufLen(new byte[222]);
            var sessionkeybuf = new BufLen(egbuf, 0, 32);
            var preivbuf      = new BufLen(egbuf, 32, 32);
            var egpadding     = new BufLen(egbuf, 64, 158);

            egpadding.Randomize();
            preivbuf.Randomize();
            sessionkeybuf.Poke(sessionkey.Key, 0);

            var iv = new BufLen(I2PHashSHA256.GetHash(preivbuf), 0, 16);

            ElGamalCrypto.Encrypt(writer, egbuf, pubkey, true);

            // AES block
            var aesstart = new BufLen(writer);
            var aesblock = new GarlicAESBlock(writer, newtags, null, new BufRefLen(payload));

            cipher.Init(true, sessionkey.Key.ToParametersWithIV(iv));
            cipher.ProcessBytes(aesblock.DataBuf);

            var length = writer - dest;

            dest.PokeFlip32((uint)(length - 4), I2NPMaxHeaderSize);

            return(new GarlicMessage(new BufRefLen(dest, I2NPMaxHeaderSize, length)));
        }
Exemple #14
0
        internal static byte[] Send(DHHandshakeContext context)
        {
            var clear  = new byte[304];
            var writer = new BufRefLen(clear);

            var keys = I2PPrivateKey.GetNewKeyPair();

            context.PrivateKey = keys.PrivateKey;
            context.Y          = keys.PublicKey;
            context.YBuf       = new BufLen(context.Y.Key);

            var sharedkey = BufUtils.DHI2PToByteArray(context.X.ToBigInteger().ModPow(context.PrivateKey.ToBigInteger(), I2PConstants.ElGamalP));

            context.SessionKey = new I2PSessionKey(sharedkey);

            writer.Write(context.YBuf);

            context.TimestampB = (uint)(DateTime.UtcNow - I2PDate.RefDate).TotalSeconds;

            writer.Write(I2PHashSHA256.GetHash(context.XBuf, context.YBuf));
            writer.WriteFlip32(context.TimestampB);
            writer.Write(BufUtils.Random(12));

            var key = new KeyParameter(context.SessionKey.Key.ToByteArray());

            var iv = context.YBuf.PeekB(context.YBuf.Length - 16, 16);

            context.Encryptor = new CbcBlockCipher(new AesEngine());
            context.Encryptor.Init(true, new ParametersWithIV(key, iv, 0, 16));

            iv = context.HXxorHI.PeekB(context.HXxorHI.Length - 16, 16);

            context.Dectryptor = new CbcBlockCipher(new AesEngine());
            context.Dectryptor.Init(false, new ParametersWithIV(key, iv, 0, 16));

            context.Encryptor.ProcessBytes(new BufLen(clear, 256, 48));

            return(clear);
        }
Exemple #15
0
        internal static void Receive(DHHandshakeContext context, BufLen data)
        {
            var reader = new BufRefLen(data);

            context.XBuf    = reader.ReadBufLen(256);
            context.X       = new I2PPublicKey(new BufRefLen(context.XBuf), I2PKeyType.DefaultAsymetricKeyCert);
            context.HXxorHI = reader.ReadBufLen(32);

            var HXxorHI = I2PHashSHA256.GetHash(context.XBuf);

            var idenhash = RouterContext.Inst.MyRouterIdentity.IdentHash;

            for (int i = 0; i < HXxorHI.Length; ++i)
            {
                HXxorHI[i] ^= idenhash.Hash[i];
            }

            if (!context.HXxorHI.Equals(HXxorHI))
            {
                throw new ChecksumFailureException("NTCP Incoming connection from " +
                                                   context.Client.DebugId + " HXxorHI check failed.");
            }
        }
Exemple #16
0
        public static BufLen Decrypt(BufLen data, I2PPrivateKey pkey, bool zeropad)
        {
            if (data == null || zeropad && data.Length != EncryptedPaddedLength)
            {
                throw new ArgumentException($"ElGamal padded data to decrypt must be exactly {EncryptedPaddedLength} bytes!");
            }

            if (!zeropad && data.Length != EncryptedShortLength)
            {
                throw new ArgumentException($"ElGamal data to decrypt must be exactly {EncryptedShortLength} bytes!");
            }

            var x = I2PConstants.ElGamalPMinusOne.Subtract(pkey.ToBigInteger());

            var reader = new BufRefLen(data);

            var readlen = zeropad
                        ? EncryptedPaddedLength / 2
                        : EncryptedShortLength / 2;

            var a = reader.ReadBigInteger(readlen);
            var b = reader.ReadBigInteger(readlen);

            var m2      = b.Multiply(a.ModPow(x, I2PConstants.ElGamalP));
            var m1      = m2.Mod(I2PConstants.ElGamalP);
            var m       = m1.ToByteArrayUnsigned();
            var payload = new BufLen(m, 33, ClearTextLength);
            var hash    = I2PHashSHA256.GetHash(payload);

            if (!BufUtils.Equal(m, 1, hash, 0, 32))
            {
                throw new HashCheckFailException();
            }

            return(payload);
        }
Exemple #17
0
        internal static void Receive(DHHandshakeContext context, BufLen data)
        {
            var reader = new BufRefLen(data);

            context.Y    = new I2PPublicKey(reader, context.RemoteRI.Certificate);
            context.YBuf = context.Y.Key;

            var sharedkey = BufUtils.DHI2PToByteArray(context.Y.ToBigInteger().ModPow(context.PrivateKey.ToBigInteger(), I2PConstants.ElGamalP));

            context.SessionKey = new I2PSessionKey(sharedkey);

            var key = new KeyParameter(context.SessionKey.Key.ToByteArray());

            var enciv = new BufLen(context.HXxorHI.BaseArray, context.HXxorHI.Length - 16, 16);
            var deciv = new BufLen(context.YBuf, context.YBuf.Length - 16, 16);

            context.Encryptor = new CbcBlockCipher(new AesEngine());
            context.Encryptor.Init(true, new ParametersWithIV(key, enciv.BaseArray, enciv.BaseArrayOffset, enciv.Length));

            context.Dectryptor = new CbcBlockCipher(new AesEngine());
            context.Dectryptor.Init(false, new ParametersWithIV(key, deciv.BaseArray, deciv.BaseArrayOffset, deciv.Length));

            var encrbuf = new BufLen(reader, 0, 32 + 4 + 12);

            context.Dectryptor.ProcessBytes(encrbuf);

            context.HXY        = reader.ReadBufLen(32);
            context.TimestampB = reader.ReadFlip32();

            var checkhash = I2PHashSHA256.GetHash(context.XBuf, context.YBuf);

            if (!context.HXY.Equals(checkhash))
            {
                throw new ChecksumFailureException("NTCP SessionCreated received HXY check failed!");
            }
        }
        public void UpdateHash()
        {
            var hash = I2PHashSHA256.GetHash(HashedArea);

            Hash.Poke(new BufLen(hash), 0);
        }
        public bool CheckHash()
        {
            var hash = I2PHashSHA256.GetHash(HashedArea);

            return(Hash.Equals(hash));
        }
        public IEnumerable <TunnelMessage> Process(IEnumerable <TunnelDataMessage> tdmsgs)
        {
            var result = new List <TunnelMessage>();

            RemoveUnmatchedFragments.Do(() =>
            {
                lock ( MessageFragments )
                {
                    var remove = MessageFragments.Where(p => p.Value.Created.DeltaToNow.ToMinutes > RememberUnmatchedFragmentsForMinutes).
                                 Select(p => p.Key).ToArray();
                    foreach (var key in remove)
                    {
                        Logging.LogDebug("TunnelDataFragmentReassembly: Removing old unmatched fragment for " + key.ToString());
                        MessageFragments.Remove(key);
                    }
                }
            });

            foreach (var msg in tdmsgs)
            {
                var hash = I2PHashSHA256.GetHash(msg.TunnelDataPayload, msg.IV);
                var eq   = BufUtils.Equal(msg.Checksum.PeekB(0, 4), 0, hash, 0, 4);
                if (!eq)
                {
                    // Do not stop processing, just throw away faulty data
                    // throw new SignatureCheckFailureException( "TunnelDataFragmentReassembly: SHA256 check failed in TunnelData" );
                    Logging.LogDebug("TunnelDataFragmentReassembly: SHA256 check failed in TunnelData");
                    continue;
                }

                var reader = (BufRefLen)msg.TunnelDataPayload;

                while (reader.Length > 0)
                {
                    var frag = new TunnelDataFragment(reader);

                    if (frag.FollowOnFragment)
                    {
                        List <TunnelDataFragment> fragments;

                        if (!MessageFragments.ContainsKey(frag.MessageId))
                        {
                            fragments = new List <TunnelDataFragment>();
                            MessageFragments[frag.MessageId] = new TunnelDataFragmentList(fragments);
                        }
                        else
                        {
                            fragments = MessageFragments[frag.MessageId].List;
                        }

                        if (fragments.Count <= frag.FragmentNumber)
                        {
                            fragments.AddRange(new TunnelDataFragment[frag.FragmentNumber - fragments.Count + 1]);
                        }
                        fragments[frag.FragmentNumber] = frag;

                        CheckForAllFragmentsFound(result, frag.MessageId, fragments);
                    }
                    else
                    {
                        if (frag.Fragmented)
                        {
                            List <TunnelDataFragment> fragments;

                            if (!MessageFragments.ContainsKey(frag.MessageId))
                            {
                                fragments = new List <TunnelDataFragment>();
                                MessageFragments[frag.MessageId] = new TunnelDataFragmentList(fragments);
                            }
                            else
                            {
                                fragments = MessageFragments[frag.MessageId].List;
                            }

                            if (fragments.Count == 0)
                            {
                                fragments.AddRange(new TunnelDataFragment[1]);
                            }
                            fragments[0] = frag;

                            CheckForAllFragmentsFound(result, frag.MessageId, fragments);
                        }
                        else
                        {
                            AddTunnelMessage(result, frag, frag.Payload.ToByteArray());
                        }
                    }
                }
            }

            return(result);
        }
Exemple #21
0
        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));
        }
Exemple #22
0
        public Garlic DecryptMessage(EGGarlic message)
        {
            lock ( SessionTags )
            {
                var old = SessionTags.Where(p => p.Key.Created.DeltaToNow.ToMinutes > (I2PSessionTag.TagLifetimeMinutes + 2)).ToArray();
                foreach (var one in old)
                {
                    SessionTags.Remove(one.Key);
                }
            }

            var egdata = message.EGData;
            var tag    = new I2PSessionTag(new BufRefLen(egdata, 0, 32));

            I2PSessionKey sessionkey;
            bool          found;

            lock ( SessionTags )
            {
                found = SessionTags.TryGetValue(tag, out sessionkey);
            }

            BufLen aesbuf;

            if (found)
            {
                aesbuf = new BufLen(egdata, 32);

                lock ( SessionTags )
                {
                    SessionTags.Remove(tag);
                }

#if LOG_ALL_TUNNEL_TRANSFER
                DebugUtils.LogDebug("ReceivedSessions: Working tag found for EGarlic.");
#endif

                var pivh = I2PHashSHA256.GetHash(tag.Value);

                Cipher.Init(false, sessionkey.Key.ToParametersWithIV(new BufLen(pivh, 0, 16)));
                Cipher.ProcessBytes(aesbuf);
            }
            else
            {
                BufLen egheader;
                try
                {
                    var egbuf = new BufLen(egdata, 0, 514);
                    egheader = ElGamalCrypto.Decrypt(egbuf, Key, true);
                }
                catch (Exception ex)
                {
                    DebugUtils.Log("ReceivedSessions", ex);
                    return(null);
                }

#if LOG_ALL_TUNNEL_TRANSFER
                DebugUtils.LogDebug("ReceivedSessions: Using ElGamal to decrypt.");
#endif

                sessionkey = new I2PSessionKey(new BufLen(egheader, 0, 32));
                var preiv     = new BufLen(egheader, 32, 32);
                var egpadding = new BufLen(egheader, 64);
                aesbuf = new BufLen(egdata, 514);

                var pivh = I2PHashSHA256.GetHash(preiv);

                Cipher.Init(false, sessionkey.Key.ToParametersWithIV(new BufLen(pivh, 0, 16)));
                Cipher.ProcessBytes(aesbuf);
            }

            GarlicAESBlock aesblock;

            try
            {
                aesblock = new GarlicAESBlock(new BufRefLen(aesbuf));
            }
            catch (Exception ex)
            {
                DebugUtils.Log("ReceivedSessions", ex);
                return(null);
            }

            if (!aesblock.VerifyPayloadHash())
            {
                DebugUtils.LogDebug("ReceivedSessions: DecryptMessage: AES block SHA256 check failed.");
                return(null);
            }

#if LOG_ALL_TUNNEL_TRANSFER
            DebugUtils.LogDebug("ReceivedSessions: Working Aes block received. " + SessionTags.Count.ToString() + " tags available.");
#endif

            if (aesblock.Tags.Count > 0)
            {
#if LOG_ALL_TUNNEL_TRANSFER
                DebugUtils.LogDebug("ReceivedSessions: " + aesblock.Tags.Count.ToString() + " new tags received.");
#endif
                lock ( SessionTags )
                {
                    foreach (var onetag in aesblock.Tags.ToArray())
                    {
                        SessionTags[new I2PSessionTag(new BufRef(onetag))] = sessionkey;
                    }
                }
            }

            return(new Garlic((BufRefLen)aesblock.Payload));
        }
Exemple #23
0
        public static (GarlicAESBlock, I2PSessionKey) RetrieveAESBlock(
            GarlicMessage garlic,
            I2PPrivateKey privatekey,
            Func <I2PSessionTag, I2PSessionKey> findsessionkey)
        {
            GarlicAESBlock result;

            var cipher = new CbcBlockCipher(new AesEngine());

            var tag        = new I2PSessionTag(new BufRefLen(garlic.EGData, 0, 32));
            var sessionkey = findsessionkey?.Invoke(tag);

#if LOG_ALL_LEASE_MGMT
            Logging.LogDebug($"Garlic: Session key found {sessionkey}");
#endif
            if (sessionkey != null)
            {
                var aesbuf = new BufLen(garlic.EGData, 32);
                var pivh   = I2PHashSHA256.GetHash(tag.Value);

                cipher.Init(false, sessionkey.Key.ToParametersWithIV(new BufLen(pivh, 0, 16)));
                cipher.ProcessBytes(aesbuf);

                try
                {
                    result = new GarlicAESBlock(new BufRefLen(aesbuf));

                    if (!result.VerifyPayloadHash())
                    {
                        Logging.LogDebug("Garlic: DecryptMessage: AES block SHA256 check failed.");
                        return(null, null);
                    }

                    return(result, sessionkey);
                }
                catch (ArgumentException ex)
                {
                    Logging.Log("Garlic", ex);
                }
                catch (Exception ex)
                {
                    Logging.Log("Garlic", ex);
                    return(null, null);
                }
            }

#if LOG_ALL_LEASE_MGMT
            Logging.LogDebug("Garlic: No session key. Using ElGamal to decrypt.");
#endif

            try
            {
                (result, sessionkey) = Garlic.EGDecryptGarlic(garlic, privatekey);
#if LOG_ALL_LEASE_MGMT
                Logging.LogDebug($"Garlic: EG session key {sessionkey}");
#endif
            }
            catch (Exception ex)
            {
                Logging.LogDebug("Garlic: ElGamal DecryptMessage failed");
                Logging.LogDebugData($"ReceivedSessions {ex}");
                return(null, null);
            }

            return(result, sessionkey);
        }
Exemple #24
0
 public bool VerifyPayloadHash()
 {
     return(PayloadHash == new BufLen(I2PHashSHA256.GetHash(Payload)));
 }