Beispiel #1
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);
        }
Beispiel #2
0
        public EGBuildRequestRecord(BufLen dest, BuildRequestRecord src, I2PIdentHash topeer, I2PPublicKey key)
        {
            Data = dest;
            var writer = new BufRefLen(Data);

            writer.Write(topeer.Hash16);

            var datastart = new BufLen(writer);

            ElGamalCrypto.Encrypt(writer, src.Data, key, false);
        }
Beispiel #3
0
        public void TestElGamal()
        {
            for (int i = 0; i < 20; ++i)
            {
                var data     = new BufLen(BufUtils.RandomBytes(222));
                var origdata = data.Clone();

                var enc = new BufLen(ElGamalCrypto.Encrypt(data, Public, true));

                var decryptdata = ElGamalCrypto.Decrypt(enc, Private, true);

                Assert.IsTrue(decryptdata == origdata);
            }
        }
Beispiel #4
0
        public void TestElGamalNoPad()
        {
            for (int i = 0; i < 20; ++i)
            {
                var egdata = new BufLen(new byte[512]);
                var writer = new BufRefLen(egdata);
                var data   = new BufLen(egdata, 0, 222);

                data.Randomize();
                var origdata = data.Clone();

                ElGamalCrypto.Encrypt(writer, data, Public, false);

                var decryptdata = ElGamalCrypto.Decrypt(new BufLen(egdata, 0, 512), Private, false);

                Assert.IsTrue(decryptdata == origdata);
            }
        }
Beispiel #5
0
        public void TestElGamal2()
        {
            var buf = new byte[514];

            for (int i = 0; i < 20; ++i)
            {
                var data     = new BufLen(BufUtils.RandomBytes(222));
                var origdata = data.Clone();

                var start  = new BufRefLen(buf);
                var writer = new BufRefLen(buf);
                ElGamalCrypto.Encrypt(writer, data, Public, true);
                var enc = new BufLen(start, 0, writer - start);

                var decryptdata = ElGamalCrypto.Decrypt(enc, Private, true);

                Assert.IsTrue(decryptdata == origdata);
            }
        }
Beispiel #6
0
        public void TestElGamal()
        {
            for (int i = 0; i < 20; ++i)
            {
                var egdata = new BufLen(new byte[514]);
                var writer = new BufRefLen(egdata);
                var data   = new BufLen(egdata, 0, 222);

                data.Randomize();
                var origdata = data.Clone();

                var eg = new ElGamalCrypto(Public);
                eg.Encrypt(writer, data, true);

                var decryptdata = ElGamalCrypto.Decrypt(egdata, Private, true);

                Assert.IsTrue(decryptdata == origdata);
            }
        }
Beispiel #7
0
        public void TestEGCompatibilityDecode()
        {
            var priv = new I2PPrivateKey(
                new BufRefLen(FreenetBase64.Decode(PRIVATE_KEY)),
                new I2PCertificate());

            var pub = new I2PPublicKey(
                new BufRefLen(FreenetBase64.Decode(PUBLIC_KEY)),
                new I2PCertificate());

            for (int i = 0; i < ENCRYPTED.Length; ++i)
            {
                var decr = ElGamalCrypto.Decrypt(
                    new BufLen(FreenetBase64.Decode(ENCRYPTED[i])),
                    priv,
                    true);

                var clear = new BufLen(Encoding.UTF8.GetBytes(UNENCRYPTED[i]));
                Assert.IsTrue(decr == clear);
            }
        }
Beispiel #8
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)));
        }
 public BuildRequestRecord Decrypt(I2PPrivateKey pkey)
 {
     return(new BuildRequestRecord(new BufRef(ElGamalCrypto.Decrypt(EncryptedData, pkey, false))));
 }
