I have below JavaScript code that uses CryptoJS.AES.encrypt function from CryptoJS library and I am looking for equivalent .Net Core code, can anyone please guide?
var myData = '';
var key1 = '';
var key2 = '';
var encryptedData = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(myData.substr(0, myData.length - 1)), CryptoJS.enc.Utf8.parse(key1),
{
keySize: 128 / 8,
iv: CryptoJS.enc.Utf8.parse(key2),
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
Edit
I have found below code for .Net Core:
public string EncryptString(string text, string keyString, string ivString)
{
var key = Encoding.UTF8.GetBytes(keyString);
using (var aesAlg = Aes.Create())
{
using (var encryptor = aesAlg.CreateEncryptor(key, aesAlg.IV))
{
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(text);
}
var iv = aesAlg.IV;
var decryptedContent = msEncrypt.ToArray();
var result = new byte[iv.Length + decryptedContent.Length];
Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
Buffer.BlockCopy(decryptedContent, 0, result, iv.Length, decryptedContent.Length);
return Convert.ToBase64String(result);
}
}
}
}
But I am not sure how to specify these options as specified in JavaScript code:
{
keySize: 128 / 8,
iv: CryptoJS.enc.Utf8.parse(key2),
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}
Edit 2
I updated my C# code following suggestions from Topaco and below is my code.
But when I test it the output of my C# code and JavaScript code is different can anyone please guide what's missing?
public string RequestHash(string text, string keyString, string ivString)
{
var key = Encoding.UTF8.GetBytes(keyString);
var iv = Encoding.UTF8.GetBytes(ivString);
using (var aesAlg = Aes.Create())
{
using (var encryptor = aesAlg.CreateEncryptor(key, iv))
{
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(text);
}
var decryptedContent = msEncrypt.ToArray();
return Convert.ToBase64String(decryptedContent);
}
}
}
}
Thank you so much Topaco for your help, really appreciate!
Here's my final code:
public string RequestHash(string text, string keyString, string ivString)
{
var key = Encoding.UTF8.GetBytes(keyString);
var iv = Encoding.UTF8.GetBytes(ivString);
using (var aesAlg = Aes.Create())
{
using (var encryptor = aesAlg.CreateEncryptor(key, iv))
{
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(text);
}
var decryptedContent = msEncrypt.ToArray();
return Convert.ToBase64String(decryptedContent);
}
}
}
}
Related
Trying to download multiplefile as zip using System.io.compression from asp.net core web api. But i got binary error text. How can i fix this? below is my code
Error:
Error from backend. {"headers":{"normalizedNames":{},"lazyUpdate":null},"status":200,"statusText":"OK","url":"http://localhost:4000/api/filegeneration/createfile/2023-02-08/1","ok":false,"name":"HttpErrorResponse","
message":"Http failure during parsing for http://localhost:4000/api/filegeneration/createfile/2023-02-08/1",
"error":{"error":{},"text":"PK\u0003\u0004\u0014\u0000\u0000\u0000\b\u0000��HV�
u0010\u0001\u000b\u0000\u0000\u0000\u0003\u0000\u0000\u0000\u001e\u0000\u0000\u0000
Fareshare_Qty_08.02.2023_0.txtz�{?\u0000\u0000\u0000��\u0003\u0000PK\u0001\u0002\u0014
\u0000\u0014\u0000\u0000\u0000\b\u0000��HV�\u0010\u0001\u000b\u0000\u0000\u0000\u0003\u0000\u0000
\u0000\u001e\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000Fareshare_Qty_08.02.2023_0.txtPK\u0005
\u0006\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000L\u0000\u0000\u0000G\u0000\u0000\u0000\u0000\u0000"}}
Controller:
using (var outstream = new MemoryStream())
{
using (var archive = new ZipArchive(outstream,ZipArchiveMode.Create,true))
{
foreach (string filePath in files)
{
var filearcive = archive.CreateEntry(Path.GetFileName(filePath),CompressionLevel.Optimal);
using (var entrystream = filearcive.Open())
{
using (var fileCompressionStream = new MemoryStream(System.IO.File.ReadAllBytes(filePath)))
{
await fileCompressionStream.CopyToAsync(entrystream);
}
}
}
}
outstream.Position = 0;
return File(outstream.ToArray(), "application/zip", "Fareshare.zip");
Below code works for me. Please check it.
public (string fileType, byte[] archiveData, string archiveName) DownloadFiles(string subDirectory)
{
var zipName = $"archive-{DateTime.Now.ToString("yyyy_MM_dd-HH_mm_ss")}.zip";
List<FileInfo> files = new DirectoryInfo(Path.Combine(_hostingEnvironment.ContentRootPath, subDirectory)).GetFiles().ToList();
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
files.ForEach(file =>
{
var theFile = archive.CreateEntry(file.Name);
using (var streamWriter = new StreamWriter(theFile.Open()))
{
streamWriter.Write(File.ReadAllText(file.FullName));
}
});
}
return ("application/zip", memoryStream.ToArray(), zipName);
}
Test Result
We have to rework how we're sending emails since we are using Amazon SES. In the past, we were using smtp but can't do that in this case. The class that needs updated has taken in a MailMessage object and used smtp to send it. So I'm trying to rework the method to be able to continue to accept the MailMessage object and convert it to a MimeKit MimeMessage. For the most part it's working fine except when it comes to attachments. In the code I have, the attachment gets added and sent, however, when trying to open it appears it's corrupted or something. In my test case I attached a csv file. I could not open it in excel after receiving the email.
public class EmailAbstraction
{
public virtual void Send(MailMessage mailMessage)
{
sendMessage(mailMessage);
}
private static void sendMessage(MailMessage mailMessage)
{
using (var client = new AmazonSimpleEmailServiceClient(AwsConstants.SESAWSKey, AwsConstants.SESAWSSecret, AwsConstants.RegionEndpoint))
{
foreach (var to in mailMessage.To)
{
using (var messageStream = new MemoryStream())
{
var newMessage = new MimeMessage();
var builder = new BodyBuilder
{
HtmlBody = mailMessage.Body
};
newMessage.From.Add(mailMessage.From == null
? new MailboxAddress(EmailConstants.DefaultFromEmailDisplayName, EmailConstants.DefaultFromEmailAddress)
: new MailboxAddress(mailMessage.From.Address));
newMessage.To.Add(new MailboxAddress(to.DisplayName, to.Address));
newMessage.Subject = mailMessage.Subject;
foreach (var attachment in mailMessage.Attachments)
{
builder.Attachments.Add(attachment.Name, attachment.ContentStream);
}
newMessage.Body = builder.ToMessageBody();
newMessage.WriteTo(messageStream);
var request = new SendRawEmailRequest
{
RawMessage = new RawMessage { Data = messageStream }
};
client.SendRawEmail(request);
}
}
}
}
}
And in my test app, I have this.
internal class Program
{
private static void Main(string[] args)
{
var s = GetFileStream();
var m = new MailMessage();
var sender = new MailAddress("info#ourwebsite.com", "info");
m.From = sender;
m.Sender = sender;
m.Body = "test email";
m.Subject = "test subject";
m.To.Add(myemail);
m.Attachments.Add(new Attachment(s, "test-file.csv"));
new EmailAbstraction().Send(m);
}
private static MemoryStream GetFileStream()
{
var stream = new MemoryStream();
var fileStream = File.Open(#"C:\Users\dev\Desktop\test-file.csv", FileMode.Open);
fileStream.CopyTo(stream);
fileStream.Close();
return stream;
}
}
This is just copied from the MimeKit source code:
static MimePart GetMimePart (System.Net.Mail.AttachmentBase item)
{
var mimeType = item.ContentType.ToString ();
var contentType = ContentType.Parse (mimeType);
var attachment = item as System.Net.Mail.Attachment;
MimePart part;
if (contentType.MediaType.Equals ("text", StringComparison.OrdinalIgnoreCase))
part = new TextPart (contentType);
else
part = new MimePart (contentType);
if (attachment != null) {
var disposition = attachment.ContentDisposition.ToString ();
part.ContentDisposition = ContentDisposition.Parse (disposition);
}
switch (item.TransferEncoding) {
case System.Net.Mime.TransferEncoding.QuotedPrintable:
part.ContentTransferEncoding = ContentEncoding.QuotedPrintable;
break;
case System.Net.Mime.TransferEncoding.Base64:
part.ContentTransferEncoding = ContentEncoding.Base64;
break;
case System.Net.Mime.TransferEncoding.SevenBit:
part.ContentTransferEncoding = ContentEncoding.SevenBit;
break;
//case System.Net.Mime.TransferEncoding.EightBit:
// part.ContentTransferEncoding = ContentEncoding.EightBit;
// break;
}
if (item.ContentId != null)
part.ContentId = item.ContentId;
var stream = new MemoryStream ();
item.ContentStream.CopyTo (stream);
stream.Position = 0;
part.Content = new MimeContent (stream);
return part;
}
When I try and extract the "test.png" I receive the following error: This stream does not support seek operations.
Also can a wildcard be used? var entry = zipout["*.png"]; I will not know the same when streaming.
var request = (HttpWebRequest)WebRequest.Create("http://www.xxx.xxxx.com/xxx/xxxx?key=ndXqH2fXzePomlVoX39trxUf%2FV1bfN0rZsHsTyEvI%2F0%3D&labelFormat=png");
using (var ms = new MemoryStream())
{
using (var response = (HttpWebResponse)request.GetResponse())
{
using (var stream =response.GetResponseStream())
{
using (var zipout = ZipFile.Read(stream))
{
var entry = zipout["test.png"];
entry.Extract(ms);
}
}
}
}
Updated
using (var response = request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
using (var stream = new MemoryStream())
{
if (responseStream != null)
{
responseStream.CopyTo(stream);
}
using (var zipout = ZipFile.Read(stream))
{
using (var ms = new MemoryStream())
{
var entry = zipout["test.png"];
entry.Extract(ms);
}
}
}
}
}
New error: Message = "Cannot read that as a ZipFile"
var request = (HttpWebRequest)WebRequest.Create("var request = (HttpWebRequest)WebRequest.Create("http://www.xxx.xxxx.com/xxx/xxxx?key=ndXqH2fXzePomlVoX39trxUf%2FV1bfN0rZsHsTyEvI%2F0%3D&labelFormat=png");
using (var response = request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
using (var stream = new MemoryStream())
{
if (responseStream == null)
{
return;
}
responseStream.CopyTo(stream);
stream.Position = 0;
using (var zipout = ZipFile.Read(stream))
{
using (var ms = new MemoryStream())
{
var entry = zipout["test.png"];
if (entry != null)
{
entry.Extract(ms);
}
else
{
return;
}
}
}
}
}
}
I used the following code. Picture is posted successfully with a name but its not able to post message/description with it. Please tell me where i am wrong. Also its not giving any exception.
private void SharePhoto(string _accessToken, string p)
{
var fb = new FacebookClient(_accessToken);
fb.PostCompleted += (o, args) =>
{
if (args.Error != null)
{
if (args.Error.Message.StartsWith("(OAuthException - #190)"))
{
Dispatcher.BeginInvoke(() =>
{ MessageBox.Show("Message Expired"); });
}
else
{
Dispatcher.BeginInvoke(() =>
{ MessageBox.Show(args.Error.Message, "Error", MessageBoxButton.OK); });
}
return;
}
else
{
Dispatcher.BeginInvoke(() =>
{ MessageBox.Show("Image Posted"); });
}
};
var fbupload = new FacebookMediaObject
{
FileName = "facebook.jpg",
ContentType = "image/jpeg"
};
StreamResourceInfo sri =Application.GetResourceStream(new Uri("facebook.jpg",UriKind.Relative));
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(sri.Stream);
var loadedImage = new WriteableBitmap(bitmap);
using (MemoryStream ms = new MemoryStream())
{
loadedImage.SaveJpeg(ms, loadedImage.PixelWidth, loadedImage.PixelHeight, 0, 95);
ms.Seek(0, 0);
byte[] data = new byte[ms.Length];
ms.Read(data, 0, data.Length);
ms.Close();
fbupload.SetValue(data);
}
var parameters = new Dictionary<string, object>();
parameters["message"] = txtMessage.Text;
parameters["description"] = "first ever one";
parameters["name"] = "My FB Pic";
parameters["picture"]=fbupload;
parameters["link"] = new Uri(#"http://www.anyxyz.com", UriKind.Absolute);
fb.PostAsync(#"me/photos", parameters);
}
I used extended permissions as:
private const string extendedPermissions = "user_about_me,read_stream,publish_stream";
Any Help would be greatly appreciated.
How can I pass the encrypted id in ActionLink. This is what I have written in my view:
#model IEnumerable<forumAPP.tblTechnology>
#foreach (var item in Model)
{
string techName=item.TechName;
#Html.ActionLink(techName, "Details","Home", new { TopicID = item.TechID },null) // Here I would like to encrypt the TopicID
<br />
<br />
#Html.DisplayFor(modelItem => item.TechDesc)
}
Here are a couple of simple methods you can use to encode/decode.
The encoded value is not secure, and as you can see, decoding it is trivial. If your goal is to obfuscate the id, this will work. If you need to secure it, you should take a different approach.
public string Encode( string encodeMe )
{
byte[] encoded = System.Text.Encoding.UTF8.GetBytes( encodeMe );
return Convert.ToBase64String( encoded );
}
public static string Decode( string decodeMe )
{
byte[] encoded = Convert.FromBase64String( decodeMe );
return System.Text.Encoding.UTF8.GetString( encoded );
}
So you could place these methods in your controller, and pass the encoded TechId to the view with viewBag
int techId = 1;
var encoded = Encode(id.ToString());
ViewBag.Encoded = encoded;
And then to use it in your link
#Html.ActionLink(techName, "Details","Home", new { TopicID = ViewBag.Encoded },null)
(Though, you should really consider using a view model. ViewBag, while a convienent and easy way to pass data to the view, is not considered to be best practice. Becoming comfortable with view models and strongly typed views will make your mvc life much easier in the future. Not to mention, produce cleaner and more maintainable code for those that follow you.)
Add A Folder with two classes
Class 1 : EncryptedActionParameterAttribute
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Web;
using System.Web.Mvc;
namespace MVCInvoicClient.Extensions
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class EncryptedActionParameterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Dictionary<string, object> decryptedParameters = new Dictionary<string, object>();
if (HttpContext.Current.Request.QueryString.Get("q") != null)
{
string encryptedQueryString = HttpContext.Current.Request.QueryString.Get("q");
string decrptedString = Decrypt(encryptedQueryString.ToString());
string[] paramsArrs = decrptedString.Split('?');
for (int i = 0; i < paramsArrs.Length; i++)
{
string[] paramArr = paramsArrs[i].Split('=');
decryptedParameters.Add(paramArr[0], Convert.ToInt32(paramArr[1]));
}
}
for (int i = 0; i < decryptedParameters.Count; i++)
{
filterContext.ActionParameters[decryptedParameters.Keys.ElementAt(i)] = decryptedParameters.Values.ElementAt(i);
}
base.OnActionExecuting(filterContext);
}
private string Decrypt(string encryptedText)
{
string key = "jdsg432387#";
byte[] DecryptKey = { };
byte[] IV = { 55, 34, 87, 64, 87, 195, 54, 21 };
byte[] inputByte = new byte[encryptedText.Length];
DecryptKey = System.Text.Encoding.UTF8.GetBytes(key.Substring(0, 8));
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
inputByte = Convert.FromBase64String(encryptedText);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(DecryptKey, IV), CryptoStreamMode.Write);
cs.Write(inputByte, 0, inputByte.Length);
cs.FlushFinalBlock();
System.Text.Encoding encoding = System.Text.Encoding.UTF8;
return encoding.GetString(ms.ToArray());
}
}
}
Class 2 : MyExtensions
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MVCInvoicClient.Extensions
{
public static class MyExtensions
{
public static MvcHtmlString EncodedActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
{
string queryString = string.Empty;
string htmlAttributesString = string.Empty;
if (routeValues != null)
{
RouteValueDictionary d = new RouteValueDictionary(routeValues);
for (int i = 0; i < d.Keys.Count; i++)
{
if (i > 0)
{
queryString += "?";
}
queryString += d.Keys.ElementAt(i) + "=" + d.Values.ElementAt(i);
}
}
if (htmlAttributes != null)
{
RouteValueDictionary d = new RouteValueDictionary(htmlAttributes);
for (int i = 0; i < d.Keys.Count; i++)
{
htmlAttributesString += " " + d.Keys.ElementAt(i) + "=" + d.Values.ElementAt(i);
}
}
//What is Entity Framework??
StringBuilder ancor = new StringBuilder();
ancor.Append("<a ");
if (htmlAttributesString != string.Empty)
{
ancor.Append(htmlAttributesString);
}
ancor.Append(" href='");
if (controllerName != string.Empty)
{
ancor.Append("/" + controllerName);
}
if (actionName != "Index")
{
ancor.Append("/" + actionName);
}
if (queryString != string.Empty)
{
ancor.Append("?q=" + Encrypt(queryString));
}
ancor.Append("'");
ancor.Append(">");
ancor.Append(linkText);
ancor.Append("</a>");
return new MvcHtmlString(ancor.ToString());
}
private static string Encrypt(string plainText)
{
string key = "jdsg432387#";
byte[] EncryptKey = { };
byte[] IV = { 55, 34, 87, 64, 87, 195, 54, 21 };
EncryptKey = System.Text.Encoding.UTF8.GetBytes(key.Substring(0, 8));
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
byte[] inputByte = Encoding.UTF8.GetBytes(plainText);
MemoryStream mStream = new MemoryStream();
CryptoStream cStream = new CryptoStream(mStream, des.CreateEncryptor(EncryptKey, IV), CryptoStreamMode.Write);
cStream.Write(inputByte, 0, inputByte.Length);
cStream.FlushFinalBlock();
return Convert.ToBase64String(mStream.ToArray());
}
}
}
Controller
Add this line above the controller class Example for your Index
[EncryptedActionParameter]
In your View
#Html.EncodedActionLink("Download Invoice", "FileDownload","DataFiles", new { id = item.DataFilesID }, null)
add a using statement
#using MVCInvoicClient.Extensions
I came across this while looking for a secure method of doing this. In case someone else wishes to do this securely, you can use the MvcSerializer (I found it in the MVC futures 3 project, I am unsure whether it is included in MVC 4). For example:
(new MvcSerializer()).Serialize(<Your data here>, SerializationMode.EncryptedAndSigned)
And then to reverse the process...
(new MvcSerializer()).Deserialize(<Serialized data here>, SerializationMode.EncryptedAndSigned)
This is great because without any extra effort it encrypts and signs the data. The futures project also includes some attributes to make this happen automatically during model binding.