2010-04-26 17 views
6

tengo un hash de la contraseña que se almacena en una mesa y se puso en su lugar por la siguiente ColdFusion Script-comparar los hashes de contraseñas entre C# y ColdFusion (CFMX_COMPAT)

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

Estoy tratando de añadir algunas funciones fuera de plazo aplicación aC#. Me gustaría poder aprovechar los datos que ya existen para poder autenticar a los usuarios. ¿Alguien sabe cómo puedo replicar el código de ColdFusion anterior en C#?

Gracias por cualquier idea.

+0

¿Qué algoritmo de cifrado usa? – SLaks

+0

Ver mi respuesta a continuación. –

+0

A continuación se muestra el código CFMX_Compat del proyecto Railo portado a C# – Seibar

Respuesta

2

Dejaré el contenido de la respuesta original a continuación para referencia histórica, pero debe tener en cuenta que esto NO es una respuesta que funcione a la pregunta original.

En su lugar, vea la respuesta más votadas en este hilo, por @Terrapin en enero de 2011. Espero que OP vea esto y pueda cambiar la respuesta aceptada. Diablos, incluso marcaré las modificaciones para ver si se puede hacer algo al respecto.


para construir sobre la respuesta de Edward Smith, y los nuevos comentarios por czuroski, aquí está mi solución.

En primer lugar, necesita una función XOR en C#, que he tomado de here y modificado ligeramente.

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

Luego, tomar el resultado de la XOR y base-64 codifican la misma.Después de tener esa cadena, MD5 hash it. El resultado debe coincidir con el resultado del fragmento de código original:

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

Gracias. Lo he intentado pero todavía no funciona. En realidad, la clave que tengo es en realidad una cadena, no una int, así que no sé si eso la está tirando, o si tengo que usar la clave para la codificación de base-64. para codificarla en base-64, ¿puedo simplemente usar Convert.ToBase64String, o no? – czuroski

+0

De acuerdo con [docs] (http://goo.gl/zGbJ), la cadena que se pasa se usa como una semilla aleatoria para generar el valor de la clave entera. Lamentablemente, no tengo más información sobre exactamente cómo obtiene ese valor. Si estuviera en su lugar, podría considerar (1) eliminar el cifrado de las contraseñas existentes (lo suficientemente simple con un script de un solo uso), y (2) reescribir el código CF existente para dejar de utilizar el cifrado. Hashing es suficiente, y el cifrado está desperdiciando CPU en este caso, en mi opinión. –

+0

Sí, estoy de acuerdo en que está desperdiciando la CPU, pero esta es una aplicación supuesta y no puedo cambiar eso ahora mismo. Así que tengo que intentar descifrarlo yo mismo, pero no he tenido suerte. – czuroski

3

MD5 es el algoritmo hash predeterminado para hash(). No soy un programador de C#, pero no debería ser demasiado difícil crear un hash MD5 para compararlo con el resultado de ColdFusion.

En cuanto a encrypt(), ¿hay alguna razón por la que está encriptando el nombre de usuario antes de hash? No puedo pensar en ningún beneficio al hacer esto, pero eso no significa que no haya ninguno. Simplemente lo haría:

Hash(UCase(GetPass.username)) 

Que debería ser más fácil de replicar en C#.

+0

Acepto, el cifrado es trivial, en el mejor de los casos. –

+1

Pero, sus datos ya lo incluyen, por lo que está buscando una respuesta donde pueda utilizar datos que ya están "encriptados". –

+0

Sí, la información ya está allí, así que solo estoy tratando de usarla. – czuroski

1

Una de las soluciones sería tener la DB hacer el hash y encriptación, podría ser más fácil ...

+0

sí - eso sería más fácil. desafortunadamente, no escribí la solicitud inicial, y no quiero cambiarla. – czuroski

1

El "cifrado" por defecto en la FQ es simplemente un XOR:

texto cifrado = base64_encode (texto plano^tecla)

Así, para descifrar:

texto plano = base64_decode (texto cifrado)^tecla

El hash por defecto, como menti oned, es md5.

Editar:

Bueno, más investigación muestra que esto no es cierto - sólo uno de esos mitos generalizados.

No puedo encontrar ninguna documentación del algoritmo real para el método de cifrado CFMX_COMPAT.

Disculpa por la búsqueda inútil.

+0

Supongo que todo se reduce al valor de la variable 'EnCode'. – mwcz

+0

Correcto, esa es solo la clave. Estoy seguro de que OP tiene acceso a él en su código fuente de CF. –

+0

Parece que no puedo hacer que esto coincida. Intenté restringirlo en una página CF de prueba para simplemente encriptar (e ignorar el hash), pero todavía no puedo obtener el valor CF cifrado para que coincida con mi valor C# encriptado. Utilicé una base64 recta encriptada en mi aplicación C#. Vi en alguna parte que CF también realiza un uuencode como parte de la encriptación. ¿Hay algo de cierto en esto? – czuroski

10

miré a través del código Railo como otra persona aquí se menciona en los comentarios.

El siguiente es CFMX_Compat portado a C# desde la fuente de Railo Java. Vea a continuación un ejemplo de uso.

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

He aquí un ejemplo de uso que codifica hexadecimal el texto cifrado, y luego descifra la misma cosa.

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

Este puerto C# del código Railo es el algoritmo de trabajo real que se asigna a Cifrar/Descifrar de CF utilizando CFMX_COMPAT. Otros algoritmos basados ​​en XOR suministrados (aunque correctos en su propio contexto) son incompatibles con el cifrado/descifrado de ColdFusion. Esta es la versión que querrás usar. –

Cuestiones relacionadas