Пример #1
0
        private void LoadInternal(Stream memory, IKeyAgreementFactory kexFac)
        {
            var versionInt = memory.ReadByte();

            if (versionInt < 0)
            {
                throw new EndOfStreamException();
            }
            var versionByte = (byte)versionInt;

            bool isClient           = (versionByte & 0b0000_1000) != 0;
            bool hasInit            = (versionByte & 0b0001_0000) != 0;
            bool hasRatchet         = (versionByte & 0b0010_0000) != 0;
            bool hasEcdh            = (versionByte & 0b0100_0000) != 0;
            bool hasServerPublicKey = (versionByte & 0b1000_0000) != 0;

            if (!isClient)
            {
                throw new InvalidOperationException("The provided state is not client state");
            }

            if (hasInit)
            {
                if (InitializationNonce == null || InitializationNonce.Length != MicroRatchetContext.InitializationNonceSize)
                {
                    InitializationNonce = new byte[MicroRatchetContext.InitializationNonceSize];
                }

                memory.Read(InitializationNonce, 0, MicroRatchetContext.InitializationNonceSize);
            }

            if (hasEcdh)
            {
                LocalEcdhForInit = kexFac.Deserialize(memory);
            }

            if (hasServerPublicKey)
            {
                if (ServerPublicKey == null || ServerPublicKey.Length != MicroRatchetContext.ExpectedPublicKeySize)
                {
                    ServerPublicKey = new byte[MicroRatchetContext.ExpectedPublicKeySize];
                }
                memory.Read(ServerPublicKey, 0, MicroRatchetContext.ExpectedPublicKeySize);
            }

            if (hasRatchet)
            {
                ReadRatchet(memory, kexFac);
            }

            Log.Verbose($"Read {memory.Position} bytes of client state");
        }
