fundamentos Cifrar y descifrar datos

Documentos relacionados
Realizar ejercicios de cifrado por medio de los cuales se comprenderá el funcionamiento e importancia del mismo.

Distinguir entre técnicas de cifrado Simétrico y Asimétrico

Julio César Mendoza T. Ingeniería de Sistemas Quito

Práctica 5. Curso

Aplicar técnicas de encriptamiento con el fin de comprender su funcionamiento.

Delegados y eventos en Visual Basic 2005

En cualquier caso, tampoco es demasiado importante el significado de la "B", si es que lo tiene, lo interesante realmente es el algoritmo.

Departamento CERES Área de Tarjetas Inteligentes Manual de Usuario

Acceso a datos con ADO.NET 2.0 (sin asistentes)

CRIPTOGRAFÍA SIMÉTRICA Y ASIMÉTRICA

Introducción. Algoritmos

Proceso de cifrado. La fortaleza de los algoritmos es que son públicos, es decir, se conocen todas las transformaciones que se aplican al documento

Software Criptográfico FNMT-RCM

Objetivos de la práctica: - Practicar uso de ficheros: abrir, cerrar y tratamiento de información contenida en el fichero.

Criptografía. Por. Daniel Vazart P.

Remesas bancarias de Clientes

Ing. Cynthia Zúñiga Ramos

Como sabemos, en un Sistema de Comunicación de Datos, es de vital importancia

Pruebas de unidad con JUnit

LiLa Portal Guía para profesores

TARIFAS DE VENTA Y DESCUENTOS

Modulo 1 El lenguaje Java

GESTINLIB GESTIÓN PARA LIBRERÍAS, PAPELERÍAS Y KIOSCOS DESCRIPCIÓN DEL MÓDULO DE KIOSCOS

RESUMEN DE CONCEPTOS BASICOS DE PROGRAMACION JAVA

Delegados y eventos Primera parte: En quién delegas tú?

Desarrollo de Servicios Web con JBuilder

GENERACIÓN DE ANTICIPOS DE CRÉDITO

Gestión de Retales WhitePaper Noviembre de 2009

MANUAL DE USUARIO DE LA APLICACIÓN DE ACREDITACION DE ACTIVIDADES DE FORMACION CONTINUADA. Perfil Entidad Proveedora

Bases de la Firma Electrónica: Criptografía

Introducción a la Firma Electrónica en MIDAS

Semana 14: Encriptación. Cifrado asimétrico

Cómo creo las bandejas del Registro de Entrada /Salida y de Gestión de Expedientes?

Para descargar la versión más reciente de Skype accedemos al sitio web de Skype y luego hacemos clic en Descargar Skype para escritorio de Windows.

TPVFÁCIL. Caja Real. Definiciones.

Manual CMS Mobincube

Tutorial BMS Server Studio UDP

ALGORITMICA Y PROGRAMACION POR OBJETOS I

MANUAL DE AYUDA MODULO TALLAS Y COLORES

POLÍTICA DE PRIVACIDAD DEL SITIO WEB DE KARDAMILI. Lineamientos generales

Para detalles y funcionalidades ver Manual para el Administrador

ISEC Labs #11. Despliegue y restauración segura de volúmenes cifrados con TrueCrypt. Javier Moreno jmoreno<arroba>isecauditors.com

Manual Instalación de certificados digitales en Outlook 2000

Manual de usuario: Portal de Consulta de Facturación Electrónica

Ejercicios - Persistencia en Android: ficheros y SQLite

x

Tipos primitivos y clases de interés

Manual para usuarios USO DE ONEDRIVE. Universidad Central del Este

TEMA 1: SISTEMAS INFORMÁTICOS. Parte 2: representación de la información

GVisualPDA Módulo de Almacén

Creación de materiales didácticos Aplicaciones para dispositivos móviles Lección 4

POLÍTICA DE PRIVACIDAD PARA APLICACIONES MÓVILES GRUPOCOPESA. 1. información que se obtiene la aplicación y su utilización

GENERACIÓN DE TRANSFERENCIAS

Contenidos. Funciones (suplemento) Funciones. Justificación del uso de Funciones

CRIPTOGRAFIA. Qué es, usos y beneficios de su utilización. Universidad Nacional del Comahue

LEER Y ESCRIBIR ARCHIVOS O FICHEROS EN C. FOPEN, FCLOSE, MODOS DE ACCESO READ, WRITE Y APPEND (CU00536F)

