Archive for septiembre, 2012

Cifrado simétrico bajo IOS (parte 2 : Con las manos en la masa)

Este post es la segunda parte de este otro

Hemos hablado de lo que son los cifrados simétricos y asimétricos, para que se usan y ahora tocaría implementarlos en una app IOS.

Como veréis la intención del post no es entrar a las tripas de la librería, cosa que solo os recomiendo en caso de tener mucho tiempo libre, o poca vida social…si bien es útil conocer como funciona, mi intención no es la de asustar a nadie….asi que como dice el lema K.I.S.S. (Keep it simple, stupid…) intentaremos que cualquiera pueda implementar cifrado AES en su app sin volverse loco en el intento…

Una de la maneras mas simples de poder hacerlo, es usando una vez mas las Category que tanto nos facilitan la vida…si no os suena, os dejo este otro post que hice hace un tiempo que os explicara de que se trata

Podriamos usar una Category de NSString (ya que seguro que tus primeras pruebas serán cifrando algún texto corto), aunque como AES nos permite encriptar mucho mas que simple texto, quizás lo mas juicioso seria usar una Category de NSData…y si requieres al final de un NSString pues casteo al canto y ya esta… ;)

Ahora debemos crear una category de NSData a la que en un alarde de ingenio llamaremos AES256.

Al crearla obtendremos una par de archivos el NSData+AES256.h y el NSData+AES256.m. En el archivo .m deberemos hacer un

#import <CommonCrypto/CommonCryptor.h>

para poder usar las funcionalidades que requeriremos en unos momentos…

Implementaremos básicamente 2 métodos que serán los que nos ayudaran a cifrar y descifrar datos.

En el .h los definiremos como con cualquier otro método…

- (NSData *)AES256EncryptWithKey:(NSString *)key;
- (NSData *)AES256DecryptWithKey:(NSString *)key;

Y en el .m su implementación (que es relativamente estándar…aquí he tirado de la documentación oficial de Apple, que es amplia…)

Aquí el que servirá para cifrar :

