I'm developing an ASP.NET MVC application in which I want to encrypt a short string on the server, using C#, and send it to the client-side.
Then on the client-side it will be decrypted through Javascript code.
Any thoughts on how to implement this?
Do you know of a simple encryption algorithm (doesn't have to be bullet-proof secure) that can be easily translated from C# to Javascript or vice-versa?
NOTE: I could do this entirely in C# and do the decryption through Ajax, but I'd prefer not to do it this way, as I want to reduce website traffic as much as possible.
What about a simple XOR Cipher?
These two implementations are fully compatible:
Simple XOR Encryption (C#)
JavaScript XOR Encryption
It sounds like you want an obfuscation or encoding, not encryption. Base64 encoding should work well here. The result will look nothing like an email address, and the encoding process is fast.
In C#, you can use:
string emailAddress = "abc#example.com";
string encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(emailAddress));
And you can use this JavaScript function to decode it:
function Base64Decode(encoded) {
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
do {
enc1 = keyStr.indexOf(encoded.charAt(i++));
enc2 = keyStr.indexOf(encoded.charAt(i++));
enc3 = keyStr.indexOf(encoded.charAt(i++));
enc4 = keyStr.indexOf(encoded.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
} while (i < encoded.length);
return output;
}
The C# application encodes the string abc#example.com into YWJjQGV4YW1wbGUuY29t, and the JavaScript version will decode YWJjQGV4YW1wbGUuY29t back into abc#example.com.
The System.Security.Cryptography has a bunch of symetric (and asymetric) encrytion algorithms ready to use. (For something super secure use aes)
You should be able to find matching Javascript implementation for most (here are a few aes implementations in JS)
http://www.movable-type.co.uk/scripts/aes.html
http://www.hanewin.net/encrypt/aes/aes.htm
Note: If you are planning to use private key based encryption then keep in mind, your web page is going to have the key embedded in it and that means that it all becomes kind of pointless cause anyone with access to the page can do the decryption, at best you would be making the life of the screen scrapers a little bit harder. If making screen scrapers life harder is your goal you could just use an obsfucation algorithm. Any trivial implementation would make very impractical for screen scrapers that do not have a javascript engine:
Eg.
function samObsfucated()
{
return("s" + "a" + "m" + "#" + "s" + "." + "com");
}
Then onload populate your email fields with the output of these functions.
Javascript encryption has a really good use case for software that stores passwords for users ala clipperz
In terms of the simplest thing that could possibly work, it seems that you want a simple form of obfuscation, rather than anything really secure.
Rot-13 might be enough, provided that you're dealing with an audience with ASCII email addresses. If you need to support Unicode, then you might need something slightly more sophisticated.
Can you use HTTPS to encrypt all traffic between the client and server? This is probally the most secure method that you will find.
Very Simple Functions,
function Encrypt(value)
{
var result="";
for(i=0;i<value.length;i++)
{
if(i<value.length-1)
{
result+=value.charCodeAt(i)+10;
result+="-";
}
else
{
result+=value.charCodeAt(i)+10;
}
}
return result;
}
function Decrypt(value)
{
var result="";
var array = value.split("-");
for(i=0;i<array.length;i++)
{
result+=String.fromCharCode(array[i]-10);
}
return result;
}
Related
I was using this method to translate some text from my program using google translate, this was working perfectly until this week:
public string TranslateText(string input, string languagePair)
{
string r = WebUtility.HtmlDecode(input);
r = WebUtility.UrlEncode(r);
string url = String.Format("http://www.google.com/translate_t?hl=en&ie=UTF8&text={0}&langpair={1}", r, languagePair);
WebClient webClient = new WebClient();
webClient.Encoding = Encoding.GetEncoding("Windows-1252");
byte[] resultbyte = webClient.DownloadData(url);
string result = Encoding.Default.GetString(resultbyte);
result = result.Substring(result.IndexOf("TRANSLATED_TEXT=") + 16);
result = result.Replace("\\x26", "&");
result = result.Replace("\\x3d", "=");
result = WebUtility.HtmlDecode(result);
result = result.Remove(result.IndexOf(";"));
result = result.Replace("'", string.Empty);
return result;
}
But now I'm running the program just as always and I'm getting this translations always:
<html lang="en"> <head> <style>#import url(https://fonts.googleapis.com/css?lang=en&family=Product+Sans|Roboto:400,700)
And I don´t know what could happen. Anyone knows what's the problem?
A quick Google implies that the Google Translate API hasn't been designed to work like that for a while, the fact it's lasted that long for you is probably sheer luck.
The way you are using the Google Translate tools is not allowed under their terms (essentially screen scraping their free web tool). You should apply for an account with them and expect to pay, albeit a small amount if you are only translating a little bit of text. You may be able to get around it by modifying your URL and web page scraping code (if you haven't already been blocked), but you can't ask for help here to circumvent legal agreements.
If you decide to go the legal route, once you're up and running with an account you can access the API directly using your API key/token. See the quickstart guide for details.
I am currently converting a legacy ASP.NET 1.1 application into a .NET 4 MVC 3 application.
I am looking at the password encryption and a routine was written in the old code to use the MD5CryptoServiceProvider.
private string EncryptText(string szText)
{
try
{
UTF8Encoding objEncoder = new UTF8Encoding();
MD5CryptoServiceProvider objMD5Hasher = new MD5CryptoServiceProvider();
Byte[] btHashedDataBytes = objMD5Hasher.ComputeHash(objEncoder.GetBytes(szText));
string szReturn = objEncoder.GetString(btHashedDataBytes);
objEncoder = null;
objMD5Hasher = null;
return szReturn;
}
catch
{
return "";
}
}
I have written a quick .NET 4 console application and copied this function so I can do a comparison against the current passwords in the database (to make sure the MD5 function still gives me the same output)
string encTxt = encryptor.EncryptText("fbloggsPass12345");
using (SqlConnection conn = new SqlConnection("Server=server;Database=db;User Id=sa;Password=1111;"))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "UPDATE SiteUsers SET Token = '" + encTxt + "' WHERE PKey = 10";
if (cmd.ExecuteNonQuery() > 0)
Console.WriteLine("Updated");
else
Console.WriteLine("Failed");
}
conn.Close();
}
Console.ReadLine();
However the password in the database is currently !?MGF+&> and the output I am getting is ���!?��MGF�+&��> which when I store in the database converts to ???!???MGF?+&??>
Which I can see is almost the same, but why am I getting the ? characters
This is the first problem, at least:
string szReturn = objEncoder.GetString(btHashedDataBytes);
You're trying to use the hash as if it were UTF-8-encoded text. It's not - it's just arbitrary binary data.
If you need to convert arbitrary binary data to text, you should use something like Base64 (e.g. Convert.ToBase64String) or hex.
(Additionally, I would strongly advise you not to "handle" exceptions in the way you're doing so at the moment. Why would you want to hide problems like that? And why are you setting variables to null just before they go out of scope anyway?)
Oh, and please don't include values directly in your SQL like that - use parameterized SQL instead.
Finally, I would use a different hashing algorithm these days, particularly for passwords. Can you not use an off-the-shelf system for authentication, which is actually developed by security experts? Security is difficult: we'd all be better off leaving it to the relatively few people who know how to do it right :) See comments for more suggestions.
The standard technique for low impact upgrading is using the old hash as input for the new hashing scheme. This works pretty well with normal MD5 hashes.
Unfortunately for you, you were sending the binary hash through a non binary safe encoding (UTF8). This replaced every second character by 0xFFFD, effectively halving the output size to 64 bits. This weakens an upgraded scheme considerably but not fatally.
I'd upgrade the existing hashes to PBKDF2(legacyHash, salt), then on user login replace the hash with a new hash PBKDF2(password, salt) that doesn't depend on the legacy scheme. After a few months trigger a password reset for all users who did not login yet, getting rid of the legacy hash based passwords.
For the new scheme, I'd go with PBKDF2-SHA-1 which is implemented in the Rfc2898DeriveBytes Class. Use sufficient iterations, at least 10000.
what i need to do is sending a file from java to c#. the java act as the client meanwhile, c# act as server.
the file is loaded in java through fileinputstream and its been converted to utf8 then base64. see the code.
FileInputStream fin=new FileInputStream(fileName);
byte[] content = new byte[fin.available()];
fin.read(content, 0, content.length);
String asString = new String(content, "UTF8");
byte[] newBytes = asString.getBytes("UTF8");
String base64 = Base64.encodeToString(newBytes, Base64.DEFAULT);
and the server (using c# language) will read the data send and convert it back as a file. im using base64 then to utf8 and last i am not sure how to make it. what im trying to send is video.mp4 size of 144kb or less. so far, the output shows the catch of "WRONG FORMAT". see the code.
try
{
for (int i = 0; i <= _server.Q.NoOfItem - 1; i++)
{
words = _server.Q.ElementAtBuffer(i).ToString();
//textBox1.Text = words;
byte[] encodedDataAsBytes = System.Convert.FromBase64String(words);
string returnValue = System.Text.Encoding.UTF8.GetString(encodedDataAsBytes);
textBox1.Text = returnValue;
}
}
catch (ArgumentNullException argNull)
{
textBox1.Text = "Received null value";
}
catch (FormatException FrmtEx)
{
textBox1.Text = "Wrong format";
}
you can ignore the for (int i = 0; i <= _server.Q.NoOfItem - 1; i++) as this is the way i want to capture/retrieve the data sent.
p/s: it works when im just trying to pass any string without load the file (string >> utf8 >> base64) and to receive (base64 >> utf8 >> string).
the file is loaded in java through fileinputstream and its been converted to utf8
Then you've lost data. Video data is not text data, so don't load it as text data. Treat it as binary data - by all means encode it to base64 if you need to represent it as a string somewhere but don't perform any text decoding on it, as that's only meant for encoded text data, which this isn't.
It's really important to understand what's wrong here. The only thing the two lines below can do is lose data. If they don't lose data, they serve no purpose - and if they do lose data, they're clearly a bad idea:
String asString = new String(content, "UTF8");
byte[] newBytes = asString.getBytes("UTF8");
You should analyze how you ended up with this code in the first place... why did you feel the need to convert the byte array to a string and back?
jowierun's answer is also correct - you shouldn't be using available() at all. You might want to use utility methods from Guava, such as Files.toByteArray if you definitely need to read the whole file into memory in one go.
p/s: it works when im just trying to pass any string without load the file (string >> utf8 >> base64) and to receive (base64 >> utf8 >> string).
Well yes - if you start with text data, then that's fine - UTF-8 can represent every valid string, and base64 is lossless, so you're fine. (Admittedly you could break it by presenting an invalid string with half of a surrogate pair, but...) The problem is at the point where you treat non-text data as text in the first place.
You shouldn't use fin.available() to assume you can read the file in one go. That is likely to work for only small files. Instead you need to do the read in a loop and collect all the contents together before you encode it.
It would make sense to (on the java side at least) to have a decode that routine you can use to TEST that your encode is working (a unit test perhaps?). You will probably find that test is failing consistently with the problem you are getting.
I'm developing an application, that makes use of some REST web services.
It's technical documentation says that I should pass SHA256 hash of some string in the request.
In an example request (in the documentation) a string:
hn-Rw2ZHYwllUYkklL5Zo_7lWJVkrbShZPb5CD1expires=1893013926label[0]=any/somestatistics=1d,2d,7d,28d,30d,31d,lifetimestatus=upl,livetitle=a
After executing:
digest = Digest::SHA256.digest(string_to_sign)
signature = Base64::encode64(digest).chomp.gsub(/=+$/, '')
results in a hash:
YRYuN2zO+VvxISNp/vKQM5Cl6Dpzoin7mNES0IZJ06U
This example is in ruby, as the documentation is for ruby developers.
I'm developing my application in C# and for the exactly same string, when I execute:
byte[] rawHash = sha256.ComputeHash(rawRequest, 0, rawRequest.Length);
string friendlyHash = Convert.ToBase64String(rawHash);
and remove the trailing "=" signs, I get:
Vw8pl/KxnjcEbyHtfNiMikXZdIunysFF2Ujsow8hyiw
and therefore, the application fails to execute resulting in an signature mismatch error.
I've tried changing the encoding while converting the string to a byte array preceding the hashing and nothing changed.
Any ideas?
Based on the document here, you are missing a - (that is a dash) in your string. Seems that Acrobat helpfully removes it in a copy paste from the document...
Here is some code that I splatted together that gets the same value as the example (well it would if you trimmed the final =)
string s = "hn-Rw2ZH-YwllUYkklL5Zo_7lWJVkrbShZPb5CD1expires=1893013926label[0]=any/somestatistics=1d,2d,7d,28d,30d,31d,lifetimestatus=upl,livetitle=a";
SHA256Managed sh = new SHA256Managed();
byte[] request = System.Text.UTF8Encoding.UTF8.GetBytes(s);
sh.Initialize();
byte[] b4bbuff = sh.ComputeHash(request, 0, request.Length);
string b64 = Convert.ToBase64String(b4bbuff);
I am working on a feature that needs me to digitally sign a short string in PHP, and verify the string's signature in C#.
I would really like to use openssl_sign in PHP, because of its simplicity, but all the information I can find on Google indicates that this will not work.
There are some external libraries that claim to do this well, however as this is a hobby project I would rather not purchase such a library.
So what are the alternatives here? Full interoperability between C# and PHP is required. Libraries besides OpenSSL can be used.
I've done something very similar using Bouncy Castle Crypto APIs. It appears PHP openssl_sign uses SHA1 by default. If you are using anything other than the default you'll need to change the algorithm parameter for GetSigner.
string base64pubkey = "<!-- BASE64 representation of your pubkey from open ssl -->";
RsaKeyParameters pubKey = PublicKeyFactory.CreateKey(Convert.FromBase64String(base64pubkey)) as RsaKeyParameters;
byte[] signature = Convert.FromBase64String("<!-- BASE64 representation of your sig -->");
byte[] message = Encoding.ASCII.GetBytes("Something that has been signed");
ISigner sig = SignerUtilities.GetSigner("SHA1WithRSAEncryption");
sig.Init(false, pubKey);
sig.BlockUpdate(message, 0, message.Length);
if (sig.VerifySignature(signature))
{
Console.WriteLine("all good!");
}
You may use to check the digital signature smth like this:
string publicKey = "some key";
// Verifying Step 1: Create the digital signature algorithm object
DSACryptoServiceProvider verifier = new DSACryptoServiceProvider();
// Verifying Step 2: Import the signature and public key.
verifier.FromXmlString(publicKey);
// Verifying Step 3: Store the data to be verified in a byte array
FileStream file = new FileStream(args[0], FileMode.Open, FileAccess.Read);
BinaryReader reader = new BinaryReader(file2);
byte[] data = reader.ReadBytes((int)file2.Length);
// Verifying Step 4: Call the VerifyData method
if (verifier.VerifyData(data, signature))
Console.WriteLine("Signature verified");
else
Console.WriteLine("Signature NOT verified");
reader.Close();
file.Close();
Is there a reason you need something as complex as SSL signing? Can't you just use a simple one-way hash like MD5/SHA-1 on the string? If all you're looking for is verification that the string wasn't tampered with, that should be sufficient.
So looking at this - this guy appears to have asymmetric signing and encrypting working between PHP and C#. Signing should not be a problem, SHA* and MD* are standard, and so it's very very unlikely that is going to not be compatible (although you should be looking at SHA256 as MD* and SHA1 are deprecated due to vulnerabilities)
We're missing some context as to why you need to sign it. You may not need to.
The important question is: what guarantees do you need from your data?
If all you need to do is verify the integrity of the data, a hash will do the job. If you need to verify where it's coming from, you need to sign it. If you need both, hash it, concatenate the payload with the hash, and sign the whole thing.
Regarding cross-platform libraries... you really should need to worry about it. A SHA1 is a SHA1 is a SHA1, no matter which library generated it. Same thing with generating and verifying digital signatures. Use what's easiest in PHP and use what's easiest in C#. If they're both set up correctly you shouldn't need to worry about it.