Use MachineKey.Protect Outside of ASP.NET - c#

I need to encrypt a cookie outside of ASP.NET (Console App, Powershell etc.) but since this cookie will eventually be read by my MVC application it needs to be encrypted with the same key.
I can use the MachineKey class outside of ASP.NET however I can't specify the encryption type or key as these are outlined in the application's web.config which doesn't exists in this context. Since there is no config the key is randomly generated everytime.
How can I encrypt data using the same decryption key below so it is guaranteed to be decrypted successfully later by my MVC application?
<machineKey
validationKey="207FE3B8E01D0FF81871D7F3EFC082A14341A7820942D24D3BEF8954CAE53D860F46FBCDDA73F752CE1052D475D442CC8C14FC814739A757D52D152EF5EE179E"
decryptionKey="326C47E59EB1B38AEA84DBC9633BB770C318A740E477C82F3A8D9506F030D953"
validation="SHA1" decryption="AES"
/>

Some possible ideas.
Just use an App.config with your console app and mirror the machine
key from the web.config of your main project.
Grab the machine key programatically. To do this you would need the
path of the machine key (perhaps you could store it in DB, windows
registry, or somewhere?). MSDN has some great examples of this method.
Grabbing the key is basically:
Configuration config = WebConfigurationManager.OpenWebConfiguration(configPath);
MachineKeySection configSection = (MachineKeySection)config.GetSection("system.web/machineKey");
Then it is just a matter of using the right method to encrypt the cookie. Keep in mind that some ASP.NET membership providers serialize additional data into the cookie so depending on which one you are using, this may not be possible. Also, if your app uses the UserData section of a cookie then this could break it.

Related

Are the data protection keys necessary for docker container?

I am getting the following error in my logs when running my application on a docker container.
[08:20:54 WRN] Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed. <s:Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository>
[08:20:54 WRN] No XML encryptor configured. Key {<some-id} may be persisted to storage in unencrypted form. <s:Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager>
I was reading into data protection keys, especially from this article https://www.edument.se/post/storing-the-asp-net-core-data-protection-key-ring-in-azure-key-vault?lang=en and it seems to be something that might be really important when deploying an app. However, what I don't understand is what is it being used for? I am not using identity or session cookies. And for the technologies I am using, I create my own keys to encrypt the information.(For example for JWT or for encrypting some text).
I do use cookies to set my jwt token by using the set-token header with HTTPonly flag. Could that be what the key is being created for?
I want to know in order to define if we should take action to make the keys persistent or if can just ignore it. I would appreciate it a lot if someone has some insight into this that is willing to share.
Here a screenshot of the file where the keys are being stored
Actually, the section What happens if I don’t configure the data protection service in ASP.NET Core? of the referenced post gives a great explanation of what it is used for.
And yes, setting HttpOnly=true means encrypting the cookie's value with the Key Ring. You can do a simple test: run your service locally in a docker container, perform the flow that sets the cookie on your browser, then remove the container and create a new one. Now try to perform the action that requires the cookie, and it will fail because your service can't longer decrypt the cookie's value.

How get GOOGLE api key of visitor directly from BROWSER?

Well, I am trying to distribute free software (C#), which uses GOOGLE-TRANSLATE. ( However, it needs API CREDENTIALS in order to work).
I cant disribute MY API key in application. So can I program my application, as it opened translate.google.com and get "visitor" api key for each individual user itself?
I've seen application in the past doing that.
Instead you should create a request for the key at the start of the program and then store the key in some config file.
If there is no key stored in the config file, prompt the user to add their key and give them instructions on getting a key from Google.

CookieTempDataProvider causes CryptographicException

I have an ASP.NET Core app (1.1 targeting full framework) that uses TempDataProvider to store some metadata about the currently logged-in user, such as their "display name" and some other preferences for the app. In my Startup.cs ConfigureServices method I have added the line
services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();
which is populated after login using (for example)
TempData["DisplayName"] = login.DisplayName;
This works well, creating an encrypted, chunked session cookie for the user named .AspNetCore.Mvc.CookieTempDataProvider. I can "peek" and clear on logout, etc. as I expect. However after some interval - perhaps the app pool going idle, but the browser session remaining active - I receive a CryptographicException:
System.Security.Cryptography.CryptographicException: The key {guid} was not found in the key ring
It appears that the browser session cookie is still good, but the server has lost its ability to decrypt and use it. Currently the only way to resolve is to manually clear the cookie and let the app create a new one.
Is there any way to protect against this behavior? I do want the contents of the cookie to be difficult/impossible to forge, and this seemed like a valid mechanism to achieve that.

ASP Website does not seem to use machineKey in Web.Config for FormsAuthentication.Decrypt

I want to pass the authentication cookie from my ASP.Net MVC 5 (.Net 4.5.1, hosted locally on iisexpress, run from Visual Studio) to my WCF Service (.Net 4.5.1, hosted locally on WcfSvcHost, run from same Visual Studio Solution) and decrypt it there.
I have configured both to use the same machinekey (Web.config for ASP, App.config for WCF):
<machineKey validationKey="930681CA8CDC1BC09118D6B37E4A1B7712CEDBBD9FA1E35407EA1CD440C7E6F2DB9E93DADAC4098F90ACC7417DBE57C196722FC67F313A6AAE0F946E2FF731B6" decryptionKey="714C9581DA522C636B2D97D80276D5ACC02C274A11ABF117C76181B0480D4AEA" validation="SHA1" decryption="AES" />
Both reference the Same System.Web.dll:
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5.1\System.Web.dll (v4.0.30319)
But when i try to pass the cookieString to my Service and call
FormsAuthenticationTicket tick = FormsAuthentication.Decrypt(cookieString);
I get the Following Error:
Unable to validate data
I tried it the other way around (generate a fake ticket on WCF service and decrypt on ASP website), which did not work either.
I can generate a ticket on the ASP website and decrypt it there just fine.
I can also generate a ticket on the Service and decrypt it there without any problems.
var t1 = new FormsAuthenticationTicket("foo", false, 1337);
var cookie = FormsAuthentication.Encrypt(t1);
var t2 = FormsAuthentication.Decrypt(cookie);
I also made a small Console app, created a ticket there and decrypted it on the WCF service without any problems.
So it seems like the ASP Website does not use the specified keys to encrypt or decrypt the data.
Does anyone know what i can do to solve this problem?
EDIT:
I followed this guide to obtain the cookie and pass it to my service.
http://thoughtorientedarchitecture.blogspot.de/2009/10/flowing-aspnet-forms-authentication.html
However as i said i tried copying the value of the encrypted cookie and decrypt it in a simple console app with the same machinekey and it did not work.
You also asked this at http://forums.asp.net/p/1956219/5581762.aspx. See my answer there:
In the WCF service, set <machineKey ... compatibilityMode="Framework45" />. This will cause it to use the same algorithm as ASP.NET.
(Also remember to change your machine key if you inadvertently copied & pasted your real key into the question above.)
Levi answered my question over here: http://forums.asp.net/t/1956219.aspx.
Adding will infer compatibilityMode="Framework45" to the machineKey section.
So to fix this bug, either add compatibilityMode="Framework45" to the machineKey section or add to the system.web section of your web.config of your ASP website.
I think you should do something like
var authCookie = FormsAuthentication.GetAuthCookie(userName, rememberUser.Checked);
// Get the FormsAuthenticationTicket out of the encrypted cookie
var ticket = FormsAuthentication.Decrypt(authCookie.Value);
// Create a new FormsAuthenticationTicket that includes our custom User Data
var newTicket = new FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration, ticket.IsPersistent, "userData");
// Update the authCookie's Value to use the encrypted version of newTicket
authCookie.Value = FormsAuthentication.Encrypt(newTicket);

