I'm having a problem with my WCF push notification service. Every time it sends a push notification to apple, a new RSA is generated inside the "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys" folder. I think that the problem causing this might be related to the Apple p12 Certificate.
Why does that happen? Is there any way to prevent the generating of those RSA?
I'm using PushSharp library and my code looks like this:
pushBroker = new PushBroker();
pushBroker.RegisterAppleService(
new PushSharp.Apple.ApplePushChannelSettings(false, appleCert, p12Pass, false)
, null);
The temporary file is where Windows has put the RSA private key that it loaded out of the appleCert
PFX blob.
If the file appears, then disappears (since you called it a "temp" file), then everything's working as expected. If it appears and stays forever then PushSharp is loading the certificate with PersistKeySet, which says that the private key shouldn't be deleted.
I don't know if https://github.com/has-taiar/PushSharp.Web/blob/master/PushSharp.Apple/ApplePushChannelSettings.cs is the real source of ApplePushChannelSettings, but it'll do. Looking at that source, they seem to be using PersistKeySet
, making the file permanent.
You have two practical approaches:
1) Load the certificate into an X509Store as a one-time operation (using PersistKeySet on load because you need to for store persistence). The file becomes permanent, but gets used for forever, so it's cool.
2) Load the certificate yourself from the PFX and (ideally) Dispose the certificate when you're done. I don't know if you have any sort of on-shutdown notification that you can more-or-less reliably use, but calling cert.Dispose()
(or, on older Framework versions, cert.Close()
) is more reliable than waiting on the GC and Finalizer to do the cleanup for you.
If you do have a good shutdown event:
// Note that I'm not specifying any X509KeyStorageFlags here.
// You don't want it PersistKeySet (that's the whole point) and you don't
// need it to be exportable (unless you get exceptions without Exportable, in which case
// PushSharp is doing something naughty).
private X509Certificate _cert = new X509Certificate2(appleCert, p12CerPass);
...
_broker.RegisterAppleService(new PushSharp.Apple.ApplePushChannelSettings(_cert, false));
...
// In some OnShutdown type location
_cert.Dispose();
If not:
// Still don't specify any load flags. Especially not PersistKeySet.
var cert = new X509Certificate2(appleCert, p12CerPass);
_broker.RegisterAppleService(new PushSharp.Apple.ApplePushChannelSettings(cert, false));
No matter what you'll still end up with a permanently leaked file every time your process abnormally terminates, since the file-deletion code won't get a chance to kick in.
A solution exists to completely avoid creating the temporary file, and that is to use the EphemeralKeySet flag which was added to .NET Core 2.0 (currently in preview). It's not yet available in .NET Framework.
// Keep the private key in memory, never let it touch the hard drive.
var cert = new X509Certificate2(appleCert, p12CerPass, X509KeyStorageFlags.EphemeralKeySet);
_broker.RegisterAppleService(new PushSharp.Apple.ApplePushChannelSettings(cert, false));
But I don't know if PushSharp is available for .NET Core.