Club Builder - Foros de discusión Club Builder
Foro de C++Builder en español
 
 FAQFAQ   BuscarBuscar   MiembrosMiembros   Grupos de UsuariosGrupos de Usuarios   RegistrarseRegistrarse 
 PerfilPerfil   Entra para ver tus mensajes privadosEntra para ver tus mensajes privados   EntrarEntrar 

wchar_t y char

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Consultas
Ver tema anterior :: Ver tema siguiente  
Autor Mensaje
Mensaje    Asunto: wchar_t y char Responder citando

¿Por favor alguien me puede decir que está pasando?
Tengo Builder 2010.
Esta función va perfecta con puntero char *:
Código:

void __fastcall TForm1::Encriptar(char *Valor)
{
   int Cod = 48592318, Cont = 0;
   char *V2 = Valor;

    while(Valor[Cont] != NULL)
    {
       V2[Cont] = ~Valor[Cont]^Cod;
        Cont++;
    }
}


pero esta otra que es la misma pero cambiando (char *) por (wchar_t *)
me sale todo el texto en CHINO.
Código:

void __fastcall TForm1::Encriptar(wchar_t *Valor)
{
   int Cod = 48592318, Cont = 0;
   wchar_t *V2 = Valor;

    while(Valor[Cont] != NULL)
    {
       V2[Cont] = ~Valor[Cont]^Cod;
        Cont++;
    }
}

¿Que estoy haciendo MAL?

Aparte de ello, Ninguna de las dos consigue hacer funcionar el salto de linea, es decir:
Código:

String X = "ESTO ES UNA PRUEBA\n y la siguiente linea.";
Encriptar(X.c_str());//Encripto
Encriptar(X.c_str());//Desencripto
ShowMessage(X.cstr());//El salto de Línea no funciona.

El ShowMessage me muestra:
"ESTO ES UNA PRUEBA\n y la siguiente linea."
Es decir, convierte bien pero el ShowMessage no hace caso del salto de linea '\n'
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Responder citando

Tu error está en tu rutina no es simétrica. Trata de esta manera (he eliminado el ~):

Código:
void __fastcall Encriptar(char *Valor)
{
   int Cod = 48592318, Cont = 0;
   char *V2 = Valor;

    while(Valor[Cont])
    {
       V2[Cont] = Valor[Cont]^Cod;
        Cont++;
    }
}


Échale un vistazo a este truco que publique hace tiempo.

Saludos.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Escafandra, Gracias.
4 ojos ven mas que 2. Lo tenia delante de mis narices y no lo veia.
La confución me vino porque con ANSI(AnsiString y *char) funcionaba perfecto, no asi con UNICODE(String y *wchar_t).

La función que comentas, ya la ví, solo decir que esta función de encriptación la utilizo para codificar todo el texto plano del codigo para que si un HACKER hiciese ingenieria inversa, no tubiese pistas de mis mensajes y complicarle un poco mas que averigue los SALTOS en donde pido al usuario por ejemplo que se registre.
Dado que, la voy ha utilizar constantemente, me resulta mas facíl utilizar mi función sin pasar parametros, de otra forma seria muy repetitivo y pesado ya que ahora tengo que encriptar todos los mensajes de mi aplicación.
Por ejemplo en mi codigo pondria:
Código:

STring TEXTO = L"~~ñññññññ~";
ShowMessage(Encriptar(TEXTO.w_str()));

Y el usuario veria el mensaje "GRACIAS POR REGISTRARSE".
Pero si desensamblan mi codigo se veria "~~ñññññññ~".
Por tanto los HACKERS lo tienen un pelin mas complicado.
De nuevo, GRACIAS.
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Responder citando

Escafandra:
No consigo lo que quiero con mi función de encriptación.
Código:

void __fastcall TForm1::Encriptar(wchar_t *Valor)
{
   int i = 0, x = 0;
    unsigned short int Clv[] = {4,6,5,1,3,2,9,8,7};
    unsigned short int p = sizeof(Clv)/2;//Ultima posición del array Clv
    while(Valor[i] != NULL)
    {
      if(x == p) x = 0;
        Valor[i] ^= Clv[x];
        i++;
        x++;
    }
}