Is Forms Authentication Ticket Decryption possible with PHP?

I'm a PHP developer who knows almost nothing about .NET. I've been asked by the .NET guys at work to translate .NET code that decrypts an authentication ticket into PHP so that the PHP code can then set the appropriate session variables for my application to run. Is this even possible? I'm staring at the code and it's baffling me. I'll keep trying if someone can tell me it's not a waste of time for some reason I don't even know. Thanks for any help!
Additional info: Can I even grab the ticket with PHP in the first place?
First off, open your machine.config and add in a machinekey entry. Set the decryption key and validation key according to a randomly generated ones from a machinekey generator for aspnet 2.0.
Be sure to use the default's, ie. AES and SHA1.
Now that you have the AES decrypt key, store it somewhere because you are going to need it on the php side.
In your dot net app, go into the web.config and get the forms auth cookie name, usually something like .ASPXAUTH
Now go to the PHP side. Download and set up an AES encryption library, like this one, http://phpseclib.sourceforge.net/documentation/
Then in PHP you can do something like this (this uses the phpsec lib):
set_include_path(get_include_path() . PATH_SEPARATOR . 'phpseclib');
include('Crypt/AES.php');
$authCookie = $_COOKIE['_ASPXAUTH'];
echo $authCookie;
$aes = new Crypt_AES();
$aes->setKey('BCDCBE123654F3E365C24E0498346EB95226A307857B9BDE8EBA6198ACF7F03C');
echo $aes->decrypt($authCookie);
Now what ends up coming out is going to first be pm + the SHA1 hash + a byte representation of the auth ticket. You must convert the serialized bytes to a string to make it readable. Can someone else iluminate on that last step?
As Gumbo said, you need to take into account the algorithms involved. The asp.net authentication ticket uses:
Create a serialized forms
authentication ticket. A byte array
representation of the ticket is
created.
Sign the forms authentication
ticket. The message authentication
code (MAC) value for the byte array
is computed by using the algorithm
and key specified by the validation
and validationKey attributes of the
machineKey element. By default, the
SHA1 algorithm is used.
Encrypt forms authentication ticket.
The second byte array that has been
created is encrypted by using the
Encrypt method of the
FormsAuthentication class. The
Encrypt method internally uses the
algorithm and key specified by the
decryption and decryptionKey
attributes on the machineKey
element. ASP.NET version 1.1 uses
the 3DES algorithm by default.
ASP.NET version 2.0 uses the
Rinjdael (AES) algorithm by default.
From Microsoft KB
The forms authentication ticket is
used to tell the ASP.NET application
who you are. Thus, ticket is building
block of Forms Authentication's
security.
The ticket is encrypted and signed
using the configuration
element of the server's Machine.config
file. ASP.NET 2.0 uses the
decryptionKey and the new decryption
attribute of the element
to encrypt forms authentication
tickets. The decryption attribute lets
you specify the encryption algorithm
to use. ASP.NET 1.1 and 1.0 use 3DES
encryption, which is not configurable.
Tampering with the ticket value is
determined by a failure to decrypt the
ticket on the server. As a result, the
user will be redirected to the logon
page.
If the application is deployed in a
Web farm, you must make sure that the
configuration files on each server
share the same value for the
validationKey and decryptionKey
attributes in the tag,
which are used for hashing and
decryption of the ticket respectively.
You must do this because you cannot
guarantee which server will handle
successive requests. For more
information about
FormsAuthenticationTicket encryption
and Web farm deployment
considerations, visit the following
MSDN Web site:
So, you can specify what encryption/decryption algorithm to follow and the key. You can use the same decryption logic in PHP.
If you know the decryption algorithm you sure can implement it in PHP.

Categories

Resources