-
-
Save jechtom/cde72caeebb215115171 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Newtonsoft.Json; | |
using Newtonsoft.Json.Bson; | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Services | |
{ | |
public class HMAC | |
{ | |
/// <remarks> | |
/// To generate new key: | |
// byte[] tokenData = new byte[64]; | |
// new RNGCryptoServiceProvider().GetBytes(tokenData); | |
// string key = string.Join(", ", tokenData); | |
// </remarks> | |
private byte[] hmacKey64bytes = new byte[] { .................... }; | |
public T DeserializeAndValidate<T>(string text) where T : class | |
{ | |
if (string.IsNullOrWhiteSpace(text)) | |
return null; | |
// deserialize | |
byte[] input; | |
try | |
{ | |
// decode | |
input = Convert.FromBase64String(text); | |
using (MemoryStream inputStream = new MemoryStream(input)) | |
{ | |
int hashSize; | |
using (System.Security.Cryptography.HMAC hmac = CreateProvider()) | |
{ | |
// read hash | |
hashSize = (hmac.HashSize / 8); | |
byte[] hash = new byte[hashSize]; | |
inputStream.Read(hash, 0, hash.Length); | |
// verify hash | |
byte[] hashCurrent = hmac.ComputeHash(inputStream); | |
// compare hash | |
for (int i = 0; i < hashCurrent.Length; i++) | |
{ | |
if (hash[i] != hashCurrent[i]) | |
return null; // invalid hash | |
} | |
} | |
// move position after hash | |
inputStream.Position = hashSize; | |
// hash is valid - try to deserialize object | |
using (var bsonReader = new BsonReader(inputStream)) | |
{ | |
T result = new JsonSerializer().Deserialize<T>(bsonReader); | |
return result; | |
} | |
} | |
} | |
catch | |
{ | |
// invalid format | |
return null; | |
} | |
} | |
public string SerializeAndSign<T>(T value) where T : class | |
{ | |
if (value == null) | |
throw new ArgumentNullException("value"); | |
// serialize | |
byte[] input; | |
using (MemoryStream inputStream = new MemoryStream()) | |
{ | |
// serialize to input stream | |
using (var bsonWriter = new BsonWriter(inputStream)) | |
{ | |
new JsonSerializer().Serialize(bsonWriter, value); | |
} | |
input = inputStream.ToArray(); | |
} | |
// sign | |
using (MemoryStream outputStream = new MemoryStream()) | |
{ | |
// compute hash | |
byte[] hash; | |
using (System.Security.Cryptography.HMAC hmac = CreateProvider()) | |
{ | |
hash = hmac.ComputeHash(input); | |
} | |
// write hash stream | |
outputStream.Write(hash, 0, hash.Length); | |
// and write input stream | |
outputStream.Write(input, 0, input.Length); | |
// serialize to Base64 | |
var result = Convert.ToBase64String(outputStream.ToArray()); | |
return result; | |
} | |
} | |
private System.Security.Cryptography.HMAC CreateProvider() | |
{ | |
return new System.Security.Cryptography.HMACSHA256(hmacKey64bytes); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment