PHP - C# translated hashing function not working? - c#

I'll get right to the question,
We have this block of C# code
using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, passwordSaltBytes, iterationCount))
{
pbkdf2Bytes = pbkdf2.GetBytes(derivedLength + iterationCountBytes.Length);
}
Returns a byte array, first index has a value of 252
We attempt the same thing in PHP:
$key = hash_pbkdf2("SHA1", $password, $password.$salt, $iterationCount, 48);
First index is 102...
The values all match before this specific part.
It's just that hashing function that isn't giving me consistent results.
Any help is appreciated, cheers.
Edit - If it's not obvious, I'm trying to understand why those two values don't match, what encoding/decoding etc. am I misunderstanding or doing incorrectly.

This is the full C# code. As you can see there are some unnecessary loops etc. but the reasons why this wasn't working are 2:
As somebody pointed out, the bytes in PHP do no output raw data by default, and thus the hash (and consequently as such,) its bytes, weren't identical with that of the C# script.
Previously, I thought (as others also pointed out) that I should pass in the $salt as it is without any encoding or transformation. But upon looking closer at the actual C# code... we can see in the 2nd for i loop that they're actually appending saltBytes onto passwordBytes, thus creating something similar to $password.$salt in PHP
Combining the two above issues:
Sending the $password.$salt instead of just one, and then setting the $raw_output option to true, outputs the same hash, the same bytes as C# does.
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
byte[] iterationCountBytes = BitConverter.GetBytes(iterationCount);
int derivedLength = passwordBytes.Length + saltBytes.Length;
byte[] passwordSaltBytes = new byte[derivedLength];
byte[] pbkdf2Bytes;
string encryptedString;
for (int i = 0; i < passwordBytes.Length; i++)
{
passwordSaltBytes[i] = passwordBytes[i];
}
for (int i = 0; i < saltBytes.Length; i++)
{
passwordSaltBytes[passwordBytes.Length + i] = saltBytes[i];
}
using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, passwordSaltBytes, iterationCount))
{
pbkdf2Bytes = pbkdf2.GetBytes(derivedLength + iterationCountBytes.Length);
}
Thanks.

Related

Use PHP to Decode BASE64 encoded Signed Integers in 16bit

I have a Base64 encoded string and I am using the following c# code to decode it. Inside should be a range of Signed integers stored in 16bit.
Now I need to do it in PHP but I'm having real trouble. Can anyone help?
Basically can anyone convert this code to php?
private string decode(string encoded)
{
Byte[] newBytes = Convert.FromBase64String(
encoded.Replace("\n","")
);
int[] newArr = new int[newBytes.Length / 4];
for (int ctr = 0; ctr < newBytes.Length / 4; ctr++)
newArr[ctr] = BitConverter.ToInt16(newBytes, ctr * 4);
return DisplayArray(newArr);
}
private string DisplayArray(Array arr)
{
string output = "";
for (int ctr = 0; ctr < arr.GetUpperBound(0); ctr++)
{
output += arr.GetValue(ctr) + ",";
}
return output;
}
Here is the base64 string....
AgACAAAAAgAAAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAUABQAFAAUABQAF
AAUAAgACAAAA/v8AAAIABwAHAAUABQAFAAUAAAAAAAAAAgAAAAAAAgACAAUA
BQAFAAIAAgAFAAIAAAAAAAAAAAACAAAAAAACAAIAAAAAAAIABQAFAAUAAgAC
AAIAAgACAAIAAgACAAUAAgACAAIAAgACAAUABQAFAAIAAAAAAAUA/v8CAAIA
AgACAAAAAgAFAAUABQAFAAAAAgACAAIAAAACAAIABQACAAIABQAFAAcAAgAF
AAUAAgAAAAAAAgACAAUAAgACAAIAAAACAAUABQACAAUABQACAAIAAAACAAIA
AgACAAUABQAFAAAA/v/+/wAAAgACAAIAAAAAAAIAAgAAAAAAAgAFAAUABQAC
AAAAAAACAAIAAgACAAIAAAAAAAIAAAACAAIAAgACAAUAAgAFAAUABQACAAUA
BQAFAAcABQAFAAUABQAFAAUABQAHAAcABwAFAAUABwAHAAUABwAHAAUABwAH
AAUABwAHAAcABQAFAAUAAgAAAP7/AAACAAIAAgACAAUABQAFAAUAAgAFAAIA
BQACAAUABwAFAAIABQAFAAIABQACAAAABwAHAAUAAgAFAAUAAgAAAAAAAgAF
AAIABQAHAAcABQACAAIAAgACAAIAAgAFAAcABQAHAAcABwAHAAcABQAFAAUA
AgACAAUABQAFAAUABQAHAAoACgAKAAoABwAHAAoACgAKAAcACgAKAAwADAAM
AAwADAAPABEAEQAPAA8AFAARABQAFAAUABQAFgAWABEAEQAUABQAFAAWABYA
FgAZABsAGwAbABsAGwAbACAAIAAgACMAJQAoACUAKAAoACgAKAAoACgAKAAl
ACUAJQAlACUAJQAlACgAKgAqACgAJQAjACMAIAAeACAAIwAgABkAGQAZABkA
FAARAA8ADAAKAAcABwAFAAIABQAHAAcABQACAAIAAgACAAIAAAAAAAAA/v/+
/wAAAAAAAAIAAAD+//7/AAACAAUAAgACAAIAAAACAAUAAAAAAAAAAAAAAAAA
/v/+//7/AAAAAP7//v8AAAAA/v/+//7/+//7//v//v8AAAAA/v/7//7//v8A
AP7//v/7//7//v8AAP7/AAAAAAAAAAACAAIAAAAAAAAAAAAAAAIABQAHAAUA
BwAKAAoADwAUABsAIwAqAC8AOQBBAE0AWgBhAGkAcwB/AI4AmwClALEAuwDF
ANIA3gDrAPUABgEaASkBOAFKAV4BdAGGAZIBnwGuAb8BxwHRAdsB6gH2AQAC
BQIAAvkB6gHdAccBrgGVAYMBbQFUATgBGAH1ANwA1wDPAMoAyADAALQApwCb
AJMAiQCCAH0AcwBrAGYAXwBaAFIASwBGAEEAOQAvACUAHgAWABQAEQAMAAwA
DAAMAAwABwAFAAUAAgACAAAA/v8AAAAAAAD+//7/+//7//n/+f/2//b/+f/7
//n/+f/5//n/+//2//T/+//5//n/9v/5//n/9v/2//T/9v/0//n/+f/5//b/
9v/2//n/9v/2//T/9v/5//b/+f/5//n/+f/5//b/9P/2//T/7//x//T/9P/0
//b/9v/0//b/9P/2//b/9v/2//b/9P/x//H/8f/v//H/9P/x//T/9P/0//H/
8f/0//H/8f/x//H/8f/0//H/8f/x//H/8f/s/+z/7//v//H/8f/s/+z/7P/s
/+z/7P/s/+r/6v/s/+r/5//s/+r/6v/q/+r/6v/q/+f/5//n/+X/5f/n/+r/
6v/s/+f/5//l/+f/5//l/+L/5f/l/+X/5//i/+L/4v/i/+X/5f/i/+L/4P/d
/93/4v/i/+L/4v/g/93/3f/g/+D/3f/d/93/3f/b/93/2//b/9j/3f/b/9v/
2P/W/9j/1v/W/9P/0//R/9H/0//R/9b/1v/T/9H/0f/O/9P/0f/O/8z/zv/O
/87/zP/M/87/zP/M/8n/x//H/8f/zP/M/8z/yf/J/8z/zP/O/8z/yf/H/8T/
xP/H/8f/yf/J/8n/zP/M/8n/x//H/8n/yf/M/8z/zP/O/8z/zP/M/87/zv/R
/9H/0f/T/9P/0f/R/9P/1v/W/9j/3f/d/+D/4P/d/93/4v/i/+X/5//n/+z/
7//v/+//9P/2//b/9P/2//v/+//+/wAAAAACAAIABQAKAAoADAAMAAwACgAK
AAwADAAMAAwADAAMAA8AEQARABEAEQARABEADwARABQAFAARABEADwARABQA
EQARABEAEQAUABEAFAAUAA8AEQARAAwAEQARABEADwAPAAwADwARABEAEQAM
AAwACgAKAAoACgAKAAoACgAMAAwADAAKAAcACgAKAAwACgAFAAUACgAKAAoA
CgAKAAUABwAHAAcACgAHAAcABQAHAAUABwAKAAoABQACAAUABwAHAAcABQAC
AAIABQAFAAIAAgAFAAUACgAFAAUABwAHAAUABQAFAAIAAgACAAAAAgAFAAUA
BQAFAAcABwAFAAUABQAFAAcABwAHAAcABQAFAAUABQAFAAUABQAFAAUABQAH
AAcABQAFAAUABQAFAAIAAgACAAUABwAFAAUAAgACAAUABQAFAAUABQAKAAoA
BQAFAAcABwAFAAUABwACAAIAAgAHAAcABQAFAAUABQACAAAAAAAAAAIAAgAC
AAAAAAD+/wAAAAACAAIABQAFAAUABQACAAIAAgAAAAIAAgACAAAAAAACAAIA
AgAAAP7/AAACAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAA
AAIAAgAAAAIAAAAAAAAAAAAAAAAAAgACAAAAAAACAAAAAAACAAAAAAACAAIA
AgACAAIAAgACAAIAAAAAAAAAAgACAAIAAgACAAIA/v8AAAIAAgACAAIABQAF
AAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIA
AgACAAIAAgACAAIAAgACAAUAAgACAAIAAgACAAIAAgACAAIAAgAFAAUAAgAA
AAAAAgACAAIAAgACAAIAAgACAAIAAgAFAAUAAgACAAIABQAFAAIAAgACAAAA
AgAFAAUABwAFAAIAAAACAAAA/v/7//7/AAAAAAIABwAHAAUAAgAAAAIABwAF
AAIAAgACAAIAAgACAAIA
and it should decode to...
2,0,0,2,2,2,2,2,2,5,5,5,2,0,0,7,5,5,0,0,0,2,5,5,2,2,0,0,0,2,0,2,5,2,2,2,2,5,2,2,5,5,0,5,2,2,0,5,5,0,2,0,2,2,5,7,5,2,0,2,2,2,2,5,5,2,0,2,2,5,0,-2,2,2,0,2,0,5,5,0,2,2,2,0,0,2,2,2,5,2,5,7,5,5,5,7,7,5,7,7,5,7,7,7,5,2,-2,2,2,5,5,2,2,2,7,2,5,5,0,7,2,5,0,2,2,7,5,2,2,2,7,7,7,7,5,2,5,5,5,10,10,7,10,10,10,12,12,12,17,15,20,20,20,22,17,20,20,22,25,27,27,27,32,35,40,40,40,40,40,37,37,37,40,42,37,35,30,35,25,25,20,15,10,7,2,7,5,2,2,0,0,-2,0,2,-2,0,5,2,0,5,0,0,0,-2,0,-2,0,-2,-2,-5,-2,0,-5,-2,-2, etc...
The good
PHP makes it really easy to read in base64 data and convert it to an array of signed integers. Make sure to read up on the unpack function, it's great.
$stringValue = base64_decode($base64data, true);
$integers = unpack("s*", $stringValue);
The bad
That is not what your C# code is doing. After converting the base64 into raw bytes, it then processes that data in chunks of 4 bytes, parsing the first 2 into an int16 and throwing away the second two bytes. Half your data goes down the drain.
The ugly
If the C# code is really the algorithm you are after, here is how to do it in PHP:
$stringValue = base64_decode($base64data, true);
$integers = unpack("s*", $stringValue);
// Throw away half of our data. Because... why not? :)
$integers = array_map('array_shift', array_chunk($integers, 2));