- (NSData *)AES256EncryptWithKey:(NSString *)key {

	// 'key' should be 32 bytes for AES256, will be null-padded otherwise
	char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
	bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

	// fetch key data
	[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

	NSUInteger dataLength = [self length];

	//See the doc: For block ciphers, the output size will always be less than or
	//equal to the input size plus the size of one block.
	//That's why we need to add the size of one block here
	size_t bufferSize = dataLength + kCCBlockSizeAES128;
	void *buffer = malloc(bufferSize);

	size_t numBytesEncrypted = 0;
	CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES256,
                                          NULL /* initialization vector (optional) */,
                                          [self bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesEncrypted);
	if (cryptStatus == kCCSuccess) {
		//the returned NSData takes ownership of the buffer and will free it on deallocation
		return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
	}

	free(buffer); //free the buffer;
	return nil;
}

Aquí el que usaremos para descifrar :

- (NSData *)AES256DecryptWithKey:(NSString *)key {
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
	char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
	bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

	// fetch key data
	[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

	NSUInteger dataLength = [self length];

	//See the doc: For block ciphers, the output size will always be less than or
	//equal to the input size plus the size of one block.
	//That's why we need to add the size of one block here
	size_t bufferSize = dataLength + kCCBlockSizeAES128;
	void *buffer = malloc(bufferSize);

	size_t numBytesDecrypted = 0;
	CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES256,
                                          NULL /* initialization vector (optional) */,
                                          [self bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesDecrypted);

	if (cryptStatus == kCCSuccess) {
		//the returned NSData takes ownership of the buffer and will free it on deallocation
		return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
	}

	free(buffer); //free the buffer;
	return nil;
}

A partir de la documentación veréis que no es difícil adaptar el algoritmo que necesitéis 3DES, DES, Blowfish etc…a estos dos métodos, tendréis que vigilar ciertas especificidad de cada uno (por ejemplo AES256 trabajo con 32 bytes para la key) pero nada que sea realmente dificil de conseguir…

Ahora os dejo una lineas de código para que veáis funcionando todo esto…

Primero no os olvidéis de hacer un import de la Category que habéis creado…

#import "NSData+AES256.h"

Y después usáis esto en el viewController que queráis usar :

    NSString *key = @"este es mi password";
    NSString *secret = @"Este es el texto que queremos cifrar...";

    NSData *plain = [secret dataUsingEncoding:NSUTF8StringEncoding];
    NSData *cipher = [plain AES256EncryptWithKey:key];

    NSLog(@"%s\n",[[cipher description] UTF8String]);

    plain = [cipher AES256DecryptWithKey:key];
    NSLog(@"%s\n",[[plain description] UTF8String]);    
    NSLog(@"%s\n",[[[NSString alloc] initWithData:plain encoding:NSUTF8StringEncoding] UTF8String]);

Con esto veréis en la consola que el cifrado/descifrado funciona…pero eso no significa que sea todo lo correcto que tendría que ser…

Y es que debemos tocar un tema espinoso, el del mal llamado “Idioten Vecktor“. Con el “Idioten Vektor” se están refiriendo al vector de inicialización que se usa para conseguir una mayor complejidad en AES…es decir, no solo usamos nuestro password para cifrar, sino que aplicamos este vector para conseguir que dos “outputs” cifrados con la misma contraseña sean diferentes, pero al descifrarlos podamos volver al estado inicial (espero haberme explicado bien)…

Pues bien, por defecto Common Crypto acepta como parámetro NULL con CCCrypt…en realidad internamente según explican lo llenan de ceros…

Y os preguntareis, y a mi que…y teneis razón en cierta manera, lo que hace Apple es ofrecer un vector de inicialización, del que tu no te tienes que ocupar, y por lo tanto cifras lo que quieras y te olvidas, y al descifrar con la contraseña ya vale…

Entonces porque estoy tocando las narices con esto?¿ Pues porque muchos (vale me incluyo entre los quisquillosos) insisten en que tienes que variar ese vector para conseguir que el hash que sacas sea realmente seguro.

Para que lo entendáis, se trata de dar “menos pistas” a un posible “hacker” que quiera reventar vuestro “cifrado”…

Pues me diréis que fácil, generamos un vector de inicio diferente a cada vez y solucionado…y en cierta manera volvéis a tener razón ya que con esto el cifrado esta solucionado…pero para descifrar también necesitáis ese vector, lo que significa que debéis “conseguirlo” en el momento de descifrar algo…y si bien vuestra contraseña es (o debería ser) “secreta”, vuestro vector tendría que ser como poco “discreto”…y eso implica que tendréis que romperos el coco para transportarlo de manera segura…guardarlo en algún lugar para recuperarlo cuando lo necesitéis etc…Y ese vector no acostumbra a ser algo que puedas “recordar” facilmente…

Y es precisamente porque eso “complica” todo un poco, por lo que Apple ha aceptado como NULL ese parámetro…y es que AES sin vector de inicialización sigue siendo extremadamente seguro…pero evidentemente menos que usándolo… ;)

Como complemento al mismo, estoy acabando de crear (dejarme tiempo…que voy loco últimamente xD) un set de Category’s que quiero que funcionen como un Toolbox para Hashes y cifrado…cuando este todo cerrado lo subo a GitHub;)

Si sois de los que empezáis a preocuparos por la seguridad de vuestros datos bajo IOS espero que este post haya sido de ayuda…se aceptan todo tipo de criticas, consejos etc… ;)

Share

Cifrado simétrico bajo IOS (parte 1 : Teórica)

Este post vendría en cierta manera a completar el de Generación de Hashes en Objective-C.

Cuando lo escribía vi que el post se convertía en algo demasiado largo, y siendo sincero, un pelín tedioso…así que he decidido cortarlo en dos.

