I am looking into creating a custom members login system (for learning) and I haven't been able to figure out the C# command to generate an encrypted hash.
Is there a certain namespace I need to import or anything like that?
Using the namespace System.Security.Cryptography:
MD5 md5 = new MD5CryptoServiceProvider();
Byte[] originalBytes = ASCIIEncoding.Default.GetBytes(originalPassword);
Byte[] encodedBytes = md5.ComputeHash(originalBytes);
return BitConverter.ToString(encodedBytes);
or FormsAuthentication.HashPasswordForStoringInConfigFile method
For my part, I purpose this function i use to get the gravatar picture profil:
you can use it like you want
public string getGravatarPicture()
{
MD5 md5 = new MD5CryptoServiceProvider();
Byte[] originalBytes = ASCIIEncoding.Default.GetBytes(email.ToLower());
Byte[] encodedBytes = md5.ComputeHash(originalBytes);
string hash = BitConverter.ToString(encodedBytes).Replace("-", "").ToLower();
return "http://www.gravatar.com/avatar/"+hash+"?d=mm";
}
Well, first of all an encryption hash is a contradiction. Like a vegetarian steak. You can use encryption, or you can hash them (and you should hash them), but hashing is not encryption.
Look up a class starting with Md5 ;) Or Sha1 - those are hash algoryithms. It is all there in .NET (System.Security.Cryptography namespace).
I prefer having my hash all in one concatenated string. I borrowed this to build my hash:
public static string MD5Hash(string itemToHash)
{
return string.Join("", MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(itemToHash)).Select(s => s.ToString("x2")));
}
Related
I know that in ASP.NET Core it is possible to automatically convert some query string to an object using special model binding attributes - [FromRoute], [FromQuery] and so on.
Is it possible to perform such a conversion manually? Something like:
var queryString = Request.QueryString;
var obj = SomeMagic.QueryStringToObject<MyClass>(queryString);
You can use QueryHelpers.ParseQuery(String) to parse a query string into a dictionary.
If you want the actual same behavior as provided by the [FromQuery] attribute I'd look at the QueryParameterValueSupplier.RenderParametersFromQueryString method, which does most of the heavy-lifting. I'm not sure if this is meant to be used outside of the existing ASP.NET Core framework infrastructure.
Note that a query string is just a collection of string-based name-value pairs. There's no standard that dictates how this should be mapped to something more complex like a Java or C# class. So frameworks like ASP.NET Core build their own convention on top of that, in order to make their complex binding mechanisms work. (e.g. foo.bar[2]=123). ASP.NET Core actually has two ways of binding query strings to a model (the "MVC" way and the "jQuery" way), see JQueryKeyValuePairNormalizer.
// This is a helper method for Model Binding over a JQuery syntax.
// Normalize from JQuery to MVC keys. The model binding infrastructure uses MVC keys.
// x[] --> x
// [] --> ""
// x[12] --> x[12]
// x[field] --> x.field, where field is not a number
private static string NormalizeJQueryToMvc(StringBuilder builder, string key)
Finally on a personal note I tend to avoid the query string for anything more complex than simple name-value pairs. When you start to pull in more complex data structures you also run into many limitations. For instance: differentiating between null and empty strings; awkward syntax for handling collections; etc. If I really must use the query string for passing along complex data structures, I fallback to a single Base64 encoded JSON-string and handle that manually within my code.
Finally I found more generic solution than just parsing a query string. Here I get an instance of IModelBinder (actually an instance of ComplexObjectModelBinder) and use that as a service.
// DTO
//
public class PersonName
{
public string FirstName { get;set; }
public string LastName { get;set; }
}
// Action handler
// Here I want to convert HTTP request to an instance of PersonName manually
// Example: /SearchByName?LastName=Doe&FirstName=John
//
[AcceptVerbs("GET")]
public async Task<IActionResult> SearchByName(
[FromServices] IModelMetadataProvider modelMetadataProvider,
[FromServices] IModelBinderFactory modelBinderFactory)
{
var valueProvider = await CompositeValueProvider.CreateAsync(ControllerContext);
var modelMetadata = modelMetadataProvider.GetMetadataForType(typeof(PersonName));
var modelBinderFactoryContext = new ModelBinderFactoryContext
{
Metadata = modelMetadata,
CacheToken = modelMetadata
};
var modelBinder = modelBinderFactory.CreateBinder(modelBinderFactoryContext);
var modelBindingContext= DefaultModelBindingContext.CreateBindingContext(ControllerContext, valueProvider, modelMetadata, new BindingInfo(), string.Empty);
await modelBinder.BindModelAsync(modelBindingContext);
var personName = modelBindingContext.Model as PersonName;
// ...
return Ok(personName);
}
I have data that I only want to make available in three different HTTP POSTs (think of a workflow) and I don't want to use a QueryString, or a Cookie for this information. For this reason, I think the concept of _viewstate applies here.
So, how should I emulate ViewState in ASP.NET MVC as a encrypted hidden field that includes confidentiality and authentication?
Does the ASP.NET 4 or newer framework include this?
More Information
ASP.NET used an encrypted Viewstate as a hidden field in a form. One of the benefits of this is that the cryptography was "authenticated", meaning that any tampering would be detected in addition to the privacy features available in an encrypted payload.
There are many many questions on this site that discuss how to retrofit Viewstate into ASP.NET MVC, but no answers I've seen address the encryption of the data that includes these features to the serialized data:
Confidentiality (privacy)
Authentication (no modifications)
It wasn't "Classic ASP" (which is the COM-heavy, VBScript-friendly platform that was popular from 1997 to 2003) but ASP.NET WebForms which used ViewState. ViewState itself was a Base64-encoded (not encrypted) representation of the page's controls' properties. This was done because HTML Forms don't transmit additional properties back to the server, only <input>s' value="" attributes, so the ViewState included things like a control's background color property (if it was set).
In WebForms, developers could use ViewState validation MAC to ensure their viewstate data wasn't altered, but in practice it frequently broke down. If you search for "Validation of viewstate MAC failed" then you'll find countless discussions on how to workaround the issue. However that is an irrelevant point in my post.
If you want to use a client form field as a roundtrip data vector, then that's perfectly fine, just do something like the code below.
class PageViewModel {
public String SecretData;
}
public ActionResult Foo() {
Byte[] someSecretData = GetIcbmLaunchCodes();
someSecretData = ArbitraryEncryptionAlgorithm( someSecretData ); // you can encrypt the data any way you want. I personally recommend a symmetric algorithm like AES or TripleDES.
HashAlgorithm hashAlgo = new HMACSHA1();
hashAlgo.Key = /* Your private key for HMAC */
Byte[] hmac = hashAlgo.ComputeHash( someSecretData );
// when using SHA1, hmac will be 160 bits long, or 20 bytes.
PageViewModel model = new PageViewModel();
model.SecretData = Convert.ToBase64String( hmac + someSecretData ); // array concatenation is an exercise for the reader
return View( model );
}
[HttpPost]
public ActionResult Foo(PageViewModel model) {
Byte[] postedData = Convert.FromBase64String( model.SecretData );
Byte[] hmac = postedData[0...20]; // array substring is an exercise for the reader
Byte[] secretData = postedData[20...n];
// Now verify the secret data
HashAlgorithm hashAlgo = new HMACSHA1();
hashAlgo.Key = /* Your private key for HMAC */
Byte[] hmac2 = hashAlgo.ComputeHash( secretData );
if( hmac2 != hmac ) {
/* the data has been tampered with. */
} else {
/* the data is unadulterated */
Byte[] originalSecretData = ArbitaryDecryptionAlgorithm( secretData );
}
}
I want to utilise some form of "simple" encryption that is reasonably secure but very low friction in terms of impact on development process.
Supposing I own both sides of the conversation in a client <> web service situation. My application is a windows phone/win8/silverlight/desktop app and the server is ASP.Net MVC or WebAPI.
In my mind, I want something as simple as:-
<security encryption="off|sometype|someothertype">
<privatekey>12345MyKey54321</privatekey>
</security>
as some form of configuration parameter on both the client and server. Additionally an authentication routine will return and store some form of public key.
Doing so will enable the 'encryption mode' and result in any http requests being encrypted & hashed in the selected manner using the provided keys. The end result being anything sniffed on the local, proxy or remote machines would not be able to view the data without the key and decryption method. On the server, data is decrypted using the same key before hitting controller actions.
Other than swapping out HttpRequest/WebClient calls for something like EncryptedHttpRequest and adding the appropriate hook on the MVC/WebAPI side of things, all other client code and controller actions would be ignorant to the fact the data was encrypted.
Am I missing something or could setup not be this simple? As far as I have searched there is nothing that offers this level of simplicity so I figure I'm missing some gaping flaw in my logic?
All you are looking for can be achieved by simply using HTTPS. Just buy a certificate (or use a self-signed certificate) and there is your encryption.
Do not re-invent the wheel.
I've done this successfully. It isn't too difficult and works well. I use it for activating a license for a product. The most important thing is that your truly control the client and server - no one can extract your private key from your code on the client.
Step 1: Create an MVC controller action method that takes no arguments:
[HttpPost] public ActionResult Activate() { ... }
Step 2: In the controller just use the HttpRequest.InputStream to get ahold of the bytes sent from the client.
var stream = this.HttpContext.Request.InputStream;
Step 3: Create a CryptoStream to deserialize.
I've included creating both encryption and decryption examples here. The sharedSecret is a byte[] of sufficient length (512 bytes) of random bytes - this is what you protect!
public CryptoStream CreateEncryptionStream(Stream writeStream)
{
TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();
PasswordDeriveBytes derivedBytes = new PasswordDeriveBytes(this._sharedSecret, null);
CryptoStream cryptoStream = new CryptoStream(writeStream, cryptoProvider.CreateEncryptor(derivedBytes.GetBytes(16), derivedBytes.GetBytes(16)), CryptoStreamMode.Write);
return cryptoStream;
}
public CryptoStream CreateDecryptionStream(Stream readStream)
{
TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();
PasswordDeriveBytes derivedBytes = new PasswordDeriveBytes(this._sharedSecret, null);
CryptoStream cryptoStream = new CryptoStream(readStream, cryptoProvider.CreateDecryptor(derivedBytes.GetBytes(16), derivedBytes.GetBytes(16)), CryptoStreamMode.Read);
return cryptoStream;
}
Step 4: Use your CryptoStream another stream reader to decrypt.
I use an XmlReader so that all my existing serialization code can work either in the clear (when reading/writing to disk or database on the server) or encrypted (when transmitting).
using (var reader = XmlReader.Create(decryptionStream, settings)) { ... }
Step 5: Formulate a secure response in your controller.
This is doing the reverse of Steps 1-4 to encrypt your response object. Then you just write your encrypted response to a memory stream and return it as a File result. Below, I've shown how I do this for my license response object.
var responseBytes = GetLicenseResponseBytes(licenseResponse);
return File(responseBytes, "application/octet-stream");
private byte[] GetLicenseResponseBytes(LicenseResponse licenseResponse)
{
if (licenseResponse != null)
{
using (MemoryStream memoryStream = new MemoryStream())
{
this._licenseResponseSerializer.Write(memoryStream, licenseResponse);
return memoryStream.ToArray();
}
}
return null;
}
Step 6: Implement your client request response.
You can use HttpWebRequest or the WebClient classes to formulate the request. Here's a couple of examples from the code I use.
byte[] postBytes = GetLicenseRequestBytes(licenseRequest);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(licenseServerUrl);
request.Method = "POST";
request.ContentType = "application/octet-stream";
request.Proxy = WebRequest.DefaultWebProxy;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(postBytes, 0, postBytes.Length);
}
return request;
private LicenseResponse ProcessHttpResponse(HttpWebResponse response)
{
if ((response.StatusCode == HttpStatusCode.OK) && response.ContentType.Contains("application/octet-stream"))
{
var stream = response.GetResponseStream();
if (stream != null)
{
var licenseResponse = this._licenseResponseSerializer.Read(stream);
return licenseResponse;
}
}
return new LicenseResponse(LicensingResult.Error);
}
Summary and Tips
Use the streams in the request/responses on the client and server to communicate binary octet-stream data
Use CryptoStream along with an encryption algorithm (consider using the strongest encryption possilbe) and a good private key to encrypt data when you serialize/deserialize it.
Make sure to check the size and format all incoming data to the client and server (avoid buffer overruns and throw exceptions early)
Protect your private key on your client using obfuscation if possible (take a look at the DeepSea obfustactor)
Hi I'm hitting my head against the wall here...
I'm using DataContractJsonSerializer to encode data that I'm retrieving from the database which I'm sending back to an AJAX call...
I have this extension:
public static string ToJSON<T>(this T obj) where T : class
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
using (MemoryStream stream = new MemoryStream())
{
serializer.WriteObject(stream, obj);
return Encoding.Default.GetString(stream.ToArray());
}
}
and I'm calling it from the ASMX:
return _webServiceService.GetSponsors().ToJSON();
Passing in the resultset from a Stored Procedure using Entity Framework
It's all work kinda working, except this is part of what's being returned:
{"d":"[{\"FileID\":296,\"IconUrl\":\"\\/Files\\/Banners\\/20119\\/00B56BAC.jpg\",\"ImageUrl\":....
How on earth to I get rid of the slashes so that it returns the following:
{"d":"[{"FileID":296,"IconUrl":"/Files/Banners/20119/00B56BAC.jpg","ImageUrl":....
I'm trying to implement the JQuery UI Autocomplete. Well I'm guessing this will sort it, not sure if I need the FileID value within quotes?
You don't need to JSON serialize the return value by hand, because ASP.NET will handle it for you automatically in that scenario. What you're seeing there is ASP.NET applying a second level of JSON serialization to your manually generated string, which requires escaping double quotes with backslashes.
Change your ASMX method to return something like List<Sponsor> and return _webServiceService.GetSponsors() directly, without the ToJSON() extension.
I'd like to create URLs based on the URL used by the client for the active request. Is there anything smarter than taking the current HttpServletRequest object and it's getParameter...() methods to rebuilt the complete URL including (and only) it's GET parameters.
Clarification: If possible I want to resign from using a HttpServletRequest object.
Well there are two methods to access this data easier, but the interface doesn't offer the possibility to get the whole URL with one call. You have to build it manually:
public static String makeUrl(HttpServletRequest request)
{
return request.getRequestURL().toString() + "?" + request.getQueryString();
}
I don't know about a way to do this with any Spring MVC facilities.
If you want to access the current Request without passing it everywhere you will have to add a listener in the web.xml:
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
And then use this to get the request bound to the current Thread:
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()
Instead of using RequestContextHolder directly, you can also use ServletUriComponentsBuilder and its static methods:
ServletUriComponentsBuilder.fromCurrentContextPath()
ServletUriComponentsBuilder.fromCurrentServletMapping()
ServletUriComponentsBuilder.fromCurrentRequestUri()
ServletUriComponentsBuilder.fromCurrentRequest()
They use RequestContextHolder under the hood, but provide additional flexibility to build new URLs using the capabilities of UriComponentsBuilder.
Example:
ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentRequestUri();
builder.scheme("https");
builder.replaceQueryParam("someBoolean", false);
URI newUri = builder.build().toUri();
Java's URI Class can help you out of this:
public static String getCurrentUrl(HttpServletRequest request){
URL url = new URL(request.getRequestURL().toString());
String host = url.getHost();
String userInfo = url.getUserInfo();
String scheme = url.getProtocol();
String port = url.getPort();
String path = request.getAttribute("javax.servlet.forward.request_uri");
String query = request.getAttribute("javax.servlet.forward.query_string");
URI uri = new URI(scheme,userInfo,host,port,path,query,null)
return uri.toString();
}
in jsp file:
request.getAttribute("javax.servlet.forward.request_uri")
You can also add a UriComponentsBuilder to the method signature of your controller method. Spring will inject an instance of the builder created from the current request.
#GetMapping
public ResponseEntity<MyResponse> doSomething(UriComponentsBuilder uriComponentsBuilder) {
URI someNewUriBasedOnCurrentRequest = uriComponentsBuilder
.replacePath(null)
.replaceQuery(null)
.pathSegment("some", "new", "path")
.build().toUri();
//...
}
Using the builder you can directly start creating URIs based on the current request e.g. modify path segments.
See also UriComponentsBuilderMethodArgumentResolver
If you need the URL till hostname and not the path use Apache's Common Lib StringUtil, and from URL extract the substring till third indexOf /.
public static String getURL(HttpServletRequest request){
String fullURL = request.getRequestURL().toString();
return fullURL.substring(0,StringUtils.ordinalIndexOf(fullURL, "/", 3));
}
Example: If fullURL is https://example.com/path/after/url/ then
Output will be https://example.com
System.out.println(((HttpServletRequest)request).getRequestURI());
I used it. hope it's useful.