PushMsgResult ProcessHello(ref Msg msg) { if (!CheckBasicCommandStructure(ref msg)) { return(PushMsgResult.Error); } Span <byte> hello = msg; if (!IsCommand("HELLO", ref msg)) { return(PushMsgResult.Error); } if (hello.Length != 200) { return(PushMsgResult.Error); } byte major = hello[6]; byte minor = hello[7]; if (major != 1 || minor != 0) { // client HELLO has unknown version number return(PushMsgResult.Error); } // Save client's short-term public key (C') hello.Slice(80, 32).CopyTo(m_cnClientKey); Span <byte> helloNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength]; HelloNoncePrefix.CopyTo(helloNonce); hello.Slice(112, 8).CopyTo(helloNonce.Slice(16)); m_peerNonce = NetworkOrderBitsConverter.ToUInt64(hello, 112); using var box = new Curve25519XSalsa20Poly1305(m_secretKey, m_cnClientKey); Span <byte> helloPlaintext = stackalloc byte[80]; bool isDecrypted = box.TryDecrypt(helloPlaintext, hello.Slice(120, 80), helloNonce); if (!isDecrypted) { return(PushMsgResult.Error); } helloPlaintext.Clear(); m_state = State.SendingWelcome; return(PushMsgResult.Ok); }
PullMsgResult ProduceHello(ref Msg msg) { msg.InitPool(200); Span <byte> helloNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength]; Span <byte> helloPlaintext = stackalloc byte[64]; Span <byte> helloBox = msg.Slice(120); // Prepare the full nonce HelloNoncePrefix.CopyTo(helloNonce); NetworkOrderBitsConverter.PutUInt64(m_nonce, helloNonce.Slice(16)); // Create Box [64 * %x0](C'->S) using var box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_serverKey); box.Encrypt(helloBox, helloPlaintext, helloNonce); Span <byte> hello = msg; HelloLiteral.CopyTo(hello); // CurveZMQ major and minor version numbers hello[6] = 1; hello[7] = 0; // 8-80 are left zeros for anti-amplification padding // Client public connection key m_cnPublicKey.CopyTo(hello.Slice(80)); // Short nonce, prefixed by "CurveZMQHELLO---" helloNonce.Slice(16).CopyTo(hello.Slice(112)); m_nonce++; return(PullMsgResult.Ok); }