martes, 16 de agosto de 2011

Encriptar Información Parte IIa (Usted no lo haga)



Continuando con esta serie de post sobre la encriptación de datos o como me corrigió mi amigo Mario el termino correcto sería codificación de información, antes de entrar en tierra firme y explicar todos los tipos de encriptación voy a ahondar en las malas practicas utilizadas por muchos desarrolladores que piensan que están haciendo sus sitios seguros y protegiendo la información cuando en realidad solo están agregando líneas de código inservibles para el fin que se está solicitando, ¿Por qué les pasa esto?, muy simple, les pasa por que no entienden y no se dan el tiempo de tratar de entender lo que están haciendo, sin ir mas lejos he conocido programadores que logran entregar productos y que no saben explicar cosas tan básicas como lo que significa una clase, una interfaz, herencia, para ellos es hablar otro idioma cuando se les consulta por el patrón singleton o clases abstractas.

Al momento de encriptar información una de las malas prácticas más comunes es la codificación XOR, sin ir más lejos una empresa que empieza con servi…. la ocupaba hace poco en sus url, ésta codificación ocupa la lógica matemática del “o exclusivo” la cual dice que es un tipo de disyunción lógica de dos operandos que es verdad si solo un operando es verdad pero no ambos. En programación el manejo se hace tomando el universo no incluido en los binarios a comparar.

Si en c# realizáramos un XOR entre los enteros 10 y 12, este nos devolvería un 6 y la logica que ocurriría sería la siguiente

int A = 10 ^ 12;

donde

10 = 1010

12 = 1110

A = 110

Es fácil reconocer que lo que se realizó fue una suma de números binarios, explicado esto vamos a un ejemplo de este tipo de codificación.

Como codificar:

public static byte[] Codificar(byte[] cadena)

{

for (int _i = 0; _i < cadena.Length; _i++)

cadena [_i] = (byte)(15 ^ bytACodificar[_i]);

return cadena;

}

Si se fijan a cada elemento del vector de byte le realizó un XOR con un número fijo (en este caso es 15) el cual ocuparé para decodificar la cadena como se ve en la siguiente función:

public static byte[] DeCodificar(byte[] cadena)

{

for (int _i = 0; _i < cadena.Length; _i++)

cadena[_i] = (byte)(15 ^ cadena[_i]);

return cadena;

}

No hay diferencia en las funciones solo se aplica una simple conmutatividad, ¿cuanto se demora un atacante en descifrar esto?, menos de lo que te has demorado en leer el artículo, si aplicáramos esto en un código lo haríamos de la siguiente forma:

String text = "Pablo Hormazabal rlz.";

System.Text.ASCIIEncoding codificador = new System.Text.ASCIIEncoding();

byte[] texto = Codificar(codificador.GetBytes(text));

System.Console.WriteLine(codificador.GetString(texto));

texto = DeCodificar(texto);

System.Console.WriteLine(codificador.GetString(texto));

System.Console.ReadKey();

El resultado es el siguiente:


martes, 9 de agosto de 2011

Como llamar un package que tiene un cursor de entrada y salida desde spring con jdk142_11 (la vieja escuela)

Lo primero que debemos crear es una clase que herede las propiedades de la clase StoredProcedure, dentro de ella definimos la llamada al package de la manera que más les acomode, en el ejemplo les dejo una forma que recomiendo (recordando que no soy dueño de la verdad y si algún lector considera que existe algo mejor le agradecería comentarlo).

public class GetNotiPortal extends StoredProcedure

{

private static final String SPROC_NAME = "Ruta con el Package";

public GetNotiPortal(DataSource ds)

{

super(ds,SPROC_NAME);

declareParameter(new SqlParameter("Parametro1", OracleTypes.VARCHAR));

declareParameter(new SqlParameter("Parametro2",OracleTypes.VARCHAR));

declareParameter(new SqlOutParameter("OUT_CURSORPORTAL ", OracleTypes.CURSOR,new ClaseRowMapper()));

compile();

}

}

