Closed Data-Inquisitor closed 5 years ago
I understand UWA/UWP applications require additional permissions to access files outside of certain locations. You could try using the StorageFolder API to access your client.pfx
file in the application installation directory or granting your application broadFileSystemAccess
permissions.
https://docs.microsoft.com/en-us/windows/uwp/files/file-access-permissions
Thank you for the tip Colin. Although I no longer get an access denied error, I am still unable to load the certification. Here is the code I am working with. It is very simple. It includes the default App + code for loading certification and connecting to the NATS streaming server.
I think there may be an error in how I am using StorageFolder and StorageFile.
Here is the code. ` namespace Test {
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
//************************************
// get the default NATS options
var natsOptions = ConnectionFactory.GetDefaultOptions();
// Setup NATS to be "secure", then load and add a certificate into the NATS options.
// See https://github.com/nats-io/csharp-nats#tls for additional information.
natsOptions.Secure = true;
var results = GetCertificate();
X509Certificate2 certs = new X509Certificate2(results, "password"); //Process gets stuck at this stage
natsOptions.AddCertificate(certs);
natsOptions.Url = "nats://localhost:4222";
natsOptions.PingInterval = 1000;
natsOptions.Timeout = 10000;
var stanOptions = StanOptions.GetDefaultOptions();
stanOptions.NatsConn = new ConnectionFactory().CreateConnection(natsOptions);
var connection = new StanConnectionFactory().CreateConnection("CLUSTER_ID", "CLIENT_ID", stanOptions);
//****************************************
}
}
//*************************************************************
// The purpose of the code below is to extract the byte stream from the certificate file
//*************************************************************
public byte[] GetCertificate()
{
var stream = setStorageFolder();
return stream.Result; // stream.Result is NULL
}
private static async Task<byte[]> GetBytesAsync(StorageFile file)
{
byte[] fileBytes = null;
if (file == null) return null;
using (var stream = await file.OpenReadAsync())
{
fileBytes = new byte[stream.Size];
using (var reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(fileBytes);
}
}
return fileBytes;
}
public async Task<byte[]> setStorageFolder()
{
StorageFolder appFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFile file = await appFolder.GetFileAsync(@"PATH\client.pfx");
return await GetBytesAsync(file);
}
****************************************************************
/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
}
} `
It looks like you're getting closer, but honestly I'm haven't personally used the StorageFolder API. To test, have you tried setting permissions to broadFileSystemAccess
to ensure it is a file access issue in the API? If you can get the cert loaded, have you tried validating the X509 chain, with X509Certificate2.Verify
?
Closing due to inactivity, please re-open this if you're still having problems.
I am getting an error message when I try to load a .pfx certificate within a Universal Windows Application. This error does not occur when I execute the script in the Enabling TLS section (https://github.com/nats-io/stan.net) using a basic console app.
Specifically it is at this line where I get the error message. natsOptions.AddCertificate(new X509Certificate2("client.pfx", "password"));
Error message: Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException: 'Access is denied'.
Again, this error only occurs with the windows universal app and not in a basic console app. I am using the same NATS streaming server in both contexts.