Compare password hashes between C# and ColdFusion (CFMX_COMPAT) - c#

I have a password hash that is stored in a table and is put there by the following coldfusion script-
#Hash(Encrypt(Form.UserPassword,GetSiteVars.EnCode))#
I am trying to add some outside functionality within a c# application. I would like to be able to take advantage of the data that already exists so that I can authenticate users. Does anyone know how I can replicate the above coldfusion code in c#?
Thanks for any thoughts.

I looked through the Railo code as someone else here mentioned in comments.
Following is CFMX_Compat ported to C# from the Railo Java source. See below for an example of usage.
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
namespace RailoUtil
{
// SOURCE: Railo Source Code License LGPL v2
// http://wiki.getrailo.org/wiki/RailoLicense
public class RailoCFMXCompat
{
private String m_Key;
private int m_LFSR_A = 0x13579bdf;
private int m_LFSR_B = 0x2468ace0;
private int m_LFSR_C = unchecked((int)0xfdb97531);
private int m_Mask_A = unchecked((int)0x80000062);
private int m_Mask_B = 0x40000020;
private int m_Mask_C = 0x10000002;
private int m_Rot0_A = 0x7fffffff;
private int m_Rot0_B = 0x3fffffff;
private int m_Rot0_C = 0xfffffff;
private int m_Rot1_A = unchecked((int)0x80000000);
private int m_Rot1_B = unchecked((int)0xc0000000);
private int m_Rot1_C = unchecked((int)0xf0000000);
public byte[] transformString(String key, byte[] inBytes)
{
setKey(key);
int length = inBytes.Length;
byte[] outBytes = new byte[length];
for (int i = 0; i < length; i++)
{
outBytes[i] = transformByte(inBytes[i]);
}
return outBytes;
}
private byte transformByte(byte target)
{
byte crypto = 0;
int b = m_LFSR_B & 1;
int c = m_LFSR_C & 1;
for (int i = 0; i < 8; i++)
{
if (0 != (m_LFSR_A & 1))
{
m_LFSR_A = m_LFSR_A ^ m_Mask_A >> 1 | m_Rot1_A;
if (0 != (m_LFSR_B & 1))
{
m_LFSR_B = m_LFSR_B ^ m_Mask_B >> 1 | m_Rot1_B;
b = 1;
}
else
{
m_LFSR_B = m_LFSR_B >> 1 & m_Rot0_B;
b = 0;
}
}
else
{
m_LFSR_A = (m_LFSR_A >> 1) & m_Rot0_A;
if (0 != (m_LFSR_C & 1))
{
m_LFSR_C = m_LFSR_C ^ m_Mask_C >> 1 | m_Rot1_C;
c = 1;
}
else
{
m_LFSR_C = m_LFSR_C >> 1 & m_Rot0_C;
c = 0;
}
}
crypto = (byte)(crypto << 1 | b ^ c);
}
target ^= crypto;
return target;
}
private void setKey(String key)
{
int i = 0;
m_Key = key;
if (String.IsNullOrEmpty(key)) key = "Default Seed";
char[] Seed = new char[key.Length >= 12 ? key.Length : 12];
Array.Copy(m_Key.ToCharArray(), Seed, m_Key.Length);
int originalLength = m_Key.Length;
for (i = 0; originalLength + i < 12; i++)
Seed[originalLength + i] = Seed[i];
for (i = 0; i < 4; i++)
{
m_LFSR_A = (m_LFSR_A <<= 8) | Seed[i + 4];
m_LFSR_B = (m_LFSR_B <<= 8) | Seed[i + 4];
m_LFSR_C = (m_LFSR_C <<= 8) | Seed[i + 4];
}
if (0 == m_LFSR_A) m_LFSR_A = 0x13579bdf;
if (0 == m_LFSR_B) m_LFSR_B = 0x2468ace0;
if (0 == m_LFSR_C) m_LFSR_C = unchecked((int)0xfdb97531);
}
}
}
Here is a usage example that Hex-encodes the encrypted text, and then decrypts the same thing.
RailoCFMXCompat cfmx = new RailoCFMXCompat();
UTF8Encoding encoding = new UTF8Encoding();
//encrypt my string
byte[] encrypted = cfmx.transformString("mySecretKey", encoding.GetBytes("clear text"));
string encryptedHex = BitConverter.ToString(encrypted); //72-07-AA-1B-89-CB-01-96-4F-51
//decrypt my string
byte[] encryptedBytes = HexToBytes("72-07-AA-1B-89-CB-01-96-4F-51");
byte[] decrypted = cfmx.transformString("mySecretKey", encryptedBytes);
string cleartext = encoding.GetString(decrypted);

