Skip to main content

jetblack-negotiate-stream

A Python client for .Net NegotiateStream. It supports single sign on (SSO) and encryption.

This was tested using Python 3.8 on Windows 11.

Installation

Install from pypi.

pip install jetblack-negotiate-stream

Example

The following programs provide a simple echo server in C# and client in Python.

Client

This is an example of a Python client using the synchronous NegotiateStream class. Note the call to authenticate_as_client before reading and writing.

import socket

from jetblack_negotiate_stream import NegotiateStream

def main():
    hostname = socket.gethostname()
    port = 8181

    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.connect((hostname, port))

        stream = NegotiateStream(hostname, sock)

        # Do the client side negotiate handshake.
        stream.authenticate_as_client()

        for data in (b'first line', b'second line', b'third line'):
            # All reads and writes are encrypted.
            stream.write(data)
            response = stream.read()
            print("Received: ", response)

if __name__ == '__main__':
    main()

Async Client

This program uses NegotiateStreamAsync which is simply an asynchronous version of the NegotiateStream class demonstrated above.

import asyncio
import socket

from jetblack_negotiate_stream import NegotiateStreamAsync

async def main():
    hostname = socket.gethostname()
    port = 8181

    reader, writer = await asyncio.open_connection(hostname, port)

    stream = NegotiateStreamAsync(hostname, reader, writer)

    await stream.authenticate_as_client()
    for data in (b'first line', b'second line', b'third line'):
        stream.write(data)
        await stream.drain()
        response = await stream.read()
        print("Received: ", response)

    stream.close()
    await stream.wait_closed()

if __name__ == '__main__':
    asyncio.run(main())

Alternative Async Client

The following client follows the patterns demonstrated in the asyncio library using open_negotiate_stream. This follows the conventions of the asyncio open_connection function. The negotiation happens before the function returns, resulting in cleaner code.

import asyncio
import socket

from jetblack_negotiate_stream import open_negotiate_stream

async def main():
    hostname = socket.gethostname()
    port = 8181

    # Following the same pattern as asyncio.open_connection.
    reader, writer = await open_negotiate_stream(hostname, port)

    for data in (b'first line', b'second line', b'third line'):
        writer.write(data)
        await writer.drain()
        response = await reader.read()
        print("Received: ", response)

    writer.close()
    await writer.wait_closed()

if __name__ == '__main__':
    asyncio.run(main())

Server

Here is a trivial C# echo server for the clients.

using System;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;

namespace NegotiateStreamServer
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var listener = new TcpListener(IPAddress.Any, 8181);
            listener.Start();

            while (true)
            {
                Console.WriteLine("Listening ...");
                var client = listener.AcceptTcpClient();

                try
                {
                    Console.WriteLine("... Client connected.");

                    Console.WriteLine("Authenticating...");
                    var stream = new NegotiateStream(client.GetStream(), false);
                    stream.AuthenticateAsServer();

                    Console.WriteLine(
                        "... {0} authenticated using {1}",
                        stream.RemoteIdentity.Name,
                        stream.RemoteIdentity.AuthenticationType);

                    var buf = new byte[4096];
                    for (var i = 0; i < 3; ++i)
                    {
                        var bytesRead = stream.Read(buf, 0, buf.Length);
                        var message = Encoding.UTF8.GetString(buf, 0, bytesRead);
                        Console.WriteLine(message);
                        stream.Write(buf, 0, bytesRead);
                    }
                    stream.Close();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
        }
    }
}

Acknowledgements

The library uses the pyspnego library, and takes many ideas from net.tcp-proxy.

Metadata

Release files for jetblack-negotiate-stream 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jetblack-negotiate-stream 0.2.2
File Size Uploaded
jetblack-negotiate-stream-0.2.2.tar.gz 7.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jetblack-negotiate-stream 0.2.2
File Interpreter ABI Platform
jetblack_negotiate_stream-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 17.6 kB

Release files / jetblack-negotiate-stream-0.2.2.tar.gz

Download URL jetblack-negotiate-stream-0.2.2.tar.gz
Size 7.8 kB
Tags Source
SHA-256 checksum
How to use checksums
802bc76162ebc48f7237b725af160dca68cf11469b574af7a7a2fd0d24bb9389
BLAKE2b-256 checksum
How to use checksums
81f654c1e7894be785c2f8dab0a0620285c31c5bfbf6c4939de3011fa76390e4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.12 CPython/3.10.10 Darwin/21.6.0

Release files / jetblack_negotiate_stream-0.2.2-py3-none-any.whl

Download URL jetblack_negotiate_stream-0.2.2-py3-none-any.whl
Size 9.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b14b563929944ca503218be09be7aa1df3304a15faf0967e8e8d37dae03bd05f
BLAKE2b-256 checksum
How to use checksums
08e2ebaba1c4d187160ff863d058004f35a7acfbb46fc5f158363677bb3bbd15
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.12 CPython/3.10.10 Darwin/21.6.0

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page