Otro de los puntos importante es que mucha gente requiere de usar datos cifrados, ya sea para guardarlos en el propio terminal, para pasarlo como parámetros hacia una API o para mil cosas más, pero se asustan ante algo que parece mas complicado de lo que en realidad es…

Apple para variar te lo pone fácil, y existe unas librerías (las Common Crypto) que te permiten hacer todas esas cosas sin volverte loco…quizás no acabes entendiendo del todo como funcionan sus tripas…pero siguiendo ciertas reglas a rajatabla tus datos estarán seguros…o mucho más seguros que si no usas esto…:P ;)

En este primer post encontrareis una parta mas teórica, y en el segundo entraremos a cortar el bacalao… ;)

Bueno, pues vamos por faena…y empezaremos por el cifrado asimétrico.

La criptograma asimétrica :

-Que es, y para que nos puede servir…solo así podemos entender el otro, el simétrico que es el que nos interesa en esta serie de posts…

-Que conocemos como cifrado asimétrico?

La criptografia asimétrica también es conocida como “cifrado de clave publica” o “cifrado de dos llaves” (lo que nos da una pista de por donde van los tiros).

Con esta técnica usamos dos claves creadas por nosotros, para “cifrar” algo, un mensaje, un documento, un archivo etc…

Una de las dos claves creadas es publica y esta se puede “entregar” a la persona que en teoría debe descifrar ese mensaje (existen muchas vías para que esa persona obtenga la clave publica, aunque ese merecería un post solo para eso), la otra clave es “privada” y solo nosotros debemos conocerla, guardarla etc…nadie mas debe tener acceso a la misma.

Ese “par” de claves se obtienen mediante unos algoritmos que aseguran que solo pueden ser creadas una vez y nadie mas podría obtener ese mismo par de claves de manera casual…

Y que conseguimos con eso…?¿ Pues algo realmente interesante…si yo quiero enviarte una información cifrada, y conozco tu llave publica, puedo cifrar algo, y tu y solo tu (usando tu llave privada) podrás descifrarla…

Y si usas tu clave privada para cifrar algo, cualquiera podrá descifrarla usando tu clave publica…Y que conseguimos con esto otro?¿ Pues ademas de cifrar, nos aseguramos de que la persona que ha cifrado el mensaje es realmente quien es…

Y esa es por ejemplo una de las bases de la famosa firma electrónica, cifrado+seguridad del origen del usuario que ha cifrado la información… ;)

La criptografia simétrica :

La criptografía simétrica es también conocida como criptografía de clave secreta…y es la mas común, es por ejemplo la que usamos cada día para loguearnos en una pagina web…

Se dice que el secreto de un buen cifrado simétrico debe residir en la llave y no en el algoritmo…es decir que aunque sepamos/descubramos como están cifrados estos datos, si no conocemos la clave no podremos conseguir el bote de miel… ;)

Los algoritmos han ido mejorando su complejidad con el tiempo pero actualmente los ordenadores permiten descifrar claves con mayor rapidez…es por ello que la complejidad de las claves acaba estando regido por su tamaño…a mas tamaño, mas tiempo necesita el ordenador para “probar” las combinaciones necesarias para conseguir su objetivo…

Por ejemplo uno de los algoritmos que mas se usaban hasta no hace demasiado era DES que usaba una clave de 56 bits o lo que es lo mismo 2 elevado a 56 combinaciones posibles…y eso que puede parecernos una clave muy larga…actualmente no aguantaría un ataque de fuerza bruta (probar automáticamente todas las combinaciones posibles) con un ordenador normal mas que unos días…

Es por ello que ahora los standards mas usado son de 128 bits o 256 que incorporan los algoritmos como 3DES o Blowfish o AES/Rijndael…y según dicen las malas lenguas (y la wikipedia) juntando todos los ordenadores del planeta y trabajando como un enorme cluster, se necesitaría mas tiempo que la propia edad del universo para conseguir descifrar la citada clave…y eso para nuestros menesteres es ya suficientemente seguro… ;)