MD5 is the default hashing algorithm for the hash(). I'm not a C# programmer, but it shouldn't be too hard to create an MD5 hash to compare to your ColdFusion result.
As for encrypt(), is there a reason you're encrypting the username before hashing it? I can't think of any benefit to doing this, but that doesn't mean there isn't one. I would simply do:
Hash( UCase( GetPass.username ) )
Which should be easier to replicate in C#.

I'll leave the original answer content below for historical reference, but it should be noted that this is NOT a working answer to the original question.
Instead, see the top-voted answer in this thread, by #Terrapin in January 2011. I hope the OP sees this and can change the accepted answer. Heck, I'll even flag the mods to see if anything can be done about this.
To build on the answer by Edward Smith, and the follow-up comments by czuroski, here is my solution.
First, you need an XOR function in C#, which I've taken from here and modified slightly.
using System;
using System.Collections.Generic;
using System.Text;
namespace SimpleXOREncryption
{
public static class EncryptorDecryptor
{
public static string EncryptDecrypt(string textToEncrypt, int key)
{
StringBuilder inSb = new StringBuilder(textToEncrypt);
StringBuilder outSb = new StringBuilder(textToEncrypt.Length);
char c;
for (int i = 0; i < textToEncrypt.Length; i++)
{
c = inSb[i];
c = (char)(c ^ key);
outSb.Append(c);
}
return outSb.ToString();
}
}
}
Then, take the result of the XOR and base-64 encode it. After you have that string, MD5 hash it. The result should match the result from the original code snippet:
#Hash(Encrypt(Form.UserPassword,GetSiteVars.EnCode))#

One of the solutions would be to have the DB do the hashing and encription, could be easier...

The default "encryption" in CF is simply an XOR:
ciphertext = base64_encode(plaintext ^ key)
So, to decrypt:
plaintext = base64_decode(ciphertext) ^ key
The default hash, as mentioned, is md5.
Edit:
Well, further research shows this is not true - just one of those pervasive myths.
I can't find any documentation of the actual algorithm for the CFMX_COMPAT encryption method.
Sorry about the wild goose chase.

Related

md5(wordpress) password encryption in c#