Manual de Instalación y Uso para El software i2cryptlight

Aplicaciones seguras con ClaseSeguridad

Programación Orientada a Objetos con Java

Como crear una red privada virtual (VPN) en Windows XP

Semana 13: Encriptación. Cifrado simétrico

MANUAL USUARIO DEPORWIN ALTAS, BAJAS, NÚMERO DE ABONADOS V /04/2014 [DEPORWIN]

Direcciones IP IMPLANTACIÓN DE SISTEMAS OPERATIVOS 1º ASIR. En redes IPv4.

MANUAL DE PRACTICUM12 PARA CENTROS EDUCATIVOS ÁMBITO MÁSTER

Traslado de Copias y Presentación de Escritos. Manual de Usuario V.3.1

Introducción a los Tipos Abstractos de Datos

Gestió n de Certificadó Digital

Introducción a la programación orientada a objetos

PHP y MySQL. Inicio: - Herencia - Palabra clave Final - Polimorfismo - Type Hinting - Abstracción de clases

Backup & Recovery Oracle 9i. Las copias físicas offline, conocidas como Backups en frío, se realizan cuando la Base de Datos está parada.

Guía para el tratamiento en Allegro de recibos para centros no pertenecientes a la Generalitat Valenciana.

Usar componentes.net desde aplicaciones COM

Toda base de datos relacional se basa en dos objetos

Lección 12 Seguridad y criptografía. Universidad de Oviedo / Dpto. de Informática

FIRMA DIGITAL. Claudia Dacak Dirección de Firma Digital Dirección General de Firma Digital y Comercio Electrónico

Hot Potatoes, aplicaciones educativas

UAM MANUAL DE EMPRESA. Universidad Autónoma de Madrid

Servicio de Informática Vicerrectorado de Tecnologías de la Información y la Comunicación

Estructuras de Datos y Algoritmos Práctica I - Curso 2012/13

Seguridad en la transmisión de Datos

Introducción al tipo de dato ARRAY

P á g i n a 1 OPERADOR PC

Ministerio de Educación. Diseño de Presentaciones en la Enseñanza. Módulo 9: Imprimir

Política de la base datos WHOIS para nombres de dominio.eu

Configuración de DNS seguros

Árboles AVL. Laboratorio de Programación II

Curso Internet Básico - Aularagon

Prof. Dr. Paul Bustamante

Encriptación en Redes

MARFIL CONTABILIDAD ACTUALIZACIÓN FEBRERO 2011

V Manual de Portafirmas V.2.3.1

Herramientas CONTENIDOS. MiAulario

Factura Electrónica. Soluciones y Administración de Software S.A. de C.V. Software AD

by Tim Tran:

Contenidos. Archivos en C++ Archivos en C++ Introducción

MANUAL APLICACIÓN. SOFTWARE GESTIÓN DE CLÍNICAS DENTALES

AUTORIZACIÓN DE COMERCIALIZACIÓN EXCEPCIONAL DE MEDICAMENTOS DE USO HUMANO GUÍA PARA LA SOLICITUD DE UNA AUTORIZACIÓN DE COMERCIALIZACIÓN EXCEPCIONAL

FUNDAMENTOS DE PROGRAMACIÓN. SEPTIEMBRE 2005

CURSO: GESTIÓN TERRITORIAL DE LA INFORMACIÓN CATASTRAL Y ADMINISTRACIÓN ELECTRÓNICA. Supuestos Prácticos: Alteración catastral (10/07/2012)

ESCUELA SUPERIOR DE INFORMATICA Prácticas de Estadística UNA SESIÓN EN SPSS

Transcripción:

