0

I have been working on some cryptography and I need to create a new SHA-2 (sha256) system in which I generate new salt and hash , so the hash will be based upon the user typed password + newly created salt as I understand it. However, as I have downloaded a sample project, of all the sha-1 and sha-2 code that I have played around with, i have never seen the chinese symbols and so I'm a little concerned and confused

This is the code ,

    // utilty function to convert byte[] to string        
    public static string GetString(byte[] bytes)
    {
        char[] chars = new char[bytes.Length / sizeof(char)];
        System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
        return new string(chars);
    }

incoming bytes do not have any strange characters so what is causing them?

screenshot enter image description here

bytes parameter is byte[24] .... [0] = 20 , 1 = 101 etc.. just normal looking. So it seems to be occurring on this line System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);

1 Answers1

1

You just found some unicode characters. I far more often see--instead of unicode--UTF8 used, as so:

var toString = System.Text.Encoding.UTF8.GetString(yourByteArray);
var backToBytes = System.Text.Encoding.UTF8.GetBytes(toString);

EDIT

Here's an example console program that uses the AES encryption/decryption wrapper I coded after scouring the web for best-practice examples.

namespace Sandbox
{
    class Program
    {
        static void Main(string[] args)
        {
            var originString = "This is some example text";

            var originBytes = System.Text.Encoding.UTF8.GetBytes(originString);

            var aes = new AesCryptoServiceProvider {KeySize = 256};
            aes.GenerateIV();
            aes.GenerateKey();
            var vectorBytes = aes.IV;
            var keyBytes = aes.Key;

            //Not going to use these in the code, but here's how to get the values if you
            //Want to save them off.
            var vectorString = System.Text.Encoding.UTF8.GetString(vectorBytes);
            var keyString = System.Text.Encoding.UTF8.GetString(keyBytes);

            var encryptedBytes = EncryptionService.Encrypt(keyBytes, vectorBytes, originBytes);

            var encyptedString = System.Text.Encoding.UTF8.GetString(encryptedBytes);

            var decryptedBytes = EncryptionService.Decrypt(keyBytes, vectorBytes, encryptedBytes);

            var decryptedString = System.Text.Encoding.UTF8.GetString(decryptedBytes);

            Console.WriteLine($"Origin:\t\t {originString}");
            Console.WriteLine($"Vector:\t\t {vectorString}");
            Console.WriteLine($"Key:\t\t {keyString}");
            Console.WriteLine($"Encrypted:\t {encyptedString}");
            Console.WriteLine($"Decrypted:\t {decryptedString}");

            Console.ReadLine();

        }
    }

    public static class EncryptionService
    {
        public static byte[] Encrypt(byte[] key, byte[] vector, byte[] input)
        {
            if (key.Length == 0)
                throw new ArgumentException("Cannot encrypt with empty key");

            if (vector.Length == 0)
                throw new ArgumentException("Cannot encrypt with empty vector");

            if (input.Length == 0)
                throw new ArgumentException("Cannot encrypt empty input");

            var unencryptedBytes = input;

            using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider { Key = key, IV = vector })
            using (ICryptoTransform encryptor = aes.CreateEncryptor())
            using (MemoryStream ms = new MemoryStream())
            using (CryptoStream writer = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
            {
                writer.Write(unencryptedBytes, 0, unencryptedBytes.Length);
                writer.FlushFinalBlock();
                var byteArray = ms.ToArray();

                if (byteArray.Length == 0)
                    throw new Exception("Attempted to encrypt but encryption resulted in a byte array of 0 length.");

                return byteArray;
            }
        }