I want to authenticate user form asp.net web application. data base used for application is MySQL and password stored in db is in encrypted format which is generated from word press application. i need to encrypted password so that i can compare encrypted password with db password.
my password : Push#123
Encrypted password : $P$BGW0cKLlkN6VlZ7OqRUvIY1Uvo/Bh9/
How to generate this Encrypted password in c#
It took me a while, but here you have working almost 1:1 conversion from php to C#:
using System;
using System.Text;
using System.Security.Cryptography;
using System.Linq;
namespace WordpressHash {
public class Program {
private static string itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public static void Main(string[]args) {
string StrPassword = "Push#123";
string expected = "$P$BGW0cKLlkN6VlZ7OqRUvIY1Uvo/Bh9/";
string computed = MD5Encode(StrPassword, expected);
Console.WriteLine(StrPassword);
Console.WriteLine(computed);
Console.WriteLine("Are equal? " + expected.Equals(computed));
}
static string MD5Encode(string password, string hash) {
string output = "*0";
if (hash == null) {
return output;
}
if (hash.StartsWith(output))
output = "*1";
string id = hash.Substring(0, 3);
// We use "$P$", phpBB3 uses "$H$" for the same thing
if (id != "$P$" && id != "$H$")
return output;
// get who many times will generate the hash
int count_log2 = itoa64.IndexOf(hash[3]);
if (count_log2 < 7 || count_log2 > 30)
return output;
int count = 1 << count_log2;
string salt = hash.Substring(4, 8);
if (salt.Length != 8)
return output;
byte[]hashBytes = {};
using(MD5 md5Hash = MD5.Create()) {
hashBytes = md5Hash.ComputeHash(Encoding.ASCII.GetBytes(salt + password));
byte[]passBytes = Encoding.ASCII.GetBytes(password);
do {
hashBytes = md5Hash.ComputeHash(hashBytes.Concat(passBytes).ToArray());
} while (--count > 0);
}
output = hash.Substring(0, 12);
string newHash = Encode64(hashBytes, 16);
return output + newHash;
}
static string Encode64(byte[]input, int count) {
StringBuilder sb = new StringBuilder();
int i = 0;
do {
int value = (int)input[i++];
sb.Append(itoa64[value & 0x3f]); // to uppercase
if (i < count)
value = value | ((int)input[i] << 8);
sb.Append(itoa64[(value >> 6) & 0x3f]);
if (i++ >= count)
break;
if (i < count)
value = value | ((int)input[i] << 16);
sb.Append(itoa64[(value >> 12) & 0x3f]);
if (i++ >= count)
break;
sb.Append(itoa64[(value >> 18) & 0x3f]);
} while (i < count);
return sb.ToString();
}
}
}
Every hash in the database is encoded using salt and n iterations of md5. Brief explanation can be found here: https://codex.wordpress.org/Function_Reference/wp_hash_password
Intentionally I have ommited salt generation. But if you will need it in the future, it should start with $P$ and be at least 12 characters long. Whit this extra method you will be able also to hash new passwords, not only check if hash is correct.
Probably this might do the trick for you
using System.Security.Cryptography;
class Program
{
static void Main(string[] args)
{
string StrPassword = "Push#123";
using (MD5 md5Hash = MD5.Create())
{
string hashPassword = GetMd5Hash(md5Hash, StrPassword);
Console.WriteLine(hashPassword);
}
}
static string GetMd5Hash(MD5 md5Hash, string input)
{
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
return sBuilder.ToString();
}
}
Hash functions map binary strings of an arbitrary length to small binary strings of a fixed length. A cryptographic hash function has the property that it is computationally infeasible to find two distinct inputs that hash to the same value; that is, hashes of two sets of data should match if the corresponding data also matches. Small changes to the data result in large, unpredictable changes in the hash.
The hash size for the MD5 algorithm is 128 bits.
The ComputeHash methods of the MD5 class return the hash as an array of 16 bytes. Note that some MD5 implementations produce a 32-character, hexadecimal-formatted hash. To interoperate with such implementations, format the return value of the ComputeHash methods as a hexadecimal value.
Source MSDN: MD5 Class
I've rewritten crypt_private php method from class-phpass.php (see /wp-includes/class-phpass.php of your wordpress installation) to use it in c#.
Password is user entered string, setting is user_pass value in wp database of wp_users row.
crypt_private return hash of password. So, if crypt_private returned value equals setting value, password is correct.
This works if you're using php5 and newer on server with wordpress.
private const string itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public bool SignIn(string password)
{
string foundUserHash = "hash from database (saved password of a user)";
string hash = Crypt(password, foundUserHash);
return foundUserHash == hash;
}
private string Crypt(string password, string setting)
{
string output = "*0";
if (setting.Substring(0, 2) == output)
output = "*1";
string id = setting.Substring(0, 3);
if (id != "$P$" && id != "$H$")
return output;
int count_log2 = itoa64.IndexOf(setting[3]);
if (count_log2 < 7 || count_log2 > 30)
return output;
var count = 1 << count_log2;
string salt = setting.Substring(4, 8);
if (salt.Length != 8)
return output;
var hash = GetHash(
GetByteArraysAppended(
Encoding.UTF7.GetBytes(salt),
Encoding.UTF7.GetBytes(password)
));
do
{
hash = GetHash(
GetByteArraysAppended(
hash,
Encoding.UTF7.GetBytes(password)
));
}
while (--count!=0);
output = setting.Substring(0, 12);
output += encode64(hash, 16);
return output;
}
private string encode64(byte [] input, int count)
{
string output = "";
int i = 0;
do
{
Int32 value = input[i++];
output += itoa64[value & 0x3f];
if (i < count)
value |= input[i] << 8;
output += itoa64[(value >> 6) & 0x3f];
if (i++ >= count)
break;
if (i < count)
value |= input[i] << 16;
output += itoa64[(value >> 12) & 0x3f];
if (i++ >= count)
break;
output += itoa64[(value >> 18) & 0x3f];
} while (i < count);
return output;
}
private byte[] GetByteArraysAppended(byte[] partOne, byte[] partTwo)
{
var parts = partOne.ToList();
parts.AddRange(partTwo);
var result = parts.ToArray();
return result;
}
private byte[] GetHash(byte [] bytesToHash)
{
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
var hash = md5.ComputeHash(bytesToHash);
return hash;
}