Dentro del método GetNotiPortal se hace una llamada al constructor de la clase de la que se hereda (extends), pasándole dos parámetros (Datasource y un String), luego de esto debemos declarar los parámetros de entrada en este caso son dos más la declaración del Cursor definiéndolo con su respectiva clase RowMapper ya que debemos recordar que no es solo un parámetro de entrada si no que cumple doble función.

La siguiente función nos permite ejecutar el package y leer el cursor que contiene la información de salida.

public Resultado[] recuperaDatos(String valor1, String valor2)

{

Resultado[] resultado = null;

GetNotiPortal getNotiPortal = new GetNotiPortal(this.getDataSource());

Map inParams = new HashMap();

inParams.put("Parametro1", valor1);

inParams.put("Parametro2", valor2);

Map results = getNotiPortal.execute(inParams);

if (results.get("OUT_CURSORPORTAL")==null)

{

return resultado;

}

else

{

Set s=results.entrySet();

Iterator it=s.iterator();

while(it.hasNext())

{

Map.Entry m =(Map.Entry)it.next();

Object o = m.getValue();

List l = (List)o;

resultado = new NotificaVo[l.size()];

for (int i=0; i < l.size(); i++)

{

resultado[i]= (NotificaVo)l.get(0);

}

}

return notificaVo;

}

}

Definición de datasource y Rowmapper en el applicationContext.xml

Los datasource y las clases Rowmapper en spring deben definirse dentro del archivo applicationContext.xml de la siguiente manera.

<bean id="Datasource"

class="org.springframework.jndi.JndiObjectFactoryBean">

<property name="jndiName" value="ds/Datasource" />

bean>

<bean id="txManagerDatasource"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="Datasource" />

bean>

<bean id="serviceDatasource"

class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

<property name="transactionManager" ref="txManagerProdSaludNew" />

<property name="target" ref="gestionadorSolicitud" />

<property name="transactionAttributes">

<props>

<prop key="recuperar*">

PROPAGATION_SUPPORTS,readOnly

prop>

<prop key="*">PROPAGATION_REQUIREDprop>

props>

property>

bean>

<bean id="claseRowMapper"

class="package.dao.utils.claseRowMapper">

bean>

<bean id="Nombredelaclase"

class="package.dao.Nombredelaclase ">

<property name="dataSource">

<ref bean="Datasource" />

property>

<property name="claseRowMapper">

<ref bean="claseRowMapper" />

property>

bean>

* El datasource debe estar creado y definido con los mismos parámetros en el servidor.

Ejemplo de Clase Rowmapper

public class ClaseRowMapper implements RowMapper{

public Object mapRow(ResultSet rs, int rowNum) throws SQLException{

ClaseVo claseVo = null;

int id = 0;

if((id = rs.getInt(2)) != 0)

{

claseVo = new NotificaVo();

claseVo.setnum(new Integer(id));

claseVo.setstring(rs.getString(1));

claseVo.setstring(rs.getString(2));

}

return claseVo;

}

}

viernes, 5 de agosto de 2011

Escritorio remoto desde c#

Hoy aprendí algo muy entretenido, el como hacer mi propio escritorio remoto con c#, suena complejo pero es realmente fácil. Lo primero que se debe hacer es agregar en el toolbox un COM llamado Microsoft RDP Client Control.


Lo agregamos en nuestro formulario:

Le damos el nombre que queremos en este caso de ejemplo le ponemos eRemoto y agregamos el siguiente código, en este caso está en el contructor de la clase Formulario y está todo en duro solo por que es un ejemplo, si quieren implementarlo deben hacerlo de una manera mas limpia y parametrizable

public FrmRControl()