        public static byte[] Decrypt(byte[] key, byte[] vector, byte[] encrypted)
        {
            if (key.Length == 0)
                throw new ArgumentException("Cannot encrypt with empty key");

            if (vector.Length == 0)
                throw new ArgumentException("Cannot encrypt with empty vector");

            if (encrypted == null || encrypted.Length == 0)
                throw new ArgumentException("Cannot decrypt empty or null byte array");

            byte[] unencrypted;

            using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider { Key = key, IV = vector })
            using (ICryptoTransform decryptor = aes.CreateDecryptor(key, vector))
            using (MemoryStream ms = new MemoryStream(encrypted))
            using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
            {
                var decrypted = new byte[encrypted.Length];
                var bytesRead = cs.Read(decrypted, 0, encrypted.Length);

                return decrypted.Take(bytesRead).ToArray();
            }

        }
    }
}
Ranger
  • 1,139
  • 1
  • 13
  • 34
  • Are those methods in that Utility class sort of re-inventing the wheel? So I should use your code in place of mine? Can you explain where and how to implement? –  May 17 '16 at 17:25
  • http://www.codeproject.com/Articles/608860/Understanding-and-Implementing-Password-Hashing is where I found the sample fyi –  May 17 '16 at 17:27
  • So unless you're going for some performance advantage (which I doubt you'll find for something on this level) I'd say your methods aren't needed and you are reinventing the wheel. I used those exact methods when implementing SHA-256 on one of my own projects. – Ranger May 17 '16 at 17:29
  • Where do I put these lines of code? var toString = System.Text.Encoding.UTF8.GetString(yourByteArray); var backToBytes = System.Text.Encoding.UTF8.GetBytes(toString); –  May 17 '16 at 17:31
  • Whenever you'd call Utility.GetString(..), instead call System.Text.Encoding.UTF8.GetString(..), and whenever you'd call Utility.GetBytes(..), instead call System.Text.Encoding.UTF8.GetBytes(..). This would be outside of your Utility class, letting you get rid of your Utility class (if those are, in fact, the only two methods the class holds). – Ranger May 17 '16 at 17:33
  • Ok, I see. Its strange that this selected answer on stackoverflow uses the same code and it seems from comments to be very controversial http://stackoverflow.com/questions/472906/how-to-get-a-consistent-byte-representation-of-strings-in-c-sharp-without-manual –  May 17 '16 at 17:39
  • "Z#�I�'\"��р�yq��'!��" is the value of "saltString" var saltString = System.Text.Encoding.UTF8.GetString(saltBytes); –  May 17 '16 at 17:41
  • @JeremyMiller To clarify; there was nothing wrong with your original question. You just seemed alarmed by the unicode characters and you're right in thinking that they're not commonly used in this manner. That doesn't make it the _wrong_ way, so you could keep doing it how you were doing it. UTF8 is just _more common_ and you're more likely to see it out there on the web. Your string doesn't (and after a fashion, will never be) human readable. (1/2) – Ranger May 17 '16 at 17:42
  • So my goal is to be able to move from SHA-1 to SHA-2 (sha256) and thus I want to generate proper salts and hashes and then store then in the database table, i'm sure the development team will be shaking their heads if I end up storing unicode ... how can i fix? –  May 17 '16 at 17:45
  • The �s are just byte values that haven't been assigned a corresponding character in UTF8. It shouldn't stop the encryption/decryption from happening. Note if you ENCODE to bytes in one format, and DECODE back to a string in another format you will _never_ get the same string back out; you need to pick a consistent format. (2/2) – Ranger May 17 '16 at 17:45
  • @JeremyMiller If you want, I'll edit my answer with my own implementation of SHA-256 with a unit test that encrypts/decrypts some text. – Ranger May 17 '16 at 17:50
  • Yes, that would be so awesome and helpful! –  May 17 '16 at 17:59
  • @JeremyMiller There you go. Made it a console program instead of a unit test. Hope you don't mind! If you have any questions, feel free to ask. – Ranger May 17 '16 at 18:47
  • 1
    Thx so much , this is very helpful! –  May 17 '16 at 19:04
  • Oh! D'oh. My bad. I'll take out my example. I've dealt with that before, so I think I can code up an example. Go ahead and un-accept my answer and I'll try to code up SHA hashing this evening. – Ranger May 17 '16 at 19:07
  • @JeremyMiller Sorry, I was tied up last evening with work, and didn't get a chance to write it. It's still on my to-do list once I get 20 mins free. – Ranger May 18 '16 at 16:59