 |
Club Builder Foro de C++Builder en español
|
| Ver tema anterior :: Ver tema siguiente |
| Autor |
Mensaje |
JesúsGandia Master


Registrado: 17 Jul 2004Mensajes: 403Ubicación: Gandia, Valencia
|
Publicado: Mar 18 May, 2010 8:56 pm Asunto: wchar_t y char |
|
|
¿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 |
|
 |
escafandra Master

Registrado: 29 Nov 2007Mensajes: 625Ubicación: Madrid - España
|
Publicado: Mar 18 May, 2010 11:18 pm Asunto: |
|
|
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 |
|
 |
JesúsGandia Master


Registrado: 17 Jul 2004Mensajes: 403Ubicación: Gandia, Valencia
|
Publicado: Mie 19 May, 2010 12:12 am Asunto: |
|
|
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 |
|
 |
JesúsGandia Master


Registrado: 17 Jul 2004Mensajes: 403Ubicación: Gandia, Valencia
|
Publicado: Mie 19 May, 2010 8:20 pm Asunto: |
|
|
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 |
|
 |
escafandra Master

Registrado: 29 Nov 2007Mensajes: 625Ubicación: Madrid - España
|
Publicado: Mie 19 May, 2010 8:47 pm Asunto: |
|
|
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 |
|
 |
JesúsGandia Master


Registrado: 17 Jul 2004Mensajes: 403Ubicación: Gandia, Valencia
|
Publicado: Mie 19 May, 2010 10:02 pm Asunto: |
|
|
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 |
|
 |
escafandra Master

Registrado: 29 Nov 2007Mensajes: 625Ubicación: Madrid - España
|
Publicado: Mie 19 May, 2010 11:19 pm Asunto: |
|
|
| 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 |
|
 |
JesúsGandia Master


Registrado: 17 Jul 2004Mensajes: 403Ubicación: Gandia, Valencia
|
Publicado: Jue 20 May, 2010 1:35 am Asunto: |
|
|
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 |
|
 |
escafandra Master

Registrado: 29 Nov 2007Mensajes: 625Ubicación: Madrid - España
|
Publicado: Jue 20 May, 2010 7:12 am Asunto: |
|
|
| 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 |
|
 |
JesúsGandia Master


Registrado: 17 Jul 2004Mensajes: 403Ubicación: Gandia, Valencia
|
Publicado: Dom 23 May, 2010 12:51 am Asunto: |
|
|
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 |
|
 |
JesúsGandia Master


Registrado: 17 Jul 2004Mensajes: 403Ubicación: Gandia, Valencia
|
Publicado: Dom 23 May, 2010 2:21 am Asunto: |
|
|
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 |
|
 |
escafandra Master

Registrado: 29 Nov 2007Mensajes: 625Ubicación: Madrid - España
|
Publicado: Dom 23 May, 2010 10:53 pm Asunto: |
|
|
| 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 |
|
 |
|
|
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
|
© 2002–2026 Club Builder · Funciona con phpBB.
|