Reputation: 185
I'm trying to create a C# TCP server to receive TCP data with SslStream on a Windows 2008 server from a client (objective C mobile application) sending TCP data.
I'm using Microsoft's sample code (NOTE: my modified version of that code is at the end of this question) i.e. it is the server code, just under the line "The following code example demonstrates creating an TcpListener that uses the SslStream class to communicate with clients.")
However, when I run this server code I get the following exception:
System.Security.Cryptography.CryptographicException: Cannot find the original si
gner.
at System.Security.Cryptography.CryptographicException.ThrowCryptographicExce
ption(Int32 hr)
at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromFile(
String fileName, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCer
tContextHandle& pCertCtx)
at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertific
ateFromFile(String fileName, Object password, X509KeyStorageFlags keyStorageFlag
s)
at System.Security.Cryptography.X509Certificates.X509Certificate.CreateFromCe
rtFile(String filename)
at SslTcpServer.LocationSslTcpServer.RunServer(String certificate) in c:\SslTcpServer\Program.cs:line 20
at SslTcpServer.Program.Main(String[] args) in c:\SslTcpServer\Program.cs:line 180
I've also tried the code at http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate.aspx and it throws a similar exception.
I got my SSL certificate from NameCheap. I purchased the EssentialSSL Wildcard certificate. I made a Created Certificate Request on the Windows 2008 server i.e. that gaint text starting with:
-----BEGIN NEW CERTIFICATE REQUEST-----
alots of random characters
-----END NEW CERTIFICATE REQUEST-----
and uploaded that gaint text file to NameCheap and got emailed a Certificate.cer
file.
public sealed class LocationSslTcpServer
{
static X509Certificate serverCertificate = null;
// The certificate parameter specifies the name of the file
// containing the machine certificate.
public static void RunServer(string certificate)
{
serverCertificate = X509Certificate.CreateFromCertFile(certificate);
// Create a TCP/IP (IPv4) socket and listen for incoming connections.
TcpListener listener = new TcpListener(IPAddress.Any, 8080);
listener.Start();
while (true)
{
Console.WriteLine("Waiting for a client to connect...");
// Application blocks while waiting for an incoming connection.
// Type CNTL-C to terminate the server.
TcpClient client = listener.AcceptTcpClient();
ProcessClient(client);
}
}
static void ProcessClient(TcpClient client)
{
// A client has connected. Create the
// SslStream using the client's network stream.
SslStream sslStream = new SslStream(
client.GetStream(), false);
// Authenticate the server but don't require the client to authenticate.
try
{
sslStream.AuthenticateAsServer(serverCertificate,
false, SslProtocols.Tls, true);
// Display the properties and settings for the authenticated stream.
DisplaySecurityLevel(sslStream);
DisplaySecurityServices(sslStream);
DisplayCertificateInformation(sslStream);
DisplayStreamProperties(sslStream);
// Set timeouts for the read and write to 5 seconds.
sslStream.ReadTimeout = 5000;
sslStream.WriteTimeout = 5000;
// Read a message from the client.
Console.WriteLine("Waiting for client message...");
string messageData = ReadMessage(sslStream);
Console.WriteLine("Received: {0}", messageData);
// Write a message to the client.
byte[] message = Encoding.UTF8.GetBytes("Hello from the server.<EOF>");
Console.WriteLine("Sending hello message.");
sslStream.Write(message);
}
catch (AuthenticationException e)
{
Console.WriteLine("Exception: {0}", e.Message);
if (e.InnerException != null)
{
Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
}
Console.WriteLine("Authentication failed - closing the connection.");
sslStream.Close();
client.Close();
return;
}
finally
{
// The client stream will be closed with the sslStream
// because we specified this behavior when creating
// the sslStream.
sslStream.Close();
client.Close();
}
}
static string ReadMessage(SslStream sslStream)
{
// Read the message sent by the client.
// The client signals the end of the message using the
// "<EOF>" marker.
byte[] buffer = new byte[2048];
StringBuilder messageData = new StringBuilder();
int bytes = -1;
do
{
// Read the client's test message.
bytes = sslStream.Read(buffer, 0, buffer.Length);
// Use Decoder class to convert from bytes to UTF8
// in case a character spans two buffers.
Decoder decoder = Encoding.UTF8.GetDecoder();
char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
decoder.GetChars(buffer, 0, bytes, chars, 0);
messageData.Append(chars);
// Check for EOF or an empty message.
if (messageData.ToString().IndexOf("<EOF>") != -1)
{
break;
}
} while (bytes != 0);
return messageData.ToString();
}
static void DisplaySecurityLevel(SslStream stream)
{
Console.WriteLine("Cipher: {0} strength {1}", stream.CipherAlgorithm, stream.CipherStrength);
Console.WriteLine("Hash: {0} strength {1}", stream.HashAlgorithm, stream.HashStrength);
Console.WriteLine("Key exchange: {0} strength {1}", stream.KeyExchangeAlgorithm, stream.KeyExchangeStrength);
Console.WriteLine("Protocol: {0}", stream.SslProtocol);
}
static void DisplaySecurityServices(SslStream stream)
{
Console.WriteLine("Is authenticated: {0} as server? {1}", stream.IsAuthenticated, stream.IsServer);
Console.WriteLine("IsSigned: {0}", stream.IsSigned);
Console.WriteLine("Is Encrypted: {0}", stream.IsEncrypted);
}
static void DisplayStreamProperties(SslStream stream)
{
Console.WriteLine("Can read: {0}, write {1}", stream.CanRead, stream.CanWrite);
Console.WriteLine("Can timeout: {0}", stream.CanTimeout);
}
static void DisplayCertificateInformation(SslStream stream)
{
Console.WriteLine("Certificate revocation list checked: {0}", stream.CheckCertRevocationStatus);
X509Certificate localCertificate = stream.LocalCertificate;
if (stream.LocalCertificate != null)
{
Console.WriteLine("Local cert was issued to {0} and is valid from {1} until {2}.",
localCertificate.Subject,
localCertificate.GetEffectiveDateString(),
localCertificate.GetExpirationDateString());
}
else
{
Console.WriteLine("Local certificate is null.");
}
// Display the properties of the client's certificate.
X509Certificate remoteCertificate = stream.RemoteCertificate;
if (stream.RemoteCertificate != null)
{
Console.WriteLine("Remote cert was issued to {0} and is valid from {1} until {2}.",
remoteCertificate.Subject,
remoteCertificate.GetEffectiveDateString(),
remoteCertificate.GetExpirationDateString());
}
else
{
Console.WriteLine("Remote certificate is null.");
}
}
public static void DisplayUsage()
{
Console.WriteLine("To start the server specify:");
Console.WriteLine("serverSync certificateFile.cer");
Environment.Exit(1);
}
}
class Program
{
static int Main(string[] args)
{
string certificate = null;
certificate = "Certificate.cer";
try
{
LocationSslTcpServer.RunServer(certificate);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
Console.ReadLine();
}
return 0;
}
}
Thanks in advance for helping!
Upvotes: 0
Views: 1723
Reputation: 165
I successfully used X.509 Digital Certificate Generator to:
For steps 4 and 5: From the Search Box (near the Windows start button - left bottom your desktop) typo: cert, then select the Manage Computer Certificates application.
Upvotes: 0