2010-04-26 1 views
6

У меня есть хэш пароля, который хранится в таблице и поместить туда следующий ColdFusion script-Сравнение хэшей паролей между C# и ColdFusion (CFMX_COMPAT)

#Hash(Encrypt(Form.UserPassword,GetSiteVars.EnCode))# 

Я пытаюсь добавить внешний функциональность в aC# приложение. Я хотел бы иметь возможность использовать данные, которые уже существуют, чтобы я мог аутентифицировать пользователей. Кто-нибудь знает, как я могу воспроизвести вышеупомянутый код coldfusion в C#?

Спасибо за любые мысли.

+0

Какой алгоритм шифрования он использует? – SLaks

+0

См. Мой ответ ниже. –

+0

Ниже приведен код CFMX_Compat от проекта Railo, перенесенного на C# – Seibar

ответ

2

Я оставил исходное содержание ответа ниже для справки об истории, но следует отметить, что это НЕ рабочий ответ на исходный вопрос.

Вместо этого см. Верхний проголосовавший ответ в этой теме от @Terrapin в январе 2011 года. Надеюсь, OP видит это и может изменить принятый ответ. Черт, я даже буду отмечать моды, чтобы посмотреть, можно ли что-нибудь сделать по этому поводу.


Чтобы построить на ответ Эдварда Смита и последующих комментариев czuroski, вот мое решение.

Во-первых, вам нужна функция XOR в C#, которую я взял из here и немного изменил.

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(); 
     } 
    } 
} 

Затем возьмите результат XOR и base-64, чтобы закодировать его.После того, как у вас есть эта строка, MD5 хэш. Результат должен соответствовать результат из исходного фрагмента кода:

#Hash(Encrypt(Form.UserPassword,GetSiteVars.EnCode))# 
+0

Спасибо - я пробовал это, но он все еще не работает. Фактически, ключ, который у меня есть, на самом деле является строкой, а не int, поэтому я не знаю, отбрасывает ли это ее, или если я должен использовать ключ для кодировки base-64. на base-64 закодировать его, могу ли я просто использовать Convert.ToBase64String или нет? – czuroski

+0

Согласно [docs] (http://goo.gl/zGbJ), переданная строка используется как случайное семя для генерации значения целочисленного ключа. К сожалению, у меня больше нет информации о том, как именно это значение получает. Если бы я был на вашем месте, я мог бы рассмотреть (1) удаление шифрования из существующих паролей (достаточно просто с одноразовым сценарием) и (2) переписать существующий код CF, чтобы больше не использовать шифрование. Хейшинг достаточен, и шифрование в этом случае тратит процессор. –

+0

Да, я согласен с тем, что он тратит впустую процессор, но это приложение с надписью, и я не могу изменить это прямо сейчас. Поэтому я должен попытаться расшифровать его сам, но не повезло. – czuroski

3

MD5 - это алгоритм хэширования по умолчанию для hash(). Я не программист на C#, но не слишком сложно создать хеш MD5 для сравнения с вашим результатом ColdFusion.

Что касается encrypt(), есть ли причина, по которой вы шифруете имя пользователя перед его хэшированием? Я не могу придумать какую-либо пользу для этого, но это не значит, что его нет. Я бы просто сделал:

Hash(UCase(GetPass.username)) 

Что должно быть проще для репликации на C#.

+0

Согласен, шифрование в лучшем случае тривиально. –

+1

Но его данные уже включают его, поэтому он ищет ответ, где он может использовать, уже «зашифрованные» данные. –

+0

да - данные уже есть, поэтому я просто пытаюсь его использовать. – czuroski

1

Одним из решений будет иметь БД сделать хэширование и Шифрование, может быть проще ...

+0

да - это было бы проще. к сожалению, я не написал первоначальное приложение и не хочу его менять. – czuroski

1

по умолчанию «шифрование» в МВ просто XOR:

шифротекста = base64_encode (открытый текст^ключ)

Таким образом, для расшифровки:

открытого текста = base64_decode (шифротекст)^ключ

по умолчанию хэширования, а Menti , md5.

Edit:

Ну, дальнейшее исследование показывает, что это не так - просто одна из тех распространенных мифов.

Я не могу найти документацию по фактическому алгоритму для метода шифрования CFMX_COMPAT.

Извините, о дикой гусиной погоне.

+0

Я думаю, все это сводится к значению переменной 'EnCode'. – mwcz

+0

Правильно, это только ключ. Я уверен, что OP имеет доступ к нему в исходном коде CF. –

+0

Кажется, я не могу совместить это. Я попытался сузить его на тестовой странице CF, чтобы просто сделать шифрование (и игнорировать хеш), но я все еще не могу получить зашифрованное значение CF в соответствии с моим зашифрованным значением C#. Я использовал прямой base64-шифрование в моем приложении C#. Я где-то видел, что CF также выполняет uuencode как часть шифрования - есть ли в этом правда? – czuroski

10

Я просмотрел код Railo, как кто-то еще здесь упоминается в комментариях.

Ниже приведен CFMX_Compat, перенесенный на C# из источника Railo Java. Ниже приведен пример использования.

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); 
     } 
    } 
} 

Вот пример использования, что Hex кодирует зашифрованный текст, а затем расшифровывает то же самое.

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); 
+1

Этот порт C# для кода Railo является фактическим рабочим алгоритмом, который сопоставляется с Encrypt/Decrypt CF с использованием CFMX_COMPAT. Другие алгоритмы, основанные на XOR (в то время как правильные в их собственном контексте), несовместимы с Encrypt/Decrypt от ColdFusion. Это версия, которую вы хотите использовать. –