Guillermo «Guille» Som fundamentos Criptografía práctica El encriptador que lo encripte... debe guardar las claves El desencriptador que lo desencripte... debe conocer las claves La criptografía nos permite proteger los datos de forma tal, que la visualización o modificación de los mismos solo sea posible para aquellos que conozcan la forma en que han sido encriptados. Esto es aplicable no solo a la comunicación entre dos puntos, sino también al contenido de nuestros ficheros.además de proteger la información,también podemos utilizar la criptografía para garantizar que los datos no han sido alterados y que provienen de una fuente fiable. Guillermo Guille Som Es Microsoft MVP de Visual Basic desde 1997. Es redactor de dotnet- Manía, mentor de Solid Quality Iberoamericana, tutor de campusmvp, miembro de Ineta Speakers Bureau Latin America, y autor de los libros Manual Imprescindible de Visual Basic.NET y Visual Basic 2005. http://www.elguille.info Para realizar las tareas criptográficas,.net Framework nos ofrece una serie de clases en las que se implementan algoritmos criptográficos estandarizados; en este artículo veremos algunos de esos algoritmos y cómo usarlos desde C# (en el ZIP que acompaña al artículo se incluye también el código para Visual Basic). Primitivas criptografías Cifrar y descifrar datos Existen diferentes formas de encriptación, conocidas como primitivas criptográficas. A continuación enumeramos esas primitivas y el uso que podemos darle. Cifrado de clave secreta (criptografía simétrica) Realiza la transformación de los datos, impidiendo que terceros los lean. Este tipo de cifrado utiliza una clave secreta compartida para cifrar y descifrar los datos. Cifrado de clave pública (criptografía asimétrica) Realiza la transformación de los datos, impidiendo que terceros los lean. Este tipo de cifrado utiliza un par de claves pública y privada para cifrar y descifrar los datos. Firmas criptográficas Ayudan a comprobar que los datos se originan en una parte específica mediante la creación de una firma digital única para esa parte. En este proceso también se usan funciones hash. Valores hash criptográficos Asigna datos de cualquier longitud a una secuencia de bytes de longitud fija. Los valores hash son únicos estadísticamente; el valor hash de una secuencia de bytes distinta no será el mismo. Podemos realizar el cifrado de datos de dos formas distintas, según sea grande o pequeño el tamaño de los mismos. En el primer caso, podemos usar el cifrado simétrico, en el cual intervienen secuencias (streams), en particular una de tipo CryptoStream, que será la que pasemos a las clases que utilizan este tipo de cifrado. La segunda forma de cifrado normalmente lo aplicaremos a cantidades pequeñas de datos, los cuales estarán almacenados habitualmente en un array de bytes. Pero para poder realizar el cifrado (y posteriormente el descifrado) necesitamos crear las claves para cifrar y descifrar esos datos. En el caso de los algoritmos simétricos, además de una clave también hay que generar un vector de inicialización (IV - Initialization Vector);

ambos hay que mantenerlos en secreto y solo deben conocerlos las dos partes interesadas. Las clases utilizadas en este tipo de algoritmos incluyen métodos para generar esas claves, en particular los métodos GenerateKey() y GenerateIV(), aunque también podemos generarlas de forma manual, por ejemplo basándonos en una cadena; en cualquier caso, al instanciar la clase, se generan tanto la clave como el IV de forma automática. En el código del fuente 1 podemos ver las dos formas de generar esas claves para usar con la clase DESCryptoServiceProvider. Si usamos una cadena a partir de la que generar tanto la clave como el vector de inicialización, debemos asegurarnos de que tiene los bytes necesarios; ese valor lo obtenemos por medio de la propiedad KeySize, que devuelve el número de bits necesarios (1 byte = 8 bits). Por otra parte, los algoritmos asimétricos deben crear una clave pública y otra privada; la clave pública es la que se usará para cifrar el contenido y la privada la usaremos para descifrarlo. Si no indicamos lo contrario en el constructor de las clases que utilizan este tipo de algoritmos, se generarán automáticamente claves con una longitud de 1024 bits, (128 bytes); el rango puede ser de 512 a 1024 en incrementos de 64 bits. Por supuesto, solo debemos exponer la clave pública, que será la usada para cifrar el mensaje, mientras que la clave privada la usaremos para descifrarlo. Estas clases implementan métodos para exportar e importar las claves públicas y/o privadas. Por ejemplo, si queremos generar una cadena en formato XML con la clave pública podemos usar el método ToXmlString() pasándole un valor falso static void generarauto() // Crear claves simétricas automáticamente DESCryptoServiceProvider des = new DESCryptoServiceProvider(); // Estas llamadas no son necesarias // ya que al crear la instancia se generan las claves des.generateiv(); des.generatekey(); // Guardar las claves generadas byte[] biv = des.iv; byte[] bkey = des.key; Console.WriteLine( La longitud de la clave (KeySize) es de 0 bits, des.keysize); Console.WriteLine( La longitud de la clave es de 0 bytes, bkey.length); static void generarmanual(string clave) // Crear la clave manualmente a partir de una cadena de texto DESCryptoServiceProvider des = new DESCryptoServiceProvider(); // Averiguar la longitud de las claves int bits = des.keysize; // Establecer la clave secreta // La longitud de la cadena debe ser de al menos (bits/8) bytes int cant = bits / 8; if (clave.length < cant) clave += new string( F, cant - clave.length); // Convertir la cadena en un array de bytes des.key = Encoding.Default.GetBytes(clave.Substring(0, cant)); des.iv = Encoding.Default.GetBytes(clave.Substring(0, cant)); // Guardar las claves generadas byte[] biv = des.iv; byte[] bkey = des.key; Console.WriteLine( La longitud de la clave (KeySize) es de 0 bits, des.keysize); Console.WriteLine( La longitud de la clave es de 0 bytes, bkey.length); Fuente 1. Generación de claves 43

