public Packet ChannelDecrypt(ICipherSetRemoteInfo channelInfo, Packet outer) { // We gotta have the primary components and something to decrypt if (outer.Body.Length < 25) { return(null); } var ci = (CS1ARemoteInfo)channelInfo; // Rip apart our packet byte[] token = outer.Body.Take(16).ToArray(); byte[] iv = outer.Body.Skip(16).Take(4).ToArray(); byte[] encryptedData = outer.Body.Skip(20).Take(outer.Body.Length - 24).ToArray(); byte[] dataMac = outer.Body.Skip(outer.Body.Length - 4).Take(4).ToArray(); // Make sure we're on the right channel if (!token.SequenceEqual(ci.Token)) { return(null); } // Validate us some hmac byte[] hmacKey = new byte[20]; Buffer.BlockCopy(ci.DecryptionKey, 0, hmacKey, 0, 16); Buffer.BlockCopy(iv, 0, hmacKey, 16, 4); var hmac = new HMac(new Sha256Digest()); hmac.Init(new KeyParameter(hmacKey)); hmac.BlockUpdate(encryptedData, 0, encryptedData.Length); byte[] mac = new byte[hmac.GetMacSize()]; hmac.DoFinal(mac, 0); var foldedMac = Helpers.Fold(mac, 3); if (!foldedMac.SequenceEqual(dataMac)) { // Get out of here with your bad data return(null); } // Everything seems ok. Get it decrypted byte[] aesIV = new byte[16]; Buffer.BlockCopy(iv, 0, aesIV, 0, 4); Array.Clear(aesIV, 4, 12); var cipher = new SicBlockCipher(new AesFastEngine()); var parameters = new ParametersWithIV(new KeyParameter(ci.DecryptionKey), aesIV); cipher.Init(false, parameters); var decryptedData = new byte[encryptedData.Length]; BufferedBlockCipher bufferCipher = new BufferedBlockCipher(cipher); var offset = bufferCipher.ProcessBytes(encryptedData, decryptedData, 0); bufferCipher.DoFinal(decryptedData, offset); // Build a packet and ship it off return(Packet.DecodePacket(decryptedData)); }
public Packet MessageDecrypt(Packet outer) { byte[] remoteKeyData = outer.Body.Take(21).ToArray(); byte[] ivData = outer.Body.Skip(21).Take(4).ToArray(); byte[] innerEncryptedData = outer.Body.Skip(25).Take(outer.Body.Length - 29).ToArray(); // Decode the body ECKeyPair remoteEphemeralKeys = ECKeyPair.LoadKeys(SecNamedCurves.GetByName("secp160r1"), remoteKeyData, null); var idAgreement = ECDHAgree(remoteEphemeralKeys.PublicKey, Key.PrivateKey); var agreedHash = Helpers.SHA256Hash(Helpers.ToByteArray(idAgreement, 20)); var aesKey = Helpers.FoldOnce(agreedHash); // Pad out the IV byte[] aesIV = new byte[16]; Array.Clear(aesIV, 0, 16); Buffer.BlockCopy(ivData, 0, aesIV, 0, 4); // Decrypt it var cipher = new BufferedBlockCipher(new SicBlockCipher(new AesFastEngine())); var parameters = new ParametersWithIV(new KeyParameter(aesKey), aesIV); cipher.Init(false, parameters); byte[] decryptedBody = new byte[innerEncryptedData.Length]; var offset = cipher.ProcessBytes(innerEncryptedData, decryptedBody, 0); cipher.DoFinal(decryptedBody, offset); Packet outPacket = Packet.DecodePacket(decryptedBody); return(outPacket); }
/// <summary> /// Decloak the given buffer and return the valid Packet from it /// </summary> /// <param name="buffer">A cloaked packet buffer.</param> static public Packet Decloak(byte[] buffer) { if (buffer.Length < 8 || buffer [0] == 0) { return(Packet.DecodePacket(buffer)); } byte[] nonce = buffer.Take(8).ToArray(); var parms = new ParametersWithIV(new KeyParameter(cloakKey), nonce); var chacha = new ChaChaEngine(20); chacha.Init(false, parms); byte[] outBuff = new byte[buffer.Length - 8]; chacha.ProcessBytes(buffer, 8, buffer.Length - 8, outBuff, 0); return(Decloak(outBuff)); }