Im attempting to write a push server for the iPhone in C#. I have the following code:
// Create a TCP/IP client socket.
using (TcpClient client = new TcpClient())
{
client.Connect("gateway.sandbox.push.apple.com", 2195);
using (NetworkStream networkStream = client.GetStream())
{
Console.WriteLine("Client connected.");
X509Certificate clientCertificate = new X509Certificate(#"certfile.p12", passwordHere);
X509CertificateCollection clientCertificateCollection = new X509CertificateCollection(new X509Certificate[1] { clientCertificate });
// Create an SSL stream that will close the client's stream.
SslStream sslStream = new SslStream(
client.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
try
{
sslStream.AuthenticateAsClient("gateway.sandbox.push.apple.com");
}
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.");
client.Close();
return;
}
}
ect....
Only I keep receiving a exception:
"A call to SSPI failed, see Inner exception"
Inner Exception -> "The message received was unexpected or badly formatted."
Does anyone have any idea whats going wrong here?
Figured it out. Replaced sslStream.AuthenticateAsClient("gateway.sandbox.push.apple.com"); with sslStream.AuthenticateAsClient("gateway.sandbox.push.apple.com", clientCertificateCollection, SslProtocols.Default, false); And registered the certificates on the PC.
Edit: Here is the code for creating a payload as requested:
private static byte[] GeneratePayload(byte [] deviceToken, string message, string sound)
{
MemoryStream memoryStream = new MemoryStream();
// Command
memoryStream.WriteByte(0);
byte[] tokenLength = BitConverter.GetBytes((Int16)32);
Array.Reverse(tokenLength);
// device token length
memoryStream.Write(tokenLength, 0, 2);
// Token
memoryStream.Write(deviceToken, 0, 32);
// String length
string apnMessage = string.Format ( "{{\"aps\":{{\"alert\":{{\"body\":\"{0}\",\"action-loc-key\":null}},\"sound\":\"{1}\"}}}}",
message,
sound);
byte [] apnMessageLength = BitConverter.GetBytes((Int16)apnMessage.Length);
Array.Reverse ( apnMessageLength );
// message length
memoryStream.Write(apnMessageLength, 0, 2);
// Write the message
memoryStream.Write(System.Text.ASCIIEncoding.ASCII.GetBytes(apnMessage), 0, apnMessage.Length);
return memoryStream.ToArray();
} // End of GeneratePayload
From Zenox's comment:
use a different version of AuthenticateAsClient
sslStream.AuthenticateAsClient("gateway.sandbox.push.apple.com", clientCertificateCollection, SslProtocols.Default, false);
Other way is just to use X509Certificate2 and X509CertificateCollection2 classes.
I recently used Growl For Windows to push messages to the Prowl client on the IPhone from .Net code. So you might get your functionatlity without writing a push server yourself.
The "The message received was unexpected or badly formatted." error usually comes when you did not register the p12 certificate in Windows. (Under Vista, just double click on the p12 file and the import wizard will open)
In my case I had to delete all the certificate from my windows 8 and then re-install them in order to send push notifications to apple device.
I do not know why my certificates stop working, I am searching for the correct reason and will update here soon.
Related
I am kind of new to doing security and encryption, so if I just made a very dumb mistake, sorry in advance.
I need a server and a client communicating through a secure connection using SslStream. But my certificates don't work. I get the following error: System.NotSupportedException: 'The server mode SSL must use a certificate with the associated private key.'
My code was the microsoft example given in the documentation: https://learn.microsoft.com/en-us/dotnet/api/system.net.security.sslstream?view=netframework-4.8ss
I tried:
Self singed certs using makecert (Like in this post: SSLStream example - how do I get certificates that work?)
Certificates with OpenSSL
The procedure on this website: http://www.reliablesoftware.com/DasBlog/PermaLink,guid,6507b2c6-473e-4ddc-9e66-8a161e5df6e9.aspx
Using the .pfx file instead of the .cer file (like in this post:X509Certificate2 the server mode SSL must use a certificate with the associated private key), but got the following exception: Win32Exception: The certificate chain was issued by an authority that is not trusted.
All except the last one gave the System.NotSupportedException: 'The server mode SSL must use a certificate with the associated private key.' exception.
Does this mean that self-signed certificates don't work? Do I need to buy a certificate?
Edit:
Here is the code I used. It is the modified example (Sorry if it is terribly coded on my part) and is executable, simulating server and client and throws the exception:
class Program
{
static void Main(string[] args)
{
//Temporarily added the arguments here for you to see
args = new string[2] { #"C:\Users\jacke\Documents\CA\TempCert.cer", "FakeServerName" };
Console.WriteLine("Starting server in seperate thread...");
Task t = Task.Run(() => { Server.Initialize(args[0]); });
Task.Delay(500).Wait();
Client.RunClient(args[1]);
}
}
public static class Server
{
private static X509Certificate cert;
private static TcpListener server;
public static void Initialize(string certificate)
{
cert = X509Certificate.CreateFromCertFile(certificate);
server = new TcpListener(IPAddress.Any, 12321);
server.Start();
while (true)
{
Console.WriteLine("Waiting for a client to connect...");
TcpClient client = server.AcceptTcpClient();
ProcessClient(client);
}
}
private static void ProcessClient(TcpClient client)
{
SslStream sslStream = new SslStream(client.GetStream(), false);
try
{
sslStream.AuthenticateAsServer(cert, clientCertificateRequired: false, checkCertificateRevocation: true);
sslStream.ReadTimeout = 5000;
sslStream.WriteTimeout = 5000;
Console.WriteLine("Waiting for client message...");
string messageData = Helpers.ReadMessage(sslStream);
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
{
sslStream.Close();
client.Close();
}
}
}
public static class Client
{
private static Hashtable certificateErrors = new Hashtable();
public static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
return false;
}
public static void RunClient(string serverName)
{
TcpClient client = new TcpClient("localhost", 12321);
Console.WriteLine("Client connected.");
SslStream sslStream = new SslStream(
client.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
try
{
sslStream.AuthenticateAsClient(serverName);
}
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.");
client.Close();
return;
}
byte[] messsage = Encoding.UTF8.GetBytes("Hello from the client.<EOF>");
sslStream.Write(messsage);
string serverMessage = Helpers.ReadMessage(sslStream);
Console.WriteLine("Server says: {0}", serverMessage);
client.Close();
Console.WriteLine("Client closed.");
}
}
public static class Helpers
{
public static string ReadMessage(SslStream sslStream)
{
// Read the message sent by the server.
// The end of the message is signaled using the
// "<EOF>" marker.
byte[] buffer = new byte[2048];
StringBuilder messageData = new StringBuilder();
int bytes = -1;
do
{
bytes = sslStream.Read(buffer, 0, buffer.Length);
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.
if (messageData.ToString().IndexOf("<EOF>") != -1)
{
break;
}
} while (bytes != 0);
return messageData.ToString();
}
}
And here is how I created the certificates (as explained in the post I linked above):
makecert -sv RootCATest.pvk -r -n "CN=FakeServerName" RootCATest.cer
makecert -ic RootCATest.cer -iv RootCATest.pvk -n "CN=FakeServerName" -sv
TempCert.pvk -pe -sky exchange TempCert.cer
cert2spc TempCert.cer TempCert.spc
pvkimprt -pfx TempCert.spc TempCert.pvk
Additional information I entered with the commands above:
When asked for a by the first 2 commands password I left it blank
I checked export private key and set 'A' as a password for the last command
Then I imported the .pfx file in the local certificate store (I also tried machine wide earlier) and let the program pick the right store. It warned me that all certificates by the CA will be trusted and I should contact the CA to check this was indeed their certificate, but I proceeded. Then I ran the code (using the 'TempCert.cer' file I just created) and got the error. Any advice is highly appreciated!
If I recall correctly, a .cer file does not include a private key, and I assume by loading a certificate from file the certificate store is not checked. You could export a .pfx and include the private key in the export.
I don't know why the .pvk attempt failed though (never tried that format myself) - SslStream can definitely work with self-signed certificates; the client side just has to ignore the validation failure.
However if you've already imported it into the store, you should be able to load it directly:
using System.Security.Cryptography.X509Certificates;
// ...
using (X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates.Find(X509FindType.FindBySubjectName, "FakeServerName", false);
return new X509Certificate2(certs[0]);
}
Respoding to the error in your comment:
The credentials supplied to the package were not recognized
I don't know if I got exactly that message, but I do remember having to grant access to the user the app runs into. You'd have to open the correct certificates tool:
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-view-certificates-with-the-mmc-snap-in
(run mmc, select file/add snap-in, choose certificates)
Then grant user(s) access to the private key:
https://docs.secureauth.com/display/KBA/Grant+Permission+to+Use+Signing+Certificate+Private+Key
(right click the certificate, select all tasks/manage private keys)
So I have two Ruby programs, they are a client and server sockets programs and they work together exchanging messages. But a C# client does not work. I give MCVE, first the ruby client.
#socketClient.rb
#With thanks to https://code.likeagirl.io/socket-programming-in-ruby-f714131336fd
require "socket"
while sum = $stdin.gets.chomp # Read lines from the socket
socket = TCPSocket.open("localhost", 3000)
#puts "Starting the Client..................."
socket.puts sum
while message = socket.gets # Read lines from the socket
puts message.chomp
end
socket.close # Close the socket
end
#puts "Closing the Client..................."
and the server
#simplestSocketServer.rb
#With thanks to https://code.likeagirl.io/socket-programming-in-ruby-f714131336fd
require "socket"
port = 3000
ipAddress = "127.0.0.1"
server = TCPServer.open(ipAddress, port) # Server would listen on port 3000
loop { # Servers run forever
puts "Starting the Server, accepting connections on port " + port.to_s + "..................."
client_connection = server.accept # Establish client connect connection
begin
clientText = client_connection.gets.chomp
puts clientText
resp = "Acknowledged"
client_connection.puts("#{clientText}" + "#{resp}") # Send the answer to the client
client_connection.puts("Closing the connection with #{client_connection}")
rescue Exception => getException
puts "#{getException}"
end
client_connection.close # Disconnect from the client
}
and the C# console program
using System;
using System.Net.Sockets;
using System.Text;
namespace SimplestCSharpRubySocketsClient
{
class Program
{
static void Main(string[] args)
{
try
{
string ipAddress = "127.0.0.1";
Int16 portNumber = 3000;
TcpClient _client; _client = new TcpClient();
_client.Connect(ipAddress, portNumber);
System.Console.WriteLine("we have connected, seemingly ...");
NetworkStream stream;
stream = _client.GetStream();
Byte[] sendBytes = Encoding.UTF8.GetBytes("some text");
System.Console.WriteLine("writing and flushing some bytes ...");
stream.Write(sendBytes, 0, sendBytes.Length);
stream.Flush();
Byte[] recvBytes = new byte[_client.ReceiveBufferSize];
System.Console.WriteLine("_client.ReceiveBufferSize = " + _client.ReceiveBufferSize); // <--- this prints 65536
System.Console.WriteLine("waiting to read bytes ...");
stream.Read(recvBytes, 0, recvBytes.Length); //<--- hangs here
System.Console.WriteLine("comething came back ...");
string result = Encoding.UTF8.GetString(recvBytes);
string result2 = result.Substring(0, result.LastIndexOf("\r\n"));
_client.Close();
_client.Dispose();
_client = null;
}
catch (Exception ex)
{
//TODO figure out a better error handler
throw ex;
}
}
}
}
The C# program connects and writes bytes but when looking to read bytes it just hangs.
And be aware I am running the C# console program in Visual Studio with admin rights. The two ruby programs run in their own separate Windows console windows.
Folding in some feedback, I added another line in the ruby server to output the clientText. And it prints nothing, suggesting the server is not fully receiving the bytes. Is there a termination signal that C# is required to send?
Thanks in advance.
The problem here is that the C# client does not send a newline at the end of the string, like the Ruby version does (socket.puts sends a string with a newline at the end).
If you change your sendBytes array to include a \n in the payload like this:
Byte[] sendBytes = Encoding.UTF8.GetBytes("some text\n");
you will see that it prints comething came back ... on the console.
The newline is required because of the following gets in the Ruby server:
clientText = client_connection.gets.chomp
Since days I'm trying to get (JS)wss/(c#)SslStream connection to work in order to create a wss server in mono c#.
My Problem : When an incomming secure WebSocket connection is accepted by the server, I can't get data from it in order to begin the handshake process.
What I did so far :
I setup a TCPListener that accept the client giving me a TCPClient instance.
I get the stream from the TCPClient and create a SslStream from it.
I synchronously authenticate it with AuthenticateAsServer(X509Certificate2)
I unsuccessfully try to read data
Other details :
I note that if I use a Stream object instead of an SslStream one, I succed in getting data from it (but crypted as expected)
I tested to connect my WebSoket to same adress/port to Fleck (built on my box with Monodevelop too) using the same pfx certificate and got it working properly
I note also that Fleck throw messages saying it recieve 0 byte, then it close the connection and (in some way) reconnect it and get data properly from Socket/SslStream.
I don't get any error, SslStream seem to be correctly authenticated
I correctly connect clients in https and deal with requests on an another port in the same program
My Configuration :
OS : ArchLinux
C# : Mono .Net Framework 4.7
Browsers (Chromium & Firefox)
Despite of all my research so far I've not found the solution , maybe someone can help me to wonder what I miss here ...
Thanks in advance for any help !
The listen code :
public void AudioListen ()
{
audioComListener.Start ();
while (isAudioActive) {
TcpClient s = audioComListener.AcceptTcpClient ();
Stream clientStream;
string hellostr;
clientStream = getClientStream(s);
if(debugCommuncation)
{
logToFileLine("(KEY) HandShaking begins with "+s.Client.RemoteEndPoint.ToString ().Split (':') [0]);
}
if(!WebSocketHandshake(clientStream))
{
if(debugCommuncation)
{
logToFileLine("(KEY) (X) HandShake read 0 byte from "+s.Client.RemoteEndPoint.ToString ().Split (':') [0]);
}
s.Close();
return;
}
else
{
logToFileLine("(KEY) HandShaking OK with "+s.Client.RemoteEndPoint.ToString ().Split (':') [0]);
}
hellostr=streamReadLine(clientStream);
if(hellostr.IndexOf("hello:")==0)
{
string usrstr=hellostr.Split(':')[1];
User usr= Users.GetUser(usrstr);
if(usr!=null)
{
usr.TcpC=s;
User usrdest=usr.corresp;
if( usrdest!=null &&
usrdest.ByPass==null &&
usrdest.TcpC!=null)
{
Stream clientStream2 = getClientStream(usrdest.TcpC);
usr.ByPass=new TCPByPass(clientStream,clientStream2);
usrdest.ByPass=usr.ByPass;
}
}
}
Thread.Sleep (1);
};
}
Function to get the SslStream :
private Stream getClientStream(TcpClient s,bool forceHTTP=false)
{
Stream clientStream;
if(isSSL && !forceHTTP)
{
clientStream = new SslStream (s.GetStream ());
((SslStream)clientStream).AuthenticateAsServer(SrvCert);
// Set timeouts for the read and write to 5 seconds.
/**/clientStream.ReadTimeout = 5000;
clientStream.WriteTimeout = 5000;
//SecuDiag.MakeAllDiag(((SslStream)clientStream));
}
else
{
clientStream=s.GetStream ();
}
return clientStream;
}
Function that try to get data for hanshake purpose :
public bool WebSocketHandshake(Stream clientStream)
{
string hellostr;
// Here I test trying to get data (Also tried to use Stream.ReadByte())
Byte[] toto=new Byte[2048];
((SslStream)clientStream).Read(toto,0,2048);
if(toto[0]==0)return false;
Console.WriteLine("#############################################");
Console.WriteLine("toto array is {0} bytes long",toto.Length);
for(int t =0;t<10;t++)
{
for(int u =0;u<10;u++)
{
Console.Write(toto[t*10+u].ToString());
}
Console.WriteLine(";");
}
Console.WriteLine("#############################################");
// Trying to get data
//hellostr=streamReadLine(clientStream);
//Console.WriteLine(hellostr);
return true;
}
I think I solved the problem. I don't understand why, but I think its necessary to close the accepted connection just after accepting it iaoi the connection is wss. The the websocket wil automagically reconnect :)
I made a client server socket connection with sslStream but there is a a exception on server when the code reaches to line AuthenticateAsServer I searched in internet but I couldn't find a good answer why it happens.
I made the .pfx testfile in my project and made a simple password for it. I don't know the problem is from file or not.
the exception is in line: sslStream.AuthenticateAsServer(certificate);
basic exception is: a call to sspi failed
inner exception is: clientsThe client and server cannot communicate, because they do not possess a common algorithm
server is a little long and I add the part of code that exception happens and all of client code:
this is server:
public void AcceptCallBack(IAsyncResult ar)
{
// clients.Add(new myClient(server.EndAccept(ar)));
// try
// {
myClient c = new myClient();
// Socket handle = (Socket)ar.AsyncState;
TcpListener handle = (TcpListener)ar.AsyncState;
byte[] buff=new byte[2048] ;
// Socket hand = handle.EndAccept(out buff,ar);
TcpClient hand = handle.EndAcceptTcpClient(ar);
dowork.Set();
c.tcp = hand;
clients.Add(c);
// hand.BeginReceive(c.buffer, 0, c.buffer.Length, SocketFlags.None, new AsyncCallback(receiveIDCallBack), c);
using (SslStream sslStream = new SslStream(hand.GetStream()))
{
sslStream.AuthenticateAsServer(certificate);
// ... Send and read data over the stream
sslStream.BeginWrite(buff,0,buff.Length,new AsyncCallback(sendCallBack),c);
count++;
sslStream.BeginRead(c.buffer,0,c.buffer.Length,new AsyncCallback(receiveIDCallBack),c);
}
// }
// catch(Exception)
// {
// }
}//end of acceptcallback function
this is client:
using UnityEngine;
using System.Collections;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Net.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
public class sslCode : MonoBehaviour {
// private Socket _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private byte[] _recieveBuffer = new byte[8142];
static string server = "127.0.0.1";
TcpClient client;
public string message;
public string receive;
public string send;
private void SetupServer()
{
try
{
// client.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1500));
client = new TcpClient(server,1500);
message = "connected";
}
catch (SocketException ex)
{
Debug.Log(ex.Message);
message = ex.Message;
}
// _clientSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
// Create a secure stream
using (SslStream sslStream = new SslStream(client.GetStream(), false,
new RemoteCertificateValidationCallback(ValidateServerCertificate), null))
{
sslStream.AuthenticateAsClient(server);
// ... Send and read data over the stream
sslStream.BeginRead(_recieveBuffer, 0, _recieveBuffer.Length, new AsyncCallback(ReceiveCallback),null);
}
}
private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
throw new NotImplementedException();
}// end of setup server
private void ReceiveCallback(IAsyncResult AR)
{
//Check how much bytes are recieved and call EndRecieve to finalize handshake
using (SslStream sslStream = new SslStream(client.GetStream(), false,
new RemoteCertificateValidationCallback(ValidateServerCertificate), null))
{
sslStream.AuthenticateAsClient(server);
// ... Send and read data over the stream
int recieved = sslStream.EndRead(AR);
if (recieved <= 0)
return;
//Copy the recieved data into new buffer , to avoid null bytes
byte[] recData = new byte[recieved];
Buffer.BlockCopy(_recieveBuffer, 0, recData, 0, recieved);
//Process data here the way you want , all your bytes will be stored in recData
receive = Encoding.ASCII.GetString(recData);
//Start receiving again
sslStream.BeginRead(_recieveBuffer, 0, _recieveBuffer.Length, new AsyncCallback(ReceiveCallback), null);
}
}// end of receiveCallBack
private void SendData(string dd)
{
using (SslStream sslStream = new SslStream(client.GetStream(), false,
new RemoteCertificateValidationCallback(ValidateServerCertificate), null))
{
sslStream.AuthenticateAsClient(server);
// ... Send and read data over the stream
byte[] data = Encoding.ASCII.GetBytes(dd);
SocketAsyncEventArgs socketAsyncData = new SocketAsyncEventArgs();
socketAsyncData.SetBuffer(data, 0, data.Length);
sslStream.BeginWrite(data,0,data.Length,new AsyncCallback(sendcallback),null);
send = dd;
sslStream.BeginRead(_recieveBuffer, 0, _recieveBuffer.Length, new AsyncCallback(ReceiveCallback), null);
}
}
private void sendcallback(IAsyncResult ar)
{
}// end of send data
can this be problem of certificate file generated in vs or options of windows?
I searched a little more on internet and and I think there should be probability of algorithm mismatch that I use for my certificate file and what windows 8.1 can understand. i really don't know....
that algorithms that vs let me make for my certificate are "sha256RSA" and "sha1RSA"
thanks for your help
i made the .pfx testfile in my project
That's a Big Red Flag. Without knowing anything about the tools you use, the best guess is that you created a signing certificate. It is not suitable for key exchange. A failure-mode covered by this blog post.
Without knowing anything about your OS, I'd have to guess that you use Linux. In which case this question ought to be helpful. If that's a wrong guess then help yourself by googling "create self signed ssl certificate, add the appropriate keywords to select your OS and/or tool chain.
thank you my friends, i finally could find my problem.
the code needed a little edit but the main problem wasnt the code.
the problem was from the way certificate files work. i just had generated a pfx file and gave its address to code below:
sslStream.AuthenticateAsServer(server);
but now i made the pfx format in internet options and imported it to personal section, after that exported it to trusted root section, so cer format of that pfx file will be generateed that only contains the public key of that pfx file.
so right now code runs very well.
I'm using the moon aspn library for sending push notifications in asp.net and c#. I'm encountering the following error: Call to SSPI Failed; in the inner exception i have: Unknown error while processing the certificate; error code: -2147467259.
here is my code:
private void SendQueueToapple(IEnumerable<NotificationPayload> queue)
{
int i = 1000;
foreach (var item in queue)
{
if (!_conected)
{
Connect(_host, NotificationPort, _certificates);
var response = new byte[6];
--> --> --> _apnsStream.BeginRead(response, 0, 6, ReadResponse, new MyAsyncInfo(response, _apnsStream));<-- <-- <--
} try {
if (item.DeviceToken.Length == 64) //check lenght of device token, if its shorter or longer stop generating Payload.
{
item.PayloadId = i;
byte[] payload = GeneratePayload(item);
_apnsStream.Write(payload);
Logger.Info("Notification successfully sent to APNS server for Device Toekn : " + item.DeviceToken);
Thread.Sleep(1000); //Wait to get the response from apple.
}
else
Logger.Error("Invalid device token length, possible simulator entry: " + item.DeviceToken);
}
catch (Exception ex)
{
Logger.Error("An error occurred on sending payload for device token {0} - {1}", item.DeviceToken, ex.Message);
_conected = false;
}
i++;
}
}
This might be a certificate related problem. You have to create .cer and .p12 files. Pay close attention to these files. You first generate the .cer and I'm not going into detail here. There's enough material available. The problem comes when generating the .p12 file.
In your mac, go to the Keychain Access. Select "My Certificates" from the left pane. There you will see a list of certificates. Select the certificate you generated for push notifications. Right click and export. Make sure you DO NOT expand the certificate perform this step on the private key. That's where thing starts to go wrong.