Beispiel #10
0
        public void TestEGDecrypt()
        {
            var mi =
                "niPls-Doz1DJ3ua4pQDwstMeqnmznBCU~qaxIidv" +
                "jTW~ohDDpq3BatYwTSM-fIr-eEy4Amdl-tWJTXRO" +
                "2UzftkuD1-t-Ix9EfED26KrUxnwx2fC74Haykj9L" +
                "oytqFTFbYj34kMCUDDbhAqv6Ep3EDY8Am7WYqSJL" +
                "stXXV4tUFZ~mteCm1qfNUbbl6itCUId7zcgkW6SX" +
                "rwdkno3Ul4H~WVDtmewlxdDbT-rYyOJTnp4Y39Mo" +
                "8B1ojtMuGCgtbk-LS4gJmlXeCJh~1kHiM-nLIB9W" +
                "rtq8O4weJ~-R36obERZofGOV3D3kSKSoawXVcq4V" +
                "BlQOHTn24LkTHYLh3O~0SZlT0KfU5WrqTZtu8jZ~" +
                "B0q-cvrfqqWcmCFCoKW3WSJ5D0qZi1e9sLMebM96" +
                "asSRFZvlOUp8xZm84Z-au~m3EmkAaF4QlAzufA~L" +
                "~1RFaepKpfng0eWfWG73H1daoL3c2e3Pt~5m07FR" +
                "ZMr6TZoj1IsuI7J-QXRGfvbuMjJqB-tMBQAEAAcA" +
                "ADJtDgiK2OMz6qSmopA~cLUMW~zQesBqsoYx9AEc" +
                "sOIkp4g8YgRK2jJhfY46h7aj76ftkV-5uF6xoDUG" +
                "kbIQGH3rjneTQ2wspOz2WRpQk0MW6Ugd0H~5vYK2" +
                "ekploxq2gOil0Ad1rz~uobpE2bBKYK9B-EEkRKEP" +
                "-GTX6DSyosFXxMC1I5cwLDWmXktdNVuzt56AxfcL" +
                "Nzh9gd1R4l903-aFRiY~VXFHg1NjWBPcjCCz6fpL" +
                "U0XIdg6hf~DNMnd5D4C27HYujxUi6tj42sikDCPu" +
                "P6CBGAH~j7vzqkDxW2wker91lwwp~6N8jN4xcvme" +
                "-EI27LPGnOICvpzxdVrKtpc0Ib4dOe8SFkvxSR4x" +
                "PDSGWFF-~vAELzyHTYiE07ahNw==";

            var myinfo = FreenetBase64.Decode(mi);

            var ed =
                "AAAOggAE3uf0930YRPZqauUGNYgj5Ix7aoMz0ZO8" +
                "OIYpRS9zFi6CHe-SXOCeZMgOSxdkp320s70lnAJ9" +
                "2Z0fjP9WbBeKuCPjZSyMa-MQ4Bq5Sv~iXK-5T~ui" +
                "m9WTMnwzWIltbt2Toncx-9aAGsIgoABUpzQ1yjsG" +
                "-DwSEazn1ZsGAxGXI74SqokXGBggerXCtAhpTOTJ" +
                "MsFteib29WhURmPxLXPxtoCqav8hEUjEyBy2pnPE" +
                "h-3fcZPhxfK5FI0h0vZO0ZATZx~0RDV9NyxwaAMy" +
                "llav8iG2nFmVd7hkvWSVdcaRp2gpZuDcM9aXb2yo" +
                "xIagerhVF8Dyfbib3YX8GP9tvOhBAGWSRlvNIW6i" +
                "ImwOHJPuCbD4f2Ombp2VENYfKH~Tc4JP53DOnLs0" +
                "1pMze3xLaK0LsoPwR2LgYfamxbGDINa8KNB0PXC7" +
                "l7zcO6vDuC~mlVgs6VkkC-kirW8QMpO9t7v49l3y" +
                "tqlHBLU~khJwBFYuQEoB78bt~RQANw6R6V12yRIE" +
                "oW8dGJh5P1eGAFgO24oHyfLdKB-vfm1SZQB5MVyU" +
                "Ec6Hv4AKDBsxFqzFbThSgURqWk~AL9v-LuMhz034" +
                "jq-fGZtUY3l~ogz12IxdJIJVsjvJ2jWE-8NyFzC5" +
                "NhCSYV8jgdbL56ISMNPT9PRuiIyMHJ1w1NfypZ3c" +
                "aHKEnIjBzpj6R-9~~8PjLvdNO9cVaur5OLOGf4Q3" +
                "ABbqj9rg5uMJYIrFgddB4uETzb97Iue8BJr8XTRh" +
                "mwihpOLabG9r1b4-X1Z1HpBZxp8ml3xlZ-Lw6zp3" +
                "rQj2O84fSr0pxQh04Q-gIPBq7d4fS74uHMhN6rMx" +
                "bydEq0QQe4cqHDlGO-WZuTmK0tN-vMkwgHRXlz18" +
                "AdFFTf4caSoYerKPCk07neOWn0Vop1ni3DTRL~Tv" +
                "k04ZxNLnuuuor8gBh~jVFS-S9EnKkLcWJtJFcVbY" +
                "y9ZK-4caSvFGz1-Qf0elJKA-cpx7-ivKIQLQEuhx" +
                "5U6FrnJvchbY4JaZq2QzXVRF8s7X04kYOWWmAPXt" +
                "C3xE58e9s4-5MJhLNjdsjXoJ0R9jBleMWF-RsVwy" +
                "QNlTtabQDtDUzVeEQNRAHu9nVc0mJ18NH04KFMbH" +
                "jTWpgY1wDFB9566C9OOKzK-gkTjzO5RlSwDn5sgN" +
                "iejCOqM0-4JzMlFQNCuhMvmYAglRG8dLDZ3WjYck" +
                "NiRqHP2iKMyGQThwIS~TCzc-i5WgNzjLKPnWhhKm" +
                "1uvsZiWdnVAn9IOsFuOYvuR5NBnRJb~lYWI~zlvT" +
                "8riNkMIrnCE4CF380NEPfulMM6~98XVtmuMTY-Im" +
                "Zut2O1kz0OCBvCiYClrFlSlVDVoYEbVmkyoBKjiq" +
                "dGdPtLC5FnX6eC2bcUNGFOOY32ozF3UUsaRWVMrC" +
                "Y824xhPxcCt2yiJ~rSXAEBN2qtVW90wYzamz9pw6" +
                "XiNUdhshjLrOb-qVAnC33Kak89wbPtMGh6uXljR4" +
                "YxZ3gW2Tl9LIu4~5QP~sS7plo19-bdRfL8uAZ63j" +
                "gy-fY71std81WBfthqlOTFJMf~c-EU8xj90O408z" +
                "qYfFty-wgBBfYeeHdyWAWrqbfwLCMlHGGN0M-dbV" +
                "SjzwgSeLTYbdPrX1Dr6NHxSnJ9br0sXfoFUao1xa" +
                "4FN556lbolHjV0ns~6IbOVWElDNNecsLxjTWKgdA" +
                "CrLdh2ZMFL9M56H2Xdz4Adsm5vY1K6kCcLPgbpgb" +
                "~~gl-Qq4AEc~-nV6fxpu7pmH3HfTXIm0aDtR1KG7" +
                "kEHv-MreoFvmWvnVCj6tqJr5LAOKCDTvm7cw5fYc" +
                "27gsskqG~SM~1TyPkF5sb5~xX1EkAYm9PC0pA9WG" +
                "1~M4640pRCzbVl7jWqf1B~RPc7FRs3wMZqHu6SJW" +
                "kDRfvupQeNU6TXTkVPwJZcfTElH9ajcu23ucNXP-" +
                "Glp-00AZZA2fwOzdJe8AlzBIReLRyWKza5hLqmAy" +
                "paI1e5wSFDgXH027-tXLCYw-l2rsHl2aDO-M0Psj" +
                "OOA4GhdBUlLZWdy6OAI1~vpssgFY9CUErqR6m7LA" +
                "mLa9NaBFtTt~ZUYgc0TyrYfXjecl-jxUcPnYEo3u" +
                "YiBx3kk73LQWI-jj4IqKxUf1Rjp6b~Vhw77NFQPr" +
                "vqe91ICRuo9XTMavCQP8R1Lg2R7CwljE2qLJ0qxM" +
                "UN34gUfOIdQzBi~ApnG~aLoRwwro2U2MA63RMKkZ" +
                "OoXpjAmPj1xGqsQ73bI3lpfpHFLbWm3Ax37t2aud" +
                "c7-nPoaKoNvNIC0~28jROr35UGCKNMSNmqrifhHB" +
                "wsIqqMrubLjjmts-ELHWZF~1AZEDKMGrF3j-zGVg" +
                "LAhaSCvG3CNjaHTiAkPXc5zRwFLi5XTof1QipptG" +
                "u~j6-0Kpcwb5aWUD4q0JFxJPd0pt5p8N8r8Y04RR" +
                "TSzzyQsC8iGUDsmQyAnsquvMBpMBoCd3pOsSwYu3" +
                "d0A7UAoEI0S3Cp4JPndz2waXB4RhJzmHQu3JYv3A" +
                "IzYNfKvLwkZVdky-e7MqHtrSJU6HErb7JE7CgtW1" +
                "Gv-WYaCGZZR5qt3x-43CCYN9qnLpSIOXL17yK6P1" +
                "wsc2lXnAj6IYzppaH6~CtP3WnrsiEzh6lznkQbDx" +
                "pFygHfhvQQBJbhfjLL6-0RWG52oVsurXnT4og0oW" +
                "0itSdrP2tFjKc3aFkG4toWyDpfEOS427cPxRRNv6" +
                "6uEq-giDYHxVuk5k4TQ9bBp4HaWSKS55vr-oz5FF" +
                "SjT~p3-7WViVeoSO4wbcO7x2djkaQ7rWm6eiggut" +
                "NKw3WVNTG-oEQWuauwWp7mHwbDmTC7i-j4dvxMfz" +
                "k4gRWFOZpOEXIuiVBp20Ljy53fqZaSmijYqJwpRi" +
                "l~g6h-gvc43GMdoC48ryj0ClTN209Ua20YN54lg~" +
                "izHnl6X-VnmgPr298LKe0COK0xlDLKj~tu2CIzi3" +
                "mNwe4eLWfsmKRGrcXMwfz7F2SfOfNpqXbpgAV9AZ" +
                "Qy-SPuqFxNTcmclIzWKudDECoUqADHu3-tLijV0m" +
                "uer990OtbKeSrW9ICCVpjrbh5aPezOLNXcDkfxGB" +
                "S~yLpUgLn1aCFQv6Bz1htwfEpeKfqQvwVfD17SoW" +
                "-8XBA2ORSqXGOL9x93tzmt1pspsfgehXTqEVerH9" +
                "H9qCAECvRtyHu7jh-DNxFtnA-w5PTg7sf0uKKMOf" +
                "qtvIrpJulVuPl~JX89aigeihJXAQoc-QD5aMBVYC" +
                "n55mgrYUEKfe4~yYYYdkJCG0zwD5mADMA-elcNUI" +
                "ojXYff~X4eJwm1upbS5LpVyH4D-F57JMJKBFOUA4" +
                "Z6i1qTjQInIDYeinHKRThB9hz3EIB18TvroAz5Yl" +
                "UdE-BmdrXsXHztucbfw4GQ5LamIGHeYrapJ4QkRm" +
                "s~a5kdy78FrTV4drRuqoGWlpB9MORKyUVKZbQJND" +
                "6ncPyrRLaVTXy4m~L2MZoi4mPifkH6JdCUtyHK4f" +
                "Z0Ch1CSjHBr~kN3FoQRW4fJ9SazZ7sreYJLHOBhf" +
                "IdJTlu6ZX~nVwDzBZSg-kDj0phD7iWSAy9tI-qjq" +
                "nLkoZZj7oDt~L1Z-M~pXgsZkfIYN2nfoC3JV~HFl" +
                "W7DB3HEphkpU2cCzr2-BBFGGftNup6O1rohh1OSD" +
                "1T9OOACf-VvRk~z1motf5Y9oboEljWgrsqXSgDWM" +
                "Nsmk7WBv0e8H8SaNiKwoRiT4Y6EVjIe5Ft5pw7r7" +
                "7s3RhsGA6EcmRT8POELuJz5Q7qK7rYbDw1Ooil9v" +
                "ebQ7Zo9m~FpTAGAnuIgcPvmFfcgdI9Y46SV1JK4f" +
                "N91F5dm~7BXZcstbE3cinOV7VEiUEUUPiZaW6dXv" +
                "7dEwrELbD0gFStVy5IGuy1gqsygVxCvQwXFZ2j0N" +
                "EpYr0NTIwEOWKol17u3UTBSY6zhhajSPxl1f0QeF" +
                "yybEcw41IHy1fDZ3RfihzHIislrcDYHQ3mr~kdYC" +
                "oUlK83CKpQL2NJPKtLXsx0ATPjSYOg9Q25rf9v8c" +
                "joNrHERzhbDgqeCIXmSF5nLEpys~yRKLYpl7RLPS" +
                "fptt5gLOVNLmp~Z4CAKjLN-aqMYNopmy92-u74fb" +
                "u-d7UftyaZHNgT2QNP7TDrwYfivNKRS6detKwTYH" +
                "fxVpGRDT2HIHXZE3xCfZa6YmfPCrl0kAKAt1NB4i" +
                "VBb~TJ0p43CuaMnT~Mu7vXkwGVKJtZ3bGQfUtEhJ" +
                "xh61nVfh3k1F3EuczB~f1ekAZDMa9qhkp-Rv67~S" +
                "97ASXgyz673QLIoksK2udHB0iHPL6H2pJlBpv4oH" +
                "4YnA0o4ejTUy5vLgret0ItpMao4waezWK8TMHAzD" +
                "STd76eOIacKbIYkuorpx2atQrHizDQ9vPSIvurH7" +
                "8gMHJ03JnYoh60zIvZIqDajTS9vrqIvvu5HaB2re" +
                "bqmfMx2XKEvjqEBA7hPdqXR6n9typIcj1tqdHK-h" +
                "9iOYkQ81u64y6SgYMxuXNd38AFTUUouh1OQp2jVv" +
                "pnLLR-vUT1-G-lO8Xw5wrlwx6G4BA3peKmaMIxBu" +
                "iJA0qLUc336-oFXvThUh2JwT9RshrKclS7vp-zc9" +
                "8dzAXxATuxKakXZaJGQ91xWyTkz8lFzuGnfWK5HF" +
                "CgNiOa2F8nbR5kzofCXyYHyRbp9pT8Ek1xAK0Ayp" +
                "FYwqfcVFZnhe0TXcup5UDgdFlroirzfJaDIbQKBz" +
                "O4cS68Kd4YV9HPgu2de84dz~PfIgredg-A-rKon8" +
                "1ZhGylOgaXCDNNag9mjdF7B5nFjddYytaOgFCTDR" +
                "G0ntFV8mMDIwxW9GZtt6MSJQSJqjdOM1ywFdPrdX" +
                "GDKnib~NO247LxGLa05wUZPMvg92~mPgg9SkD9v4" +
                "-g008LITmMajbpE8~0t-jijMKJkPCQxOaBsH5-fn" +
                "uToqxg-xm0d9wg48Xr5BmirS5UbC7pS-U9pKI1E8" +
                "vp~DWbxxRpulZYhgNq2-cR2w7ie01mDleoUv-tdk" +
                "T9L1erdyTAhHrw2YNe0SD8OmyvW4aPPsjAGMeg==";

            var egdata = FreenetBase64.Decode(ed);

            var di = new I2PDestinationInfo(new BufRefLen(myinfo));

            var decr = ElGamalCrypto.Decrypt(new BufLen(egdata, 4, 514), di.PrivateKey, true);
        }
Beispiel #11
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));
        }
Beispiel #12
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));
        }