// La longitud de la clave puede ser de 512 a 1024 bits // en incrementos de 64 bits DSACryptoServiceProvider dsa = new DSACryptoServiceProvider(640); Console.WriteLine( La longitud de la clave es de 0 bits, dsa.keysize); // Exportar las claves generadas como cadena XML string clavepublica = dsa.toxmlstring(false); Console.WriteLine( Clave pública:\n0, clavepublica); Console.WriteLine(); // Las claves pública y privada string claveprivada = dsa.toxmlstring(true); Console.WriteLine( Clave pública y privada:\n0, claveprivada); Fuente 2. Exportar las claves en formato XML es permitirnos generar un valor hash, por ejemplo del tipo SHA1, con el contenido del texto a cifrar. Mediante ese valor hash podemos comprobar si el mensaje (o texto) ha sido modificado. De esta forma, el mensaje realmente no se cifra, sino solo los valores de comprobación, ya que una de las funcionalidades de este tipo de algoritmos es obtener firmas digitales de mensajes, de forma que podamos comprobar la autenticidad del mismo. Si quisiéramos cifrar el mensaje, podremos usar cualquiera de las clases de cifrado simétrico o bien usar los 44 como parámetro; si queremos exportar las dos claves, tendremos que usar un valor verdadero como parámetro de esa llamada. En el código del fuente 2 vemos cómo usar el método ToXmlString() para guardar las claves usadas al crear la instancia de la clase DSACryptoServiceProvider. Cifrado y descifrado asimétrico Podemos usar la clase RSACrypto- ServiceProvider para cifrar y descifrar textos de forma fácil ya que, a diferencia de la clase DSACryptoServiceProvider, expone métodos para realizar esas tareas. Para cifrar un texto (en realidad un array de bytes), usaremos el método Encrypt(), que devolverá un array con el texto cifrado. Para descifrar un texto previamente cifrado, usaremos el método Decrypt(). En ambos casos debemos usar las claves públicas y privadas. Si lo que queremos es cifrar los datos, solo necesitamos la clave pública; pero para descifrar esos datos, necesitaremos también la clave privada. En el código del fuente 3 vemos cómo podemos usar esta clase para cifrar y descifrar un texto. Comprobar firma digital Una de las características de las clases que utilizan cifrado asimétrico static void pruebarsa() RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); string claves = rsa.toxmlstring(true); string clavepublica = rsa.toxmlstring(false); string texto = Hola, Mundo ; // Para cifrar solo es necesario la clave pública, // aunque también podemos usar las dos claves byte[] datosenc = cifrarrsa(texto, clavepublica); // Para descifrar necesitamos la clave pública y privada string res = descrifrarrsa(claves, datosenc); Console.WriteLine(res); static byte[] cifrarrsa(string texto, string clavepublica) RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); // La clave pública usada para cifrar el texto rsa.fromxmlstring(clavepublica); // Convertimos la cadena a un array de bytes byte[] datos = Encoding.Default.GetBytes(texto); // Generamos los datos encriptados y los devolvemos return rsa.encrypt(datos, false); static string descrifrarrsa(string claves, byte[] datoscifrados) RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); // Las claves usadas para cifrar el texto rsa.fromxmlstring(claves); // Generamos los datos desencriptados byte[] datos = rsa.decrypt(datoscifrados, false); // Devolvemos la cadena original return Encoding.Default.GetString(datos); Fuente 3. Cifrar y descifrar usando RSA