Este primer post solo quería sobrevolar un poco el mundo del cifrado sin entrar realmente en detalles ya que entiendo que muchos de vosotros solo necesitáis implementar unos métodos que funcionen, y realmente las tripas, el funcionamiento de los mismos tampoco es lo que mas os interesa…

Es por ello que tras este, os he preparado otro post que os permitira implementar en vuestras apps de manera sencilla un cifrado AES, simplemente añadiendo una Category al mismo y llamando a un par de métodos…

También haremos hincapié en el peliagudo tema de lo que algunos denominan el “Idioten Vektor“, una pequeña “laguna se seguridad” (que muchos no consideran como tal) que viene de serie con los metodos de las librerías Common Crypto de IOS…pero todo esto será en el próximo post;)

Share

Php: comprobar sintaxis email

Pequeña función para comprobar si una cadena es un mail usando una expresion regular.

function is_valid_email($email) {
  $result = TRUE;
  if (!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$", $email)) {
    $result = FALSE;
  }
  return $result;
 }
Share

Objective-C : Uso de GOTO…jejeje

Bueno, este snippet viene medio en coña…pero es que existe…y si existe pues hay que ponerlo…:P ;) xD

De la cueva de antaño os dejo el GOTO en Objetive-C :

- (BOOL)aTerribleMethod:(NSString *)iDontKnowWhatImDoing
{
    if(iDontKnowWhatImDoing isEqualToString:@"YES") { 
        [self callAnotherTerribleMethod]; 
        goto bail; 
    }

    if(iDontKnowWhatImDoing isEqualToString:@"SOMETIMES") {
        [self callYetAnotherTerribleMethod];
        goto bail;
    }

    if(iDontKnowWhatImDoing isEqualToString:@"NO") { 
        goto bail;
    }

    //Do a whole bunch of other stuff

    bail:
}

Uhmm, creo que es innecesario el decir que no lo uséis, y que si lo hacéis no digáis que lo habéis visto aquí…:P ;) xDDD

Es más yo lo saque de aqui : Link asi que no me hago responsable…:P ;)

 

Share

Objective-C : Redondear esquinas de un UIView usando una mascara

Los “tuiteros” han propuesto varias opciones igual de validas para redondear las esquinas de un UIView.

@Torcelly  ha propuesto una solución muy sencilla para llegar al mismo resultado usando una mascara…

[myView setBackgroundColor://UIColor];
[[myView layer]setMasksToBounds:YES];
[[myView layer]setCornerRadius:6.0];

y se puede revertir asi :

[myView layer]setMaskToBounds:NO];

Como siempre cualquier colaboración es bienvenida, y de parte de cracks, más! ;)

Share

Objective-C : Redondear esquinas de un UIView

Aqui os traigo un snippet que os permitira (tal como indica el titulo del post) de redondear las esquinas de un UIView…

+(void)roundView:(UIView *)view onCorner:(UIRectCorner)rectCorner radius:(float)radius
{
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds
                                                   byRoundingCorners:rectCorner
                                                         cornerRadii:CGSizeMake(radius, radius)];
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
    maskLayer.frame = view.bounds;
    maskLayer.path = maskPath.CGPath;
    [view.layer setMask:maskLayer];
    [maskLayer release];
}

Este snippet me llego via un foro de Linkedin que lo saco de aqui

Share

Objective-C : Concatenar varios NSSTRING

Aqui os dejo un snippet que usareis a menudo…


NSString *nuevo = [NSString stringWithFormat:@"%@/%@/%@", uno, dos, tres];

Aunque existen varias maneras de hacer esta concatenación, el uso de “stringWithFormat” es simple a la par que elegante… ;)

Share