{

InitializeComponent();

eRemoto.Name = "Conexión 1";

eRemoto.Server = "ip";

eRemoto.UserName = "nombreusuario";

eRemoto.Domain = "Dominio";

eRemoto.AdvancedSettings2.ClearTextPassword = "clave";

eRemoto.AdvancedSettings2.ConnectToServerConsole = true;

eRemoto.AdvancedSettings2.RDPPort = 3389;

eRemoto.AdvancedSettings2.RedirectDrives = true;

eRemoto.AdvancedSettings2.RedirectPrinters = true;

eRemoto.AdvancedSettings2.RedirectPorts = true;

eRemoto.Connect();

}

Si los parametros están ok al compilar inmediatamente se conectará de forma remota.




lunes, 1 de agosto de 2011

Encriptar Información Parte I (Base de datos)

Muchas veces por motivos de seguridad se nos hace necesario encriptar información. La gran pregunta es donde es más recomendable hacerlo (Aplicación, datos) y mi respuesta es clara “todo depende del proyecto(de claro nada jajaja) en post de ayudar les voy a dejar un tips para Oracle y otro en la segunda parte de este post en C#.

Encriptación de datos en la base de datos

Las ventajas de encriptar cadenas y campos dentro de la base de datos son las siguientes:

1.- Aumento del Nivel de seguridad externo de una solución, ya que hace necesario en la mayoría de los casos que el atacante deba tener un acceso considerable al servidor de base de datos para robar información.

2.- Aumento del Nivel de seguridad interno de una solución, esto se explica mucho mejor con un ejemplo: supongamos que tenemos una tabla Usuario en donde se almacena el rut y el password, si no tenemos encriptada la información ésta será accesible por todos los funcionarios (dba, desarrolladores) que tengan acceso al esquema.

Las desventajas:

1.- A más datos encriptados más lento y complejo será nuestro trabajo y el acceso a los datos, hay que encriptar sólo lo necesario.

2.- Si un proyecto no ésta bien diseñado en cuanto a niveles de seguridad, la encriptación solo será un maquillaje sin consistencia.

A continuación les dejo una función que encripta los datos y a su vez transforma la cadena encriptada a un Hexadecimal, esto último es solo si quieren ocupar esta cadena desde una aplicación Web.

CREATE OR REPLACE FUNCTION CINTEGRALC.encript(url varchar2)

RETURN varchar2 IS

hexvalue varchar2(5000);

enc_key RAW(8) := UTL_RAW.cast_to_raw('EDC34rfv');

l_enc_val varchar2 (2000);

l_enc_val_raw raw(2000);

l_mod number := DBMS_CRYPTO.ENCRYPT_DES

+DBMS_CRYPTO.CHAIN_ECB

+DBMS_CRYPTO.PAD_PKCS5;

BEGIN

l_enc_val_raw := dbms_crypto.encrypt

(

UTL_I18N.STRING_TO_RAW(url,'WE8ISO8859P1'),

l_mod,

enc_key

);

l_enc_val:= UTL_I18N.RAW_TO_CHAR(l_enc_val_raw,'WE8ISO8859P1');

for i in 1..length(l_enc_val) loop

hexvalue := hexvalue||hextoraw(to_char(ascii(substr(l_enc_val, i, 1)), 'FMXX'));

end loop;

RETURN hexvalue;

END encript;

Dentro de ésta función la que realmente hace la magia es DBMC_CRYPTO.ENCRYPT en este caso me pide tres parámetros:

1.- UTL_I18N.STRING_TO_RAW(url,'WE8ISO8859P1'), -> cadena a encriptar mas el tipo de globalización de Oracle.

2.- l_mod -> este es el tipo de cifrado, en este caso le solicitamos que opere con un cifrado en bloque de 3

3.- enc_key -> por último la clave con la que se está encriptando les recomiendo útilizar una clave con la misma estructura que se define en el ejemplo

En Sql server 2005 y 2008 es con la siguiente función encryptbypassphrase es tan sencillo que no necesita ejemplo