métodos que nos permiten tanto el cifrado como el descifrado. A la hora de usar la firma digital, el que la genera debe disponer de las dos claves, (pública y privada), pero el que comprueba si es correcta solo necesita la clave pública. En el código del fuente 4 podemos ver cómo generar el valor hash cifrado a partir de una cadena de texto; también usamos ese valor hash para comprobar que el texto coincide con el valor hash usado para verificarlo. Para generar el valor hash SHA1 utilizamos un objeto del tipo SHA1CryptoSerstatic void probardsa() DSACryptoServiceProvider dsa = new DSACryptoServiceProvider(); string claves = dsa.toxmlstring(true); string texto = Hola, Mundo ; // Creamos la firma hash usando el texto // y las claves pública y privada // El texto convertido en un valor hash SHA1 byte[] datoshash = clavesha1(texto); // La firma para el valor hash indicado byte[] firmahash = crearfirmadsa(datoshash, claves); // Comprobamos si es correcto, usando la clave pública string clavepublica = dsa.toxmlstring(false); // Comprobamos si los datos son correctos bool res = comprobarfirmadsa(clavepublica, firmahash, datoshash); if (res) Console.WriteLine( La comprobación es correcta. ); else Console.WriteLine( La comprobación no es correcta. ); static byte[] crearfirmadsa(byte[] datoshash, string clavesxml) DSACryptoServiceProvider dsa = new DSACryptoServiceProvider(); // Asignamos las claves indicadas dsa.fromxmlstring(clavesxml); // DSASignatureFormatter dsaformatter = new DSASignatureFormatter(dsa); // Indicamos el algoritmo hash a usar dsaformatter.sethashalgorithm( SHA1 ); // Creamos la firma y la devolvemos return dsaformatter.createsignature(datoshash); static bool comprobarfirmadsa(string clavepublica, byte[] firma, byte[] datoshash) DSACryptoServiceProvider dsa = new DSACryptoServiceProvider(); // Utilizamos la clave pública dsa.fromxmlstring(clavepublica); DSASignatureDeformatter dsadeformatter = new DSASignatureDeformatter(dsa); // El tipo de algoritmo hash a usar dsadeformatter.sethashalgorithm( SHA1 ); // Devolver un valor boolean si la firma es correcta return dsadeformatter.verifysignature(datoshash, firma); static byte[] clavesha1(string texto) // Crear una clave SHA1 a partir del texto indicado. // Devuelve un array de bytes con la clave SHA1 generada UTF8Encoding enc = new UTF8Encoding(); byte[] datos = enc.getbytes(texto); SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider(); return sha.computehash(datos); Fuente 4. Comprobación de firmas digitales 45

46 [ ] NOTA Hay que tener presente que los algoritmos hash como SHA1 solo permiten crear valores hash a partir de un array de bytes, pero no sirven para recuperar el array (o texto normal) a partir de un valor hash. viceprovider, para asegurarnos de que el valor hash generado tiene la longitud adecuada (20 bytes). Algoritmos simétricos Las clases que utilizan el algoritmo simétrico para la encriptación de datos utilizan la misma clave tanto para cifrar como para descifrar los datos, además de que se suelen aplicar cuando tenemos gran cantidad de datos, principalmente los obtenidos a partir de secuencias. En estos casos, utilizaremos una secuencia de tipo CryptoStream para realizar las tareas de cifrado y descifrado. En el código del fuente 5 utilizamos la clase TripleDESCryptoService- Provider para cifrar y posteriormente descifrar el contenido de un fichero. La clase CryptoStream acepta como parámetros del constructor la secuencia usada para leer o escribir, además de un objeto de tipo ICryptoTransform (el cual obtenemos mediante el método CreateEncryptor de la clase de encriptación usada) y el modo en el que la usaremos, para leer o para escribir. En los dos métodos usados en el ejemplo mostrado en el fuente 5, para cifrar/guardar y descifrar/leer, pasamos las claves correspondientes, las cuales deben coincidir. Esas claves las podemos generar nosotros, teniendo en cuenta la longitud esperada, que en el caso de la clase TripleDESCryptoServiceProvider debe ser de 128 a 192 bits. Esas claves también las podemos generar a partir de la creación de una ins- static void cifrarfichero(string fichero, string ficsalida, byte[] bkey, byte[] biv) byte[] datos; using (StreamReader sr = new StreamReader(fichero, Encoding.Default, true)) datos = Encoding.Default.GetBytes(sr.ReadToEnd()); sr.close(); using (FileStream fs = new FileStream(ficSalida, FileMode.Create, FileAccess.Write)) TripleDESCryptoServiceProvider td = new TripleDESCryptoServiceProvider(); td.key = bkey; td.iv = biv; CryptoStream cs = null; try // Crear una secuencia de cifrado cs = new CryptoStream(fs,td.CreateEncryptor(),CryptoStreamMode.Write); // Escribir los datos cifrados en el fichero cs.write(datos, 0, datos.length); catch finally if (cs!= null) cs.close(); static void descifrarfichero(string fichero, string ficsalida, byte[] bkey, byte[] biv) // El proveedor del cifrado y las claves usadas para cifrar TripleDESCryptoServiceProvider td = new TripleDESCryptoServiceProvider(); td.key = bkey; td.iv = biv; // // Crear la secuencia para leer el fichero cifrado using (FileStream fs = new FileStream(fichero, FileMode.Open, FileAccess.Read)) using (CryptoStream cs = new CryptoStream(fs, td.createdecryptor(), CryptoStreamMode.Read)) // Guardar el contenido de fichero descifrado StreamWriter sw = new StreamWriter(ficSalida); StreamReader sr = new StreamReader(cs); sw.write(sr.readtoend()); sw.flush(); sw.close(); Fuente 5. Cifrar y descifrar ficheros

