/// <summary> /// Tries to parse a possible Crype packet and dispatches the packet for further processing in case it's a valid packet /// </summary> /// <param name="sender">Sender of the packet</param> /// <param name="body">The message with the possible packet in it</param> private void TryParseAndDispatchPacket(User sender, string body) { byte[] packetBodyBytes = null; try { if (ValidationUtility.IsBase64String(body)) packetBodyBytes = Convert.FromBase64String(body); else return; } catch(FormatException) { return; } DEncodeValue parsedPacket = null; try { // try to decode a valid packet from the message var reader = new DEncodeReader(new MemoryStream(packetBodyBytes)); parsedPacket = reader.Read(); } catch { return; } // raise the event to dispatch the packet to be processed further if (PacketReceived != null) { PacketReceived(this, new ChatPacketReceivedEventArgs(new ReceivedPacket(sender, _chatImpl, parsedPacket))); } }
/// <summary> /// Parses a packet decrypting it if necessary. Returns the unwrapped plain packet and information about the options of the packet /// </summary> /// <param name="packet">The packet</param> /// <param name="targetedDecryptorCsp">RSA instance to decrypt targeted packets</param> /// <param name="untargetedMasterKey">Master key to decrypt untargeted packets on chat</param> /// <returns>The unwrapped packet and information about it</returns> public static PacketInfo UnwrapPacket(DEncodeValue packet, RSACryptoServiceProvider targetedDecryptorCsp, byte[] untargetedMasterKey) { var packetDict = (DEncodeDictionary) packet; var type = ((DEncodeString) packetDict.Items["ty"]).Value; if (type == "plain") { return new PacketInfo(packet, false, null, false, false); } if (type == "sigwrap") { var signedByKey = ((DEncodeArray) packetDict.Items["sb"]).Value; var signature = ((DEncodeArray) packetDict.Items["si"]).Value; var wrappedPacket = packetDict.Items["pa"]; var packetStream = new MemoryStream(); var writer = new DEncodeWriter(packetStream); writer.Write(wrappedPacket); var wrappedPacketBytes = packetStream.ToArray(); var validatorCsp = new RSACryptoServiceProvider(); validatorCsp.ImportCspBlob(signedByKey); if (!validatorCsp.VerifyHash(ComputeSha1Hash(wrappedPacketBytes), Sha1Csp.ToString(), signature)) { throw new CryptographicException("Invalid signature"); } var wrappedPacketInfo = UnwrapPacket(wrappedPacket, targetedDecryptorCsp, untargetedMasterKey); wrappedPacketInfo.IsSigned = true; wrappedPacketInfo.SignedByKey = signedByKey; return wrappedPacketInfo; } if (type == "targeted") { var encryptedPacketKey = ((DEncodeArray) packetDict.Items["ke"]).Value; var iv = ((DEncodeArray) packetDict.Items["iv"]).Value; var encryptedPacketBytes = ((DEncodeArray) packetDict.Items["pa"]).Value; // decrypt the packet key var packetKey = targetedDecryptorCsp.Decrypt(encryptedPacketKey, true); // decrypt the packet var decryptorCsp = CreatePacketCryptingAlgoInstance(); decryptorCsp.Key = packetKey; decryptorCsp.IV = iv; var decryptedPacketBytes = decryptorCsp.CreateDecryptor() .TransformFinalBlock(encryptedPacketBytes, 0, encryptedPacketBytes.Length); // parse the wrapped packet var reader = new DEncodeReader(new MemoryStream(decryptedPacketBytes)); var wrappedPacket = reader.Read(); var wrappedPacketInfo = UnwrapPacket(wrappedPacket, targetedDecryptorCsp, untargetedMasterKey); wrappedPacketInfo.IsTargeted = true; return wrappedPacketInfo; } if (type == "nontargeted") { var iv = ((DEncodeArray)packetDict.Items["iv"]).Value; var encryptedPacketBytes = ((DEncodeArray)packetDict.Items["pa"]).Value; // decrypt the packet var decryptorCsp = CreatePacketCryptingAlgoInstance(); decryptorCsp.Key = untargetedMasterKey; decryptorCsp.IV = iv; var decryptedPacketBytes = decryptorCsp.CreateDecryptor() .TransformFinalBlock(encryptedPacketBytes, 0, encryptedPacketBytes.Length); // parse the wrapped packet var reader = new DEncodeReader(new MemoryStream(decryptedPacketBytes)); var wrappedPacket = reader.Read(); var wrappedPacketInfo = UnwrapPacket(wrappedPacket, targetedDecryptorCsp, untargetedMasterKey); wrappedPacketInfo.IsUntargeted = true; return wrappedPacketInfo; } throw new Exception("Invalid packet type code"); }