Dicha función encripta bien tanto hacia/desde archivo como hacia/desde memoria. Pero...
Tengo un problema que no consigo solucionar, y es el siguiente:
Código:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   String X = L"Hola como estas\npues bien, gracias.";
    Encriptar(X.w_str()); //Encripto en memoria
    Encriptar(X.w_str()); //DesenCripto de memoria

    // El mensaje se muestra correctamente y
    // lo mas importante me respeta el salto de linea (\n) en el mensaje.
    ShowMessage(X.w_str());
}


y...

Código:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    //Paso la cadena ya encriptada
   String X = L"Lii`#afeh$cvubqUfwqcv!aklf+$aw``kh{)"
    Encriptar(X.w_str()); //Desencripto la cadena

    ShowMessage(X.w_str()); //Muestro el mensaje desencriptado

    // Mensaje mostrado tal cual: Hola como estas\npues bien, gracias.
    // Es decir DesenCripta bien, me muestra el salto de línea (\n),
    // pero imprime el salto de linea en lugar de saltar de linea
}


Tampoco entiendo por que el OPERADOR NOT DE BIT (~), no funciona ya que este operador pone los bits CERO a UNO y los UNO a CERO, por tanto deveria de funcionar como encriptador.
Todas estas pruebas las hice en su dia con B2007 y char, pero ahora con B2010 y UNICODE no entiendo por qué no hace las conversiones como se espera que se hiciesen.



Viendo que no encuentro una solución, prodrias ponerme un ejemplo de como codificar un String con la función que pusiste en TRUCOS, o me dices que parametros de ejemplo le puedo pasar a tu función. Es que no entiendo el parametro (void *Source) ni (int Mod)
A todo esto tambien te pregunto, ¿Has probado la función con wchar_t*?
GRACIAS...
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Responder citando

Te pongo un ejemplo. Vamos a encriptar un texto de un Edit:

Código:

BYTE Clave[]={1,2,3,4} // del tamaño que quieras
// Lo copio primero en un buffer.
char *buffer = new char[Edit1->Text.Length()+1];
buffer[Edit1->Text.Length()] = 0; //Ultimo carácter, el nulo
strcpy(buffer, Edit1->Text.c_str());
Crypt(buffer, Edit1->Text.Length(), Clave, 0);


Para desencriptar es igual, lo que tienes que conocer es el tamaño del buffer que encriptas, y la clave que puede ser una cadena de texto (char*) o array de Bytes. Realmente no encriptamos una cadena sino un array de char o si lo prefieres Bytes. Como no dependemos del carácter nulo para conocer el tamaño, podemos encriptar cualquier cosa.

Saludos.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Escafandra, he probado tu función de la siguiente forma
1. Encripto la frase "Hola como estas\npues bien, gracias." y la guardo en un fichero (barman.dat)
2. En el fichero se graba esto "Imoe`œ–ln"fw4žŠ]orva3ß›hdl/$'˜bhcp*"
3. Luego recupero esa línea con tu rutina desencriptandolo y lo muestro por pantalla con ShowMessage();
4. Lo que me muestra la ventana es: "Hola c!mo estac\npues rien, grqcias."
5. Como en my RUTINA, sigue sin ejecutarse el salto de línea (\n), admas desencripta incorrectamente.
Código:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   String Barman = ExtractFilePath(Application->ExeName) + "Barman.dat";
   TStringList* cLineas = new TStringList();
   cLineas->LoadFromFile(Barman.w_str());

    BYTE Clave[]={1,2,3,4}; // del tamaño que quieras
    char *buffer = new char[cLineas->Strings[0].Length()+1];
    buffer[cLineas->Strings[0].Length()] = 0; //Ultimo carácter, el nulo
    strcpy(buffer, AnsiString(cLineas->Strings[0]).c_str());
    Crypt(buffer, cLineas->Strings[0].Length(), Clave, 0);
    ShowMessage(buffer);
}


tu función:
Código:

void __fastcall TForm1::Crypt(void *Source, int Size, char* Clave, int Mod)
{
   BYTE *source = (BYTE*)Source;
   BYTE clave[8];
   int lClave = strlen(Clave);
   for(int n=0; n<8; n++)
     clave[n] = Clave[n%lClave];

   for(int n=0; n<Size; n++, Mod++){
      source[n] ^= clave[Mod%8];
   }
}


¿Que sistema Operativo tienes y que versión del Builder?

Creo que el problema es que tanto tu rutina como la mia leen caracter a caracter y cuando leen '\' lo consideran como un solo caracter no como un caracter especial, tanto tu codigo como el mio deberian de tener en cuenta si existen caracteres epeciales com '\n' ya que las 2 funciones lo tratan como si fuesen, NO 1 Caracter, SINO como 2.

