2010-04-26 9 views
6

mam hash hasła, które są przechowywane w tabeli i umieścić tam następującym ColdFusion ScriptPorównaj hashe haseł między C# i ColdFusion (CFMX_COMPAT)

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

Próbuję dodać trochę poza funkcjonalnością aplikacja AC#. Chciałbym móc wykorzystać dane, które już istnieją, aby móc uwierzytelniać użytkowników. Czy ktoś wie, w jaki sposób można replikować powyższy kod coldfusion w języku C#?

Dzięki za wszelkie myśli.

+0

Jakiego algorytmu szyfrowania używa? – SLaks

+0

Zobacz moją odpowiedź poniżej. –

+0

Poniżej znajduje się kod CFMX_Compat z projektu Railo przeniesiony do C# – Seibar

Odpowiedz

2

Zostawię poniżej oryginalną treść odpowiedzi dla odniesienia historycznego, ale należy zauważyć, że to NIE działa odpowiedź na oryginalne pytanie.

Zamiast tego zobacz odpowiedź z najważniejszymi głosami w tym wątku autorstwa @Terrapin w styczniu 2011 roku. Mam nadzieję, że PO zobaczy to i może zmienić zaakceptowaną odpowiedź. Heck, nawet oznaczę mody, żeby zobaczyć, czy można coś z tym zrobić.


Opierając się na odpowiedzi udzielonej przez Edwarda Smitha i dalszych komentarzach czuroskiego, oto moje rozwiązanie.

Po pierwsze, potrzebujesz funkcji XOR w języku C#, którą zaczerpnąłem z here i zmodyfikowałem nieznacznie.

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

Następnie, weź wynik kodu XOR i kodu-64 go.Po uzyskaniu tego ciągu, MD5 miesza go. Wynik powinien być zgodny z wynikiem z oryginalnego fragmentu kodu:

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

Dzięki - próbowałem tego, ale nadal nie działa. Właściwie klucz, który mam, jest w rzeczywistości ciągiem - nie int, więc nie wiem, czy to wyrzuca, czy też muszę użyć klucza do kodowania base-64. do kodowania base-64, czy mogę po prostu użyć Convert.ToBase64String, czy nie? – czuroski

+0

Zgodnie z [docs] (http://goo.gl/zGbJ), łańcuch przekazany jest używany jako losowy materiał siewny do generowania wartości liczby całkowitej. Niestety, nie mam więcej informacji na temat tego, w jaki sposób uzyskuje tę wartość. Gdybym był na miejscu, mógłbym rozważyć (1) usunięcie szyfrowania z istniejących haseł (wystarczająco proste w przypadku skryptu jednorazowego) i (2) przepisanie istniejącego kodu CF, aby przestał używać szyfrowania. Hashowanie jest wystarczające, a szyfrowanie marnuje procesor w tym przypadku, moim zdaniem. –

+0

tak - Zgadzam się, że to marnowanie procesora, ale jest to suppotowana aplikacja i nie jestem w stanie tego zmienić teraz. Więc muszę spróbować odszyfrować to sam, ale nie miałem szczęścia. – czuroski

3

MD5 to domyślny algorytm mieszający dla hash(). Nie jestem programistą C#, ale nie powinno być zbyt trudno tworzyć mieszanie MD5 w celu porównania z wynikiem ColdFusion.

Jeśli chodzi o encrypt(), czy istnieje powód, dla którego szyfrujesz nazwę użytkownika przed hashowaniem? Nie mogę wymyślić żadnej korzyści z tego, ale to nie znaczy, że nie ma. Po prostu zrobiłbym:

Hash(UCase(GetPass.username)) 

Które powinno być łatwiej replikować w C#.

+0

Zgadzam się, szyfrowanie jest w najlepszym razie banalne. –

+1

Ale jego dane już go zawierają, więc szuka odpowiedzi, w której może wykorzystać dane już "zaszyfrowane". –

+0

tak - dane już tam są, więc próbuję go użyć. – czuroski

1

Jednym z rozwiązań byłoby mieć DB zrobić hashowania i encription, może być prostsze ...

+0

tak - to byłoby łatwiejsze. niestety nie napisałem początkowej aplikacji i nie chcę jej zmieniać. – czuroski

1

Domyślna „szyfrowania” w CF jest po prostu XOR:

szyfrogram = base64_encode (tekst jawny^klucz)

tak więc, aby odszyfrować:

zwykłego tekstu = base64_decode (szyfrogram)^kluczową

domyślna wartość mieszania, jak Menti oned, jest md5.

Edit:

Cóż, dalsze badania pokazuje, że to nieprawda - po prostu jedna z tych rozpowszechnionych mitów.

Nie mogę znaleźć żadnej dokumentacji rzeczywistego algorytmu dla metody szyfrowania CFMX_COMPAT.

Przykro mi z powodu gonitwy.

+0

Chyba wszystko sprowadza się do wartości zmiennej 'EnCode'. – mwcz

+0

Dobrze, to tylko klucz. Jestem pewien, że OP ma do niego dostęp w swoim kodzie źródłowym CF. –

+0

Nie mogę tego zmusić do tego. Próbowałem zawęzić to na testowej stronie CF, aby zaszyfrować (i zignorować hash), ale nadal nie mogę uzyskać zaszyfrowanej wartości CF, aby dopasować ją do mojej zaszyfrowanej wartości C#. Użyłem prostego szyfrowania base64 w mojej aplikacji C#. Widziałem gdzieś, że CF również wykonuje uuencode jako część szyfrowania - czy jest w tym jakaś prawda? – czuroski

10

Przejrzałem kod Railo jako ktoś tutaj wspomniany w komentarzach.

Poniżej przedstawiono CFMX_Compat przeniesiony do C# ze źródła Java Railo. Zobacz przykład użycia.

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

Oto przykład użycia, który Hex-koduje zaszyfrowany tekst, a następnie odszyfrowuje to samo.

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

Ten port C# kodu Railo jest rzeczywistym algorytmem roboczym, który odwzorowuje szyfrowanie/odszyfrowywanie CF za pomocą CFMX_COMPAT. Inne dostarczone algorytmy XOR (mimo że poprawne w swoim własnym kontekście) są niekompatybilne z szyfrowaniem/odszyfrowywaniem ColdFusion. To jest wersja, której chcesz użyć. –