tancia de esa clase y usarlas posteriormente. Si la clave usada para leer/descifrar no es la misma que la que usamos al cifrar el fichero, recibiremos una excepción. En este caso, esas claves las generamos antes de llamar a esos dos métodos, tal como vemos en el código del fuente 6. medio del método GetNonZeroBytes() obtenemos números aleatorios, pero sin incluir el valor cero. En el código del fuente 7 se generan números aleatorios usando los dos métodos comentados; el número de bytes a generar lo dará el tamaño del array pasado como parámetro a los métodos. TripleDESCryptoServiceProvider td = new TripleDESCryptoServiceProvider(); Console.WriteLine( Generando el fichero encriptado ); cifrarfichero(fic1, fic2, td.key, td.iv); Console.WriteLine( Descifrando el fichero ); descifrarfichero(fic2, fic3, td.key, td.iv); Fuente 6.Al cifrar/descifrar los ficheros debemos usar las mismas claves Generar números aleatorios criptográficos Las clases de.net Framework utilizan generadores de números aleatorios para generar las claves criptográficas. Nosotros podemos generar también esos números aleatorios por medio de la clase RNGCryptoServiceProvider, que está basada en la clase abstracta RandomNumberGenerator. La forma de generar esos números aleatorios es por medio de un array de tipo byte en el que indicamos cuántas cifras debe generar, ya que en cada elemento del array se incluirá una cifra. El método usado para generar los números aleatorios es GetBytes(), el cual incluirá todos los valores, incluso el cero. Por [ ] NOTA Cuando usemos un objeto de tipo CryptoStream, debemos asegurarnos de llamar al método Close() para cerrar la secuencia y eliminar los datos de la memoria. Si mientras estamos usando un objeto de tipo CryptoStream se produce un error, la secuencia no se cerrará, por tanto es importante que incluyamos la manipulación de esa secuencia dentro de un bloque using o dentro de un bloque try/catch, para asegurarnos de que la cerramos en el bloque finally. // El número de bytes a generar byte[] numeros = new byte[10]; RNGCryptoServiceProvider rnd = new RNGCryptoServiceProvider(); // En los números generados puede haber ceros rnd.getbytes(numeros); for (int i = 0; i < numeros.length; i++) Console.Write( 0, numeros[i].tostring()); Console.WriteLine(); // Genera números sin incluir el cero rnd.getnonzerobytes(numeros); for (int i = 0; i < numeros.length; i++) Console.Write( 0, numeros[i].tostring()); Fuente 7. Generar números aleatorios criptográficos Conclusiones En este artículo hemos visto de una forma práctica cómo podemos usar algunas de las clases que.net Framework pone a nuestra disposición para cifrar y descifrar la información que queremos transmitir y que de este modo solo sea entendible para aquellos a los que queremos permitírselo. Si usted prefiere usar Visual Basic, en el código que acompaña a este artículo, el cual puede bajar desde el sitio Web de dotnetmanía, se incluyen todos los ejemplos aquí usados tanto en Visual Basic como en C#. 47