Por otra parte, ¿Por qué funciona cuando encripto y desencripto en memoria? pues porque en la memoria el caracter '\n' ocupa 1byte y NO 2, que es lo que ocupa cuando lo guardas en un archivo. Mas tarde cuando se lee desde disco se ocupan 2bytes; '\' y 'n', por ello la variable no la interpreta como un salto de linea sino como '\\' y 'n', es decir "\\n"
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Responder citando

JesúsGandia escribió:

¿Que sistema Operativo tienes y que versión del Builder?

Windows XP y Builder 5

JesúsGandia escribió:

Creo que el problema es que tanto tu rutina como la mia leen caracter a caracter y cuando leen '\' lo consideran como un solo caracter no como un caracter especial, tanto tu codigo como el mio deberian de tener en cuenta si existen caracteres epeciales...


Esos caracteres especiales no tienen '\', eso es sólo para la sintaxis. '\n' es el caracter 10 y '\r' es el 13...

JesúsGandia escribió:
otra parte, ¿Por qué funciona cuando encripto y desencripto en memoria? pues porque en la memoria el carácter '\n' ocupa 1byte y NO 2, que es lo que ocupa cuando lo guardas en un archivo. Mas tarde cuando se lee desde disco se ocupan 2bytes; '\' y 'n', por ello la variable no la interpreta como un salto de linea sino como '\\' y 'n', es decir "\\n"


No no es esa la explicación. Date cuenta que estas escribiendo en disco con un TStringList, es decir en modo texto. Esta forma de escribir altera los retornos de carro y línea. Al encriptar ya no tienes caracteres y la forma correcta de escribir en un archivo es en modo binario. Este modo no altera ningún dato y la rutina de encriptación vuelve a ser simétrica. Es por eso que en memoria funciona correctamente. Por otro lado, debes usar buffers distintos al puntero devuelto de la cadena de un String (c_str()) porque se pueden corromper, y por supuesto si escribes en ellos.

Conclusión, si quieres guardar tus datos encriptados en disco, abre un archivo binario de escritura...

Saludos.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Me has interpretado mal.
al referirme a caracteres especiales no me referia a caracteres de combinacion de teclas sino a caracteres tales como los que tu mencionas:
\n \r \t ... lo que pretedia decir es que cuando una cadena contine "HOLA VOY A SALTAR A LA LINEA SIGUIENTE\nYA ESTOY EN LA LINEA SIGUIENTE" y utilizas una función para escribier estos datos encriptados de la forma que sea, como el caracter '\n' ya no es tal sino que se ha convertido en 2 caracteres escritos QUE SI SE SABE, a la hora de desencriptar no se lee '\n' sino por ejemplo '}' '~', luego al desencriptarlo un char no entiende el caracter compuesto por }~ que formaban el caracter '\n' antes de que se encriptara.

Por otra parte en lo de que utilizo una lista para escribir y leer es cierto, pero si lees el post anterior, verás que he puesto directamente el codigo encriptado en una variable lo desencripto y se lo paso a otra variable, es decir la segunda variable contiene exactamente el mismo texto que hantes de ser encriptada.
"HOLA VOY A SALTAR A LA LINEA SIGUIENTE\nYA ESTOY EN LA LINEA SIGUIENTE" y entonces el SALTO DE LINEA se deberia de procesar, pero no es así.

Resumiendo lo que pretendo es todos los mensajes de mi programa los voy a escribir ENCRIPTADOS en el codigo y luego en tiempo de ejecución los DESENCRIPTARÉ para que el usuario los vea correctamente. De ahí que necesitase que se ejecutasen los saltos de linea.
Creo que al final, lo que boy a hacer otra función que busque en la cadena desencriptada el caracter '\' y si el siguiente caracter es 'n' borraré la posición de 'n' y asignare el codigo (10) a la posición de '\'. Con esto quedará resuelto y debe de funcionar.

La opción que comentas, de leer y guardar en binario, en mi caso no me valdría, porque no quiero que el texto plano de mi codigo sea exageradamente largo. Aparte esta rutina tambien la utilizo para escribir y leer datos en un archivo .INI de usuario en el cual controlo que no se cambien los caracteres '[' y ']' (SECCIONES), '=' VALORES.