Convert c# crypto code to ruby

I'm currently trying to convert this c# code into ruby, but I'm having difficulty with the hex conversion that is being used
public static string Decrypt(string hexString, string key, string iv)
{
var bytes = Enumerable.Range(0, hexString.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hexString.Substring(x, 2), 16))
.ToArray();
//===== AES provider
var provider = new AesCryptoServiceProvider();
provider.Mode = CipherMode.CBC;
provider.Key = Encoding.UTF8.GetBytes(key);
provider.IV = Encoding.UTF8.GetBytes(iv);
var transform = provider.CreateDecryptor();
using (var ms = new MemoryStream(bytes))
{
using (var cs = new CryptoStream(ms, transform, CryptoStreamMode.Read))
{
using (var sr = new StreamReader(cs))
{
cs.Flush();
var plainText = sr.ReadToEnd();
return plainText;
}
}
Here is a fiddle of the working code: https://dotnetfiddle.net/JI8SID
With these inputs:
var iv = "8E394493F1E54545";
var key = "36D65EA1F6A849AF9964E0BAA98096B3";
var encrypted = "0A1D18A104A568FDE4770E0B816870C6";
I should be getting:
"testing"
My code is below, but I keep getting a key length too short (OpenSSL::Cipher::CipherError). I'm guessing there's something wrong with my hex_to_bin conversion, but it is stumping me.
require 'openssl'
def hex_to_bin(str)
str.scan(/../).map { |x| x.hex.chr }.join
end
def decrypt(data, hex_key, hex_iv)
decipher = OpenSSL::Cipher::AES256.new(:CBC)
decipher.decrypt
decipher.key = hex_to_bin(hex_key)
decipher.iv = hex_to_bin(hex_iv)
(decipher.update(hex_to_bin(data)) + decipher.final)
end
iv = "8E394493F1E54545"
key = "36D65EA1F6A849AF9964E0BAA98096B3"
encrypted = "0A1D18A104A568FDE4770E0B816870C6"
puts decrypt(encrypted, key, iv)
Thank you in advance!
Use a key length of exactly the same length specified, in the case given AES256 make the key exactly 32-bytes in length. Otherwise an implementation can do whatever it wants from null padding, the garbage bytes past the end of the key or throw an error.
In the code there is a hexadecimal key of 32-bytes but then it is converted to a binary key of 16-bytes by the call: hex_to_bin(hex_key).
In a similar manner the 16-byte hex iv is being reduced to 8-bytes by the call: hex_to_bin(hex_iv).
You really need to supply longer hex keys. Just eliminating the conversion calls will result in 128-bits of key material.
Your intuition is correct - the problem is the call to hex_to_bin on key and iv. Here is a working decrypt routine which emits the string 'testing' when plugged into your sample code:
def decrypt(data, hex_key, hex_iv)
decipher = OpenSSL::Cipher::AES256.new(:CBC)
decipher.decrypt
decipher.key = hex_key
decipher.iv = hex_iv
(decipher.update(hex_to_bin(data)) + decipher.final)
end

C# Array.Value differs from created array in c++

What is the best way to handle the following situation in C#?
I have a server application written in C/C++.
For example
It creates a unsigned char buffer with length 256.
In this buffer the server stores the data the client sends to it. After storing, there are some cryptography checks with the received buffer.
I'm writing a client for this server in C#.
The problem is the buffer the server is expecting at fixed length of 256.
When I create a byte[] array with content and total length of 256 the cryptography checks are failing.
The reason I found out is simple. The server expects a buffer of 256 bytes long. For example if the message is "Hello World", the rest of the buffer has to be 0-padded.
Or, better explained: the bytes need to be (unsigned) "204" or (signed) "-52".
I think this is a C/C++ concept issue/problem.
To solve my problem, I am setting that value explicitly.
public static byte[] GetCBuffer(this byte[] data, int len)
{
byte[] tmp = new byte[len];
for(int i = 0; i < len; i++)
if(i < data.Length)
tmp[i] = data[i];
else
tmp[i] = 204;
return tmp;
}
Are there better ways to work with these art expected bytes? Am I not seeing something essential?
If you don't like if in your code, you can try LINQ:
public static byte[] GetCBuffer(this byte[] data, int len)
{
byte[] tmp = Enumerable.Repeat((byte)204, len).ToArray();
for(int i = 0; i < data.Length; i++)
{
tmp[i] = data[i];
}
return ret;
}
But conceptually, it's the same, just looks (arguably) a bit nicer.
Can you 'memset' the entire array to the desired fill character and then insert the actual data?

best practices to implement hashing?

I need to implement hashing (I am not referring encryption) to make some data fields (passwords or some details that do not require getting back in original format, rather only need to match in db) secure. Can you please suggest me the best practices to implement hashing. I will be using C# and SQL Server and it will be a web site.
OK now you've said you're protecting passwords you have some options.
The .NET framework has some built in algorithms - MD5, SHA1, SHA2. MD5 and SHA1 are considered obsolete and dangerous now, instead stick to SHA256.
For example (taken from my book)
static byte[] GenerateSaltedHash(string password, byte[] salt)
{
byte[] plainText = Encoding.UTF8.GetBytes(password);
HashAlgorithm algorithm = new SHA256Managed();
byte[] plainTextWithSaltBytes =
new byte[plainText.Length + salt.Length];
for (int i = 0; i < plainText.Length; i++)
{
plainTextWithSaltBytes[i] = plainText[i];
}
for (int i = 0; i < salt.Length; i++)
{
plainTextWithSaltBytes[plainText.Length + i] = salt[i];
}
byte[] hash = algorithm.ComputeHash(plainTextWithSaltBytes);
}
Now the salt is there to stop precomputed lookups of hashes (hashing itself is not enough any more, people have precomputed hashes of dictionary words and more). But how do you get a salt? Well it's any unique value really, usually a random set of bytes.
public byte[] GenerateSalt(int length)
{
salt = new byte[length];
// Strong runtime pseudo-random number generator, on Windows uses CryptAPI
// on Unix /dev/urandom
RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();
random.GetNonZeroBytes(salt);
return salt;
}
So you'd call GenerateSalt(32) first to get the salt (32 is just an example, longer if you wish. You will need to store the salt alongside the password - you don't need to worry about protecting it at all.
Finally you'll need a compare function. When you want to check passwords you would take the user input, get the salt for that user, generate the hash for the supplied password and stored salt, and then compare. You would do this using something like
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static bool ConstantCompare(byte[] array1, byte[] array2)
{
const byte Zero = 0;
int maxLength = array1.Length > array2.Length ? array1.Length : array2.Length;
bool wereEqual = array1.Length == array2.Length;
byte[] paddedArray1 = new byte[maxLength];
byte[] paddedArray2 = new byte[maxLength];
for (int i = 0; i < maxLength; i++)
{
paddedArray1[i] = array1.Length > i ? array1[i] : Zero;
paddedArray2[i] = array2.Length > i ? array2[i] : Zero;
}
bool compareResult = true;
for (int i = 0; i < maxLength; i++)
{
compareResult = compareResult & paddedArray1[i] == paddedArray2[i];
}
return compareResult & wereEqual;
}
I should, of course, point out the ASP.NET membership functions do salt and hash, so they should probably be a first point of call. No point in rolling your own if someone else has done the work.
Here is an API using PBKDF2 for key stretching ONTOP of hashing, this is now best practice.
https://sourceforge.net/projects/pwdtknet
I think you misunderstand what hashing is. You don't use a hash to "make data fields secure", because a hash can only be calculated in one direction. Compute and store the hash for your data, store the hash only, and you will be unable to retrieve your data later.
You might need to encrypt the data. That is an entirely different can of worms with it's own set of problems: how do you store and protect the decryption key, what encryption algorithm to use, do you do the encryption at the database level (sql server supports this) or the application level? How do you enforce encrypted transfer, and protect against copy of the data by the end user?

C# ushort[] to string conversion; is this possible?

I have a very painful library which, at the moment, is accepting a C# string as a way to get arrays of data; apparently, this makes marshalling for pinvokes easier.
So how do I make a ushort array into a string by bytes? I've tried:
int i;
String theOutData = "";
ushort[] theImageData = inImageData.DataArray;
//this is as slow like molasses in January
for (i = 0; i < theImageData.Length; i++) {
byte[] theBytes = System.BitConverter.GetBytes(theImageData[i]);
theOutData += String.Format("{0:d}{1:d}", theBytes[0], theBytes[1]);
}
I can do it this way, but it doesn't finish in anything remotely close to a sane amount of time.
What should I do here? Go unsafe? Go through some kind of IntPtr intermediate?
If it were a char* in C++, this would be significantly easier...
edit: the function call is
DataElement.SetByteValue(string inArray, VL Length);
where VL is a 'Value Length', a DICOM type, and the function itself is generated as a wrapper to a C++ library by SWIG. It seems that the representation chosen is string, because that can cross managed/unmanaged boundaries relatively easily, but throughout the C++ code in the project (this is GDCM), the char* is simply used as a byte buffer. So, when you want to set your image buffer pointer, in C++ it's fairly simple, but in C#, I'm stuck with this weird problem.
This is hackeration, and I know that probably the best thing is to make the SWIG library work right. I really don't know how to do that, and would rather a quick workaround on the C# side, if such exists.
P/Invoke can actually handle what you're after most of the time using StringBuilder to create writable buffers, for example see pinvoke.net on GetWindowText and related functions.
However, that aside, with data as ushort, I assume that it is encoded in UTF-16LE. If that is the case you can use Encoding.Unicode.GetString(), but that will exepect a byte array rather than a ushort array. To turn your ushorts into bytes, you can allocate a separate byte array and use Buffer.BlockCopy, something like this:
ushort[] data = new ushort[10];
for (int i = 0; i < data.Length; ++i)
data[i] = (char) ('A' + i);
string asString;
byte[] asBytes = new byte[data.Length * sizeof(ushort)];
Buffer.BlockCopy(data, 0, asBytes, 0, asBytes.Length);
asString = Encoding.Unicode.GetString(asBytes);
However, if unsafe code is OK, you have another option. Get the start of the array as a ushort*, and hard-cast it to char*, and then pass it to the string constructor, like so:
string asString;
unsafe
{
fixed (ushort *dataPtr = &data[0])
asString = new string((char *) dataPtr, 0, data.Length);
}
One thing you can do is switch from using a string to a stringBuilder it will help performance tremendously.
If you are willing to use unsafe code you can use pointers and implement the your c# code just like your c++. Or you could write a small c++\cli dll that implements this functionality.
Look into the Buffer class:
ushort[] theImageData = inImageData.DataArray;
byte[] buf = new byte[Buffer.ByteLength(theImageData)]; // 2 bytes per short
Buffer.BlockCopy(theImageData, 0, buf, 0, Buffer.ByteLength(theImageData));
string theOutData = System.Text.Encoding.ASCII.GetString(buf);
Just FYI, this has been fixed in later revision (gdcm 2.0.10). Look here:
http://gdcm.sourceforge.net/
-> http://apps.sourceforge.net/mediawiki/gdcm/index.php?title=GDCM_Release_2.0
I don't like this much, but it seems to work given the following assumptions:
1. Each ushort is an ASCII char between 0 and 127
2. (Ok, I guess there is just one assumption)
ushort[] data = inData; // The ushort array source
Byte[] bytes = new Byte[data.Length]; // Assumption - only need one byte per ushort
int i = 0;
foreach(ushort x in data) {
byte[] tmp = System.BitConverter.GetBytes(x);
bytes[i++] = tmp[0];
// Note: not using tmp[1] as all characters in 0 < x < 127 use one byte.
}
String str = Encoding.ASCII.GetString(bytes);
I'm sure there are better ways to do this, but it's all I could come up with quickly.
You can avoid unnecessary copying this way :
public static class Helpers
{
public static string ConvertToString(this ushort[] uSpan)
{
byte[] bytes = new byte[sizeof(ushort) * uSpan.Length];
for (int i = 0; i < uSpan.Length; i++)
{
Unsafe.As<byte, ushort>(ref bytes[i * 2]) = uSpan[i];
}
return Encoding.Unicode.GetString(bytes);
}
}

Categories

Resources