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"); }
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)); } }
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"); }
public IKeyAgreement Deserialize(Stream stream) => _other.Deserialize(stream);