An exciting addition to .NET Framework 3.5 is the System.Net.PeerToPeer namespace, located in the System.Net.dll assembly. The new namespace provides the core building blocks for creating peer to peer (P2P) applications in .NET.

Typically, a P2P communication has three phases:

  • Discovery: the process of dynamically locating peers and their associated network locations.
  • Connection: establishing a network connection between peers.
  • Communication: the process of passing data back and forth among peers.

The features of the System.Net.PeerToPeer namespace facilitate the discovery and connection of the peers. Communication must be performed using complementary techniques such as Sockets, HTTPWebRequest and WCF Peer Channel. The underlying technology is the Peer Name Resolution Protocol (PNRP) and it enables discovery and makes communication among peers possible by enabling serverless name resolution of any resource to a set of network endpoints. PNRP is responsible for two core tasks: publishing a PeerName for others to resolve and resolving a PeerName that was published by another peer and retrieving the associated metadata. Information about the PNRP protocol can be found on Microsoft’s website at www.microsoft.com/p2p.

Creating a Peer Name

The name of the peer can be created and registered and two ways: secured and unsecured. Secured names rely on public key cryptography and they cannot be spoofed after registration with PNRP.

PeerName p = new PeerName(“My PeerName”, PeerNameType.Secured);

or

PeerName p = new PeerName(“My PeerName”, PeerNameType.UnSecured);

Associating Metadata

The peer name can be have associated metadata, such as an IP address, a free-text comment and a binary blob. Metadata is handled by the PeerNameRegistration object.

PeerNameRegistration pnReg = new PeerNameRegistration();

pnReg.PeerName = new PeerName(“My PeerName”, PeerNameType.Secured);

pnReg.EndPointCollection.Add(new IPEndPoint(IPAddress.Parse(“<Insert an IP address to associate with the name>”), 8080));

pnReg.Comment = “<Insert up to 39 unicode char comment>”;

pnReg.Data = System.Text.Encoding.UTF8.GetBytes(“Up to 4KB associated with the name”);

If we want all local addresses to be registered with the peer name, we could use the PeerNameRegistration.UseAutoEndPointSelection and set it to true, instead of adding end points manually.

Clouds

In the PNRP context, a cloud is simply a set of computers and defines the scope to which names are published to or resolved from. When publishing a name, we need to determine which cloud (or scope) we want to publish the name to.

The current implementation of the PNRP protocol uses two clouds:

  • Link-local: only other peers on the same link can resolve the name.
  • Global: anyone on the Internet to resolve the name.

Publishing a Peer Name

Now that we’ve seen how to create a peer name and associate the relevant metadata, it’s time for us to publish the name with the PNRP. The code snippet below shows how it’s done:

PeerNameRegistration pnReg = new PeerNameRegistration();

pnReg.PeerName = new PeerName(“MyPeerName”, PeerNameType.Secured);

pnReg.Port = 8080;

pnReg.UseAutoEndPointSelection = true;

// Starting the registration means the name is published for other peers to resolve.

pnReg.Start();

Resolving Peer Names

Peer names registered with the PNRP can be resolved using the PeerNameResolver object. The resolving party must know the name in the first place, and then it can retrieve the associated metadata such as comments and IP endpoints. The PeerNameResolver object can be used in both synchronous and asynchronous scenarios.

PeerNameResolver resolver = new PeerNameResolver();

PeerNameRecordCollection collection = resolver.Resolve(new PeerName(“MyPeerName”, PeerNameType.Secured));

foreach (PeerNameRecord record in collection)

{

if (record.Comment != null)

{

         Console.WriteLine(record.Comment);

}

if (record.Data != null)

{

         Console.WriteLine(System.Text.Encoding.ASCII.GetString(record.Data));

}

foreach (IPEndPoint endpoint in record.EndPointCollection)

{

         Console.WriteLine(“Endpoint: “ + endpoint.ToString());

}

}

In order to resolve several peer names at once, the asynchronous scenario can be used such that the call to PeerNameResolver does not block.

Sample Code

I wrote a small application that demonstrates how to asynchronously resolve peer names. You need .NET Framework 3.5 on your machine and your machine should run Windows Vista, Windows Server 2008 or Windows XP SP2. The sample code was compiled using Visual Studio 2008 Beta 2.

Bruce Schneier has a story on a new Internet threat, the Storm: a worm, a Trojan horse and a bot all rolled into one. The details of this new threat are thrilling and the article is well worth the reading.

http://www.wired.com/politics/security/commentary/securitymatters/2007/10/securitymatters_1004

As I was working to implement the scalable distribution system I envisioned here, I needed a way to find the solution of a system of linear congruencies in the form of the Chinese Remainder Theorem.

Theory

Given a set of simultaneous congruencies

X Ai (mod mi)

for I = 1,…, r and for which the mi are pairwise relatively prime, the solution of the set of congruencies is

X = A1 * B1 * M / m1 + … + Ar * Br * M / mr (mod M)

where M = m1 * m2 * … * mr

and the bi terms are determined from bi * M / mi 1 (mod mi).

For instance, the set of congruencies:

X 3 (mod 27)

X 4 (mod 13)

X 2 (mod 11)

has the solution X = 2136.

C# Implementation

This is a screenshot of the code that solves the system equation above:

Here is the C# code for finding the solution of the Chinese Remainder Theorem. The code I wrote in C# also uses the code I published in a previous blog post.

Implementation of cryptography products often requires solving linear congruencies. Although the background theory is not complicated, actual implementation in a high-level language may not be straight-forward. Having the need for a linear congruence solver myself and because I could not find a decent C# implementation, I decided to share this piece of code with my readers. I included some theory stuff for your convenience.

Linear Congruence Theorem

If A and B are any integers and N is a positive integer, then the congruence

Ax B (mod N)

has a solution for x if and only if B is divisible by the greatest common divisor of A and N. When this is the case, and x0 is one solution of the congruence, then the set of all solutions is given by:

{ x0 + k * n / d } where k is a integer.

In particular, there will be exactly d = gcd(a,n) solutions in the set of residues {0,1,2,…,n-1}.

Examples

14x 5 (mod 55) has a single solution x = 20, as gcd(14, 55) is 1.

2x 4 (mod 34) has two solutions x=2 and x=19. Greatest common divisor of 2 and 34 is 2, therefore the congruence has two solutions.

Solving Linear Congruencies

In general solving equations of the form:

Ax B (mod N)

If the greatest common divisor d = gcd(A, N) divides B, then we can find a solution x to the congruence as follows: the extended Euclidean algorithm yields integers r and s such r * A + s * N = d. Then x = r * B / d is a solution. The other solutions are the numbers congruent to x modulo n/d.

For example, the congruence

2x 4 (mod 34)

has 2 solutions since gcd(2, 34) = 2 divides 4. The extended Euclidean algorithm gives (1)*2 + 0*34 = 2, i.e. r = 1 and s = 0. Therefore, one solution is x = 1*4/2 = 2. All other solutions are congruent to 2 modulo 17. Since the original equation uses modulo 34, the entire solution set in the range from 0 to 34 is x = {2, 19}.

C# Implementation

The LinearCongruence class is built using three parameters passed to the constructor: A, B and N corresponding to the terms of the congruence. The only public method is Solve which attempts to find the entire class of solutions. If no solutions are found, an exception is thrown.

Here is the output for linear congruence 2x 4 (mod 34):

The C# code is available here. I compiled it using Visual Studio 2008 Beta 2, but it should work with any other older C# compiler or with Mono. Hope this helps.