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))); }
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())); } }
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); }
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)); } }
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); }
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); }
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); }
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)); }
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 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 }
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)); }
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)); }
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))); }
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); }
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."); } }
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); }
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); }
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 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)); }
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); }
public bool VerifyPayloadHash() { return(PayloadHash == new BufLen(I2PHashSHA256.GetHash(Payload))); }