How can I calculate a CRC32 as a signed integer in C#?

I'm a PHP developer and a little out of my element in C#. In PHP, there's a crc32() function which returns a signed integer for any string that you pass in.
So this is what I'm used to:
<?php
echo crc32("test");
// displays -662733300
I would like to do the same thing in C#. I came across this C# class library but understand little about it. According to his instructions, I'm supposed to do this:
// first convert string to byte-array
String input = "test";
byte[] bytes = new byte[input.length * sizeof(char)];
System.Buffer.BlockCopy(input.ToCharArray(), 0, bytes, 0, bytes.Length);
// then calculate the value
Crc32 crc32 = new Crc32();
String output = "";
foreach (byte b in crc32.ComputeHash(bytes))
{
output += b.ToString("x2").ToLower();
}
That gives me an output string of 27d86d6a. What do I need to do instead to return a signed integer? (Which in this example should equal -662733300)
Try use BitConverter.ToInt32 method:
var crcVal = BitConverter.ToInt32(crc32.ComputeHash(bytes), 0);
EDIT
It's seems you use different Crc32 algorithm implementation, try the following one:
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
public class Program
{
public void Main()
{
// first convert string to byte-array
String input = "test";
byte[] bytes = new byte[input.Length * sizeof(char)];
System.Buffer.BlockCopy(input.ToCharArray(), 0, bytes, 0, bytes.Length);
// then calculate the value
var crcVal = crc32(input);
Console.WriteLine((int)crcVal);
}
public uint crc32(string input) {
var table = new uint[]{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
unchecked
{
uint crc = (uint)(((uint)0) ^ (-1));
var len = input.Length;
for (var i=0; i < len; i++) {
crc = (crc >> 8) ^ table[
(crc ^ (byte)input[i]) & 0xFF
];
}
crc = (uint)(crc ^ (-1));
if (crc < 0) {
crc += (uint)4294967296;
}
return crc;
}
}
}
Demo

Trying to reproduce PHP's pack("H*") function in C#

this is my code in C# :
public static String MD5Encrypt(String str, Boolean raw_output=false)
{
// Use input string to calculate MD5 hash
String output;
MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(str);
byte[] hashBytes = md5.ComputeHash(inputBytes);
// Convert the byte array to hexadecimal string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
sb.Append(hashBytes[i].ToString("x2"));
}
output = sb.ToString();
if (raw_output)
{
output = pack(output);
}
return output;
}
public static String pack(String S)
{
string MultiByte = "";
for (int i = 0; i <= S.Length - 1; i += 2)
{
MultiByte += Convert.ToChar(HexToDec(S.Substring(i, 2)));
}
return MultiByte;
}
private static int HexToDec(String hex)
{
//Int32.Parse(hexString, System.Globalization.NumberStyles.HexNumber);
return Convert.ToInt32(hex, 16);
}
To reproduce what is done in php by this way :
md5($str, true);
OR
pack('H*', md5( $str ));
I tried many things but can't get the same on the two sides in some cases of word.
For example, Trying this test on the string "8tv7er5j"
PHP Side :
9c36ad446f83ca38619e12d9e1b3c39e <= md5("8tv7er5j");
œ6­DoƒÊ8ažÙá³Ãž <= md5("8tv7er5j", true) or pack("H*", md5("8tv7er5j"))
C# Side :
9c36ad446f83ca38619e12d9e1b3c39e <= MD5Encrypt("8tv7er5j")
6­DoÊ8aÙá³Ã <= MD5Encrypt("8tv7er5j", true) or pack( MD5Encrypt("8tv7er5j") )
Why ? Encoding problem ?
EDIT 1 :
I have the good result, but bad encoded with this this function for pack() :
if ((hex.Length % 2) == 1) hex += '0';
byte[] bytes = new byte[hex.Length / 2];
for (int i = 0; i < hex.Length; i += 2)
{
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
So, System.Text.Encoding.UTF8.GetString(bytes) give me :
�6�Do��8a���Þ
And System.Text.Encoding.ASCII.GetString(bytes)
?6?Do??8a??????
...
I encountered same scenario where I am in need of php's pack-unpack-md5 functions in C#. Most important was that I need to match out of all these 3 functions with php.
I created my own functions and then validated(verified) my output with functions at onlinephpfunctions.com. The output was same when I parsed with DefaultEncoding. FYI, I checked my application's encoding(Encoding.Default.ToString()) and it was System.Text.SBCSCodePageEncoding
Pack
private static string pack(string input)
{
//only for H32 & H*
return Encoding.Default.GetString(FromHex(input));
}
public static byte[] FromHex(string hex)
{
hex = hex.Replace("-", "");
byte[] raw = new byte[hex.Length / 2];
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return raw;
}
MD5
private static string md5(string input)
{
byte[] asciiBytes = Encoding.Default.GetBytes(input);
byte[] hashedBytes = MD5CryptoServiceProvider.Create().ComputeHash(asciiBytes);
string hashedString = BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
return hashedString;
}
Unpack
private static string unpack(string p1, string input)
{
StringBuilder output = new StringBuilder();
for (int i = 0; i < input.Length; i++)
{
string a = Convert.ToInt32(input[i]).ToString("X");
output.Append(a);
}
return output.ToString();
}
PS: User can enhance these functions with other formats
I guess that PHP defaults to Latin1 so the code should look like :
public static String PhpMd5Raw(string str)
{
var md5 = System.Security.Cryptography.MD5.Create();
var inputBytes = System.Text.Encoding.ASCII.GetBytes(str);
var hashBytes = md5.ComputeHash(inputBytes);
var latin1Encoding = System.Text.Encoding.GetEncoding("ISO-8859-1");
return latin1Encoding.GetString(hashBytes);
}
If you are going to feed the result as a key for HMAC-SHA1 hashing keep it as bytes[] and initialize the HMACSHA1 with the return value of this function: DO NOT convert it to a string and back to bytes, I have spent hours because of this mistake.
public static byte[] PackH(string hex)
{
if ((hex.Length % 2) == 1) hex += '0';
byte[] bytes = new byte[hex.Length / 2];
for (int i = 0; i < hex.Length; i += 2)
{
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
}
I know this is an old question. I am posting my answer for anyone who might reach this page searching for it.
The following code is the full conversion of the pearl function pack("H*") to c#.
public static String Pack(String input)
{
input = input.Replace("-", " ");
byte[] hashBytes = new byte[input.Length / 2];
for (int i = 0; i < hashBytes.Length; i++)
{
hashBytes[i] = Convert.ToByte(input.Substring(i * 2, 2), 16);
}
return Encoding.UTF7.GetString(hashBytes); // for perl/php
}
I'm sorry. I didn't go with the questions completely. But if php code is as below,
$testpack = pack("H*" , "you value");
and if can't read the $testpack values(due to some non support format), then first do base64_encode as below and echo it.
echo base64_encode($testpack);
Then use Risky Pathak answer. For complete this answer I'll post his answer with some small modification like base 64 encoding etc.
var hex = "you value";
hex = hex.Replace("-", "");
byte[] raw = new byte[hex.Length / 2];
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
var res = Convert.ToBase64String(raw);
Console.WriteLine(res);
Now if you compare both of values, those should be similar.
And all credit should go to the Risky Pathak answer.
The same in c# can be reached with Hex.Decode() method.
And bin2hex() in php is Hex.Encode().

Implementing a LZ77 Compression algorithm into C#

Well I am currently trying to implement a compression algorithm in my project, it has to be lz77 as a matter of effect... I am already able to decompress data but I can't imagine where to start in terms of compressing. I thought it would be best to pass by a byte array with data, but that's about it...
My problem is that all descriptions of the algorithm are quite cryptic for me to understand. I would appreciate a clear description of how the algorithm works and what I have to watch for.
Also: Am I obliged to use unsafe methods and pointers when coding in C#? It would be better to avoid that... I suppose.
Here is what I got so far thanks to the information you gave me:
private const int searchWindow = 4095;
private const byte lookaheadWindow = 15;
public static byte[] lzCompressData(byte[] input)
{
int position = 0;
List<byte> tempInput = input.ToList();
List<byte> output = new List<byte>();
MemoryStream init = new MemoryStream();
BinaryWriter inbw = new BinaryWriter(init);
inbw.Write(((input.Length << 8) & 0xFFFFFF00) | 0x10);
output.AddRange(init.ToArray());
while (position < input.Length)
{
byte decoder = 0;
List<byte> tempOutput = new List<byte>();
for (int i = 0; i < 8; ++i)
{
List<byte> eligible;
if(position < 255)
{
eligible = tempInput.GetRange(0, position);
}
else
{
eligible = tempInput.GetRange(position - searchWindow, searchWindow);
}
if (!(position > input.Length - 8))
{
MemoryStream ms = new MemoryStream(eligible.ToArray());
List<byte> currentSequence = new List<byte>();
currentSequence.Add(input[position]);
int offset = 0;
int length = 0;
long tempoffset = StreamHelper.FindPosition(ms, currentSequence.ToArray());
while ((tempoffset != -1) && (length < lookaheadWindow) && position < input.Length - 8)
{
offset = (int)tempoffset;
length = currentSequence.Count;
position++;
currentSequence.Add(input[position]);
}
if (length >= 3)
{
decoder = (byte)(decoder | (byte)(1 << i));
byte b1 = (byte)((length << 4) | (offset >> 8));
byte b2 = (byte)(offset & 0xFF);
tempOutput.Add(b1);
tempOutput.Add(b2);
}
else
{
tempOutput.Add(input[position]);
position++;
}
}
else
{
if (position < input.Length)
{
tempOutput.Add(input[position]);
position++;
}
else
{
tempOutput.Add(0xFF);
}
}
}
output.Add(decoder);
output.AddRange(tempOutput.ToArray());
}
return output.ToArray();
}
I would apreciate a clear description of how the algorithm works and
what I have to watch for
it is very well explained here . If you have problem in understanding something specific please ask that.
Am I obliged to use unsafe methods and pointers when coding in C#
You don't have to worry about anything. No need to re-invent the wheel. it is already implemented. its implementation

Dotnet Hex string to Java

Have a problem, much like this post: How to read a .NET Guid into a Java UUID.
Except, from a remote svc I get a hex str formatted like this: ABCDEFGH-IJKL-MNOP-QRST-123456.
I need to match the GUID.ToByteArray() generated .net byte array GH-EF-CD-AB-KL-IJ-OP-MN- QR- ST-12-34-56 in Java for hashing purposes.
I'm kinda at a loss as to how to parse this. Do I cut off the QRST-123456 part and perhaps use something like the Commons IO EndianUtils on the other part, then stitch the 2 arrays back together as well? Seems way too complicated.
I can rearrange the string, but I shouldn't have to do any of these. Mr. Google doesn't wanna help me neither..
BTW, what is the logic in Little Endian land that keeps those last 6 char unchanged?
Yes, for reference, here's what I've done {sorry for 'answer', but had trouble formatting it properly in comment}:
String s = "3C0EA2F3-B3A0-8FB0-23F0-9F36DEAA3F7E";
String[] splitz = s.split("-");
String rebuilt = "";
for (int i = 0; i < 3; i++) {
// Split into 2 char chunks. '..' = nbr of chars in chunks
String[] parts = splitz[i].split("(?<=\\G..)");
for (int k = parts.length -1; k >=0; k--) {
rebuilt += parts[k];
}
}
rebuilt += splitz[3]+splitz[4];
I know, it's hacky, but it'll do for testing.
Make it into a byte[] and skip the first 3 bytes:
package guid;
import java.util.Arrays;
public class GuidConvert {
static byte[] convertUuidToBytes(String guid) {
String hexdigits = guid.replaceAll("-", "");
byte[] bytes = new byte[hexdigits.length()/2];
for (int i = 0; i < bytes.length; i++) {
int x = Integer.parseInt(hexdigits.substring(i*2, (i+1)*2), 16);
bytes[i] = (byte) x;
}
return bytes;
}
static String bytesToHexString(byte[] bytes) {
StringBuilder buf = new StringBuilder();
for (byte b : bytes) {
int i = b >= 0 ? b : (int) b + 256;
buf.append(Integer.toHexString(i / 16));
buf.append(Integer.toHexString(i % 16));
}
return buf.toString();
}
public static void main(String[] args) {
String guid = "3C0EA2F3-B3A0-8FB0-23F0-9F36DEAA3F7E";
byte[] bytes = convertUuidToBytes(guid);
System.err.println("GUID = "+ guid);
System.err.println("bytes = "+ bytesToHexString(bytes));
byte[] tail = Arrays.copyOfRange(bytes, 3, bytes.length);
System.err.println("tail = "+ bytesToHexString(tail));
}
}
The last group of 6 bytes is not reversed because it is an array of bytes. The first four groups are reversed because they are a four-byte integer followed by three two-byte integers.

Categories