Пример #2
0
        protected void ReadRatchet(Stream stream, IKeyAgreementFactory kexFac)
        {
            List <EcdhRatchetStep> steps = new List <EcdhRatchetStep>();
            bool last         = true;
            bool secondToLast = false;

            for (; ;)
            {
                // check if this is still a ratchet record
                var b = stream.ReadByte();
                stream.Seek(-1, SeekOrigin.Current);
                if (b < 0 || (b & 0b1110_0000) == 0)
                {
                    break;
                }

                if (last)
                {
                    var genbytes = new byte[8];
                    stream.Read(genbytes, 0, 8);
                    genbytes[0] &= 0b0001_1111;
                    var rgeneration = BigEndianBitConverter.ToInt32(genbytes, 0); // hot
                    var sgeneration = BigEndianBitConverter.ToInt32(genbytes, 4); // hot and important

                    var ecdh           = kexFac.Deserialize(stream);
                    var nextRootKey    = new byte[KeySizeInBytes];
                    var sHeaderKey     = new byte[KeySizeInBytes];
                    var sNextHeaderKey = new byte[KeySizeInBytes];
                    var sChainKey      = new byte[KeySizeInBytes];
                    var rHeaderKey     = new byte[KeySizeInBytes];
                    var rNextHeaderKey = new byte[KeySizeInBytes];
                    var rChainKey      = new byte[KeySizeInBytes];
                    stream.Read(nextRootKey, 0, KeySizeInBytes);    // cold
                    stream.Read(sHeaderKey, 0, KeySizeInBytes);     // cold
                    stream.Read(sNextHeaderKey, 0, KeySizeInBytes); // cold
                    stream.Read(sChainKey, 0, KeySizeInBytes);      // hot and important
                    stream.Read(rHeaderKey, 0, KeySizeInBytes);     // cold
                    stream.Read(rNextHeaderKey, 0, KeySizeInBytes); // cold
                    stream.Read(rChainKey, 0, KeySizeInBytes);      // hot
                    steps.Add(EcdhRatchetStep.Create(ecdh, nextRootKey, rgeneration, rHeaderKey, rNextHeaderKey, rChainKey,
                                                     sgeneration, sHeaderKey, sNextHeaderKey, sChainKey));
                }
                else if (secondToLast)
                {
                    if ((b & 0b1000_0000) != 0)
                    {
                        // send and receive chain
                        var genbytes = new byte[8];
                        stream.Read(genbytes, 0, 8);
                        genbytes[0] &= 0b0001_1111;
                        var rgeneration = BigEndianBitConverter.ToInt32(genbytes, 0); // hot
                        var sgeneration = BigEndianBitConverter.ToInt32(genbytes, 4); // hot and important

                        var sHeaderKey = new byte[KeySizeInBytes];
                        var sChainKey  = new byte[KeySizeInBytes];
                        var rHeaderKey = new byte[KeySizeInBytes];
                        var rChainKey  = new byte[KeySizeInBytes];
                        stream.Read(sHeaderKey, 0, KeySizeInBytes); // cold
                        stream.Read(sChainKey, 0, KeySizeInBytes);  // hot and important
                        stream.Read(rHeaderKey, 0, KeySizeInBytes); // cold
                        stream.Read(rChainKey, 0, KeySizeInBytes);  // hot
                        steps.Add(EcdhRatchetStep.Create(null, null, rgeneration, rHeaderKey, null, rChainKey,
                                                         sgeneration, sHeaderKey, null, sChainKey));
                    }
                    else
                    {
                        // only sending chain - the client starts with only a sending chain as the first generation
                        var genbytes = new byte[4];
                        stream.Read(genbytes, 0, 4);
                        genbytes[0] &= 0b0001_1111;
                        var sgeneration = BigEndianBitConverter.ToInt32(genbytes, 0); // hot and important

                        var sHeaderKey = new byte[KeySizeInBytes];
                        var sChainKey  = new byte[KeySizeInBytes];
                        stream.Read(sHeaderKey, 0, KeySizeInBytes); // cold
                        stream.Read(sChainKey, 0, KeySizeInBytes);  // hot and important
                        steps.Add(EcdhRatchetStep.Create(null, null, 0, null, null, null,
                                                         sgeneration, sHeaderKey, null, sChainKey));
                    }
                }
Пример #3
0
        private void LoadInternal(Stream memory, IKeyAgreementFactory kexFac)
        {
            var versionInt = memory.ReadByte();

            if (versionInt < 0)
            {
                throw new EndOfStreamException();
            }
            var versionByte = (byte)versionInt;

            bool isClient           = (versionByte & 0b0000_1000) != 0;
            bool hasInit            = (versionByte & 0b0001_0000) != 0;
            bool hasRatchet         = (versionByte & 0b0010_0000) != 0;
            bool hasEcdh            = (versionByte & 0b0100_0000) != 0;
            bool hasClientPublicKey = (versionByte & 0b1000_0000) != 0;

            if (isClient)
            {
                throw new InvalidOperationException("The provided state is not server state");
            }

            if (hasInit)
            {
                if (ClientInitializationNonce == null || ClientInitializationNonce.Length != MicroRatchetContext.InitializationNonceSize)
                {
                    ClientInitializationNonce = new byte[MicroRatchetContext.InitializationNonceSize];
                }
                if (RootKey == null || RootKey.Length != KeySizeInBytes)
                {
                    RootKey = new byte[KeySizeInBytes];
                }
                if (FirstSendHeaderKey == null || FirstSendHeaderKey.Length != KeySizeInBytes)
                {
                    FirstSendHeaderKey = new byte[KeySizeInBytes];
                }
                if (FirstReceiveHeaderKey == null || FirstReceiveHeaderKey.Length != KeySizeInBytes)
                {
                    FirstReceiveHeaderKey = new byte[KeySizeInBytes];
                }
                if (NextInitializationNonce == null || NextInitializationNonce.Length != MicroRatchetContext.InitializationNonceSize)
                {
                    NextInitializationNonce = new byte[MicroRatchetContext.InitializationNonceSize];
                }

                memory.Read(ClientInitializationNonce, 0, MicroRatchetContext.InitializationNonceSize);
                memory.Read(RootKey, 0, KeySizeInBytes);
                memory.Read(FirstSendHeaderKey, 0, KeySizeInBytes);
                memory.Read(FirstReceiveHeaderKey, 0, KeySizeInBytes);
                memory.Read(NextInitializationNonce, 0, MicroRatchetContext.InitializationNonceSize);
            }

            if (hasEcdh)
            {
                LocalEcdhRatchetStep0 = kexFac.Deserialize(memory);
                LocalEcdhRatchetStep1 = kexFac.Deserialize(memory);
            }

            if (hasClientPublicKey)
            {
                if (ClientPublicKey == null || ClientPublicKey.Length != KeySizeInBytes)
                {
                    ClientPublicKey = new byte[32];
                }
                memory.Read(ClientPublicKey, 0, 32);
            }

            if (hasRatchet)
            {
                ReadRatchet(memory, kexFac);
            }

            Log.Verbose($"Read {memory.Position} bytes of server state");
        }
Пример #4
0
 public IKeyAgreement Deserialize(Stream stream) => _other.Deserialize(stream);