Por cierto, postea que prueben tu función con wchar_t + WINDOWS7 + B2010, porque como apunto en el post anterior hay caracteres que fallan en la conconrdancia al desencriptar.

Antes de terminar, quisiera agradecerte todos los comentarios que has hecho, pues de una forma u otra me han ayudado y por supuesto la ayuda que me ofreciste con lo de encontrar el nombre de los ejecutables de los PROCESOS que me interesaban ha sido excelente. Gracias a ello he podido desarrollar lo que queria.
Atentamente, Jesús.
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Responder citando

JesúsGandia escribió:
...utilizas una función para escribier estos datos encriptados de la forma que sea, como el caracter '\n' ya no es tal sino que se ha convertido en 2 caracteres


No es así, el caracter '\n' (10) no se convierte en dos caracteres sigue siendo un Byte pero de otro valor.

El problema está en que el texto encriptado ya no es texto y por lo tanto no se debe tratar de cargar en un String. Después del encriptado pueden aparecer caracteres nulos donde no los había, o caracteres 13 ('\r') o 10 ('\n'). Como las lecturas de archivos modo texto modifican los retorno de linea y carro, además los TStringList modifican, según esos mismos retornos en número de líneas o Strings, el texto encriptado se corrompe y aparecen esos defectos que comentas.

JesúsGandia escribió:
verás que he puesto directamente el codigo encriptado en una variable lo desencripto y se lo paso a otra variable, es decir la segunda variable contiene exactamente el mismo texto que hantes de ser encriptada.

Lo que veo es que lees un archivo en un TStringList y luego lo pasas a un buffer, es la lectura del texto encriptado mediante el StringList lo que lo corrompe, pues es "interpretado". El modo binario no interpreta.

Para que te hagas una idea de como influye, incluso entre distintos programas editores de texto, en el notepad un retorno de línea viene dado por 0x0D0A, es decir "\r\n". Si quitamos el carácter 0x0D ('\r') ya no reconoce el retorno de línea, pero ese archivo leído por WordPad, mantiene el retorno de línea sólo con un '\n'. Por eso es importante no usar ningún tipo de almacenamiento intermedio en modo texto de lo encriptado, para evitar interpretaciones de los retornos, y evitar la aparición de caracteres nulos que amputarían el texto final.

JesúsGandia escribió:
Resumiendo lo que pretendo es todos los mensajes de mi programa los voy a escribir ENCRIPTADOS en el codigo y luego en tiempo de ejecución los DESENCRIPTARÉ para que el usuario los vea correctamente. De ahí que necesitase que se ejecutasen los saltos de linea.


La función que te comenté la diseñé entre otras cosas para lo que tu quieres. Yo lo que hago es encriptar el texto, pasar los bytes a números tipo texto separados por comas con lo que creo una cadena, en otra aplicación encriptadora, y el resultado, una cadena de texto consistente en números separados por comas, lo pego en el código fuente como definición de un buffer:
Código:

BYTE Buff[] = {1,56,90.....};

Esto luego lo desencripta el código. Funciona a la perfección.



Saludos.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

OK, Entendido.
¿Que función utilizas para capturar las secuencias numéricas y pasarlas como char a otra cadena?
Lo he intentado con:
Código:

char *strtok(char *s1, const char *s2);
wchar_t *wcstok(wchar_t *s1, const wchar_t *s2);


y no consigo lo que quiero...
Ya guardo todo el TEXTO como secuencias decimales separadas por COMA: "128,13,58,"

¿podrias poner un ejemplo, si no te es muy laborioso de como recoges esos valores separados por COMA y los pasas a otra CADENA en forma de CARACTER?

Así Encripto y convierto CARACTERES encriptados en VALORES numéricos
separados por COMAS:
Código:

void __fastcall TfrmEncriptar::BntCripTextoClick(TObject *Sender)
{
   String T = "";
      MemOri->Text = CrMen(MemOri->Text);// Encripta TEXTO
    for(int i = 1; i <MemOri>Text.Length(); i++)
       T += String(int(MemOri->Text[i])) + L",";

    T.Delete(T.Length(),1);
    MemOri->Text = T;
}


Texto a Encriptar = "Encriptado"
cadena guardada resultado de la encriptación = "227,200,197,212,207,214,210,199,194,201"
decirte tambien que trabajo con UNICODESTRING y wchar_t



Posdata: No he contestado antes porque desde mi ubicación el foro no funcionaba.

Gracias de antemano...
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Responder citando

escafandra, ya lo he conseguido.
Me gustaria tu Opinión, por si se puede mejorar el código.
Esto solo es una prueba de que funciona.
Código:

void __fastcall TfrmEncriptar::BntCripTextoClick(TObject *Sender)
{
   String T = "";// Creo String Auxiliar
    int x = MemOri->Text.Length();//Guardo numero de elementos de la CADENA

    MemOri->Text = CrMen(MemOri->Text);// Encripto el Texto de la CADENA
    for(int i = 1; i <MemOri>Text.Length(); i++)
       T += String(int(MemOri->Text[i])) + L" ";//Convieto los Caracteres a valores decimales separados por ESPACIOS

    T.Delete(T.Length(),1);//Cuando termino, Borro el ultimo caracter de la cadena que es un ESPACIO
    MemOri->Text = T;// Paso el texto de T a la CADENA

   T = ""; //Limpio el String Auxiliar
   //Paso los valores decimales de los caracteres encriptados al String Auxiliar T
   T += wchar_t(StrToInt(wcstok(MemOri->Text.w_str(), L" ")));
    for(int i = 1; i < x; i++)
   {
      T += wchar_t(StrToInt(wcstok(NULL, L" ")));
   }

    //Muestro la conversión de los valores decimales de la codificacion que estan guardados en el String Auxiliar
    ShowMessage(CrMen(T));//Perfecto, todo bien, utilizando UnicodeString
}
//---------------------------------------------------------------------------

_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Responder citando

JesúsGandia escribió:
...No he contestado antes porque desde mi ubicación el foro no funcionaba...


Tranquilo. Yo también he tenido problemas de conexión estos días pasados.

JesúsGandia escribió:
escafandra, ya lo he conseguido.
Me gustaria tu Opinión, por si se puede mejorar el código.

Bien, me alegro. Veo algo peligroso en el código:
Código:
MemOri->Text = CrMen(MemOri->Text);// Encripto el Texto de la CADENA

Encriptas asumiendo que el final de la cadena lo encontrarás en el texto encriptado y asignas éste a un String. Esto no es problema para encriptar pero si para el proceso contrario. Supón que por azar un carácter encriptado de como resultado 0, entonces al asignarlo a un String, la cadena se habrá truncado en ese carácter y al desencriptar lo considera como fin de cadena, obteniendo una cadena truncada. Lo mejor es pasar un buffer y un tamaño a la rutina encriptadora, así te independizas del carácter nulo. Recuerda, la cadena encriptada no es ASCIIZ sino BYTES "sin sentido". Recuerda también que quieres que la función encriptadora sea simétrica.

Si es unicode o no, no va a influir en la encripración del buffer.

Te muestro la rutina que usé en el ejemplo que te puse del programa encriptador:
Código:
void __fastcall TForm2::Button1Click(TObject *Sender)
{
  // Edit1: Texto a encriptar
  // Edit2: Clave de encriptación
  // Edit3: Resultado encriptado representado en números seguidos de coma.

  char *buffer = new char[Edit1->Text.Length()+1];
  buffer[Edit1->Text.Length()] = 0;
  strcpy(buffer, Edit1->Text.c_str());
  Crypt(buffer, Edit1->Text.Length(), Edit2->Text.c_str()); // Encripto
  Edit3->Text = "";
 
  // Lo paso a números
  for(int n=0; n < Edit1->Text.Length(); n++){
    Edit3->Text = Edit3->Text + IntToStr(buffer[n]);
    if(n+1 == Edit1->Text.Length()) break;
    Edit3->Text = Edit3->Text + ", ";
  }
  delete [] buffer;
}


Como verás trabaja con un buffer de tipo char* (PBYTE) y los String de los Edit sólo los uso para obtener el buffer que será encriptado devolviendo en él mismo el resultado. Y por su puesto el resultado de los números seguidos de comas, se devuelve en otro Edit. Esos números son los que traslado al código.


Saludos.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mostrar mensajes de anteriores:   
Cambiar a:  
No puedes publicar temas nuevos en este foro
No puedes responder a temas en este foro
No puedes editar tus mensajes en este foro
No puedes borrar tus mensajes en este foro
No puedes votar en las encuestas de este foro


Hosting WordPress Indedmedia desde 3,99 €
© 2002–2026 Club Builder · Funciona con phpBB.