Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
April 25, 2023 01:49 am GMT

Seguridad en Golang

Cmo escribir cdigo mas seguro en Go?

En esta ocasion, vamos a ver funciones de hash y de cifrado/decifrado con su principal diferencia. Como bonus, una repasada a las funciones pseudo aleatorias del lenguaje.

  1. Intro
  2. Hash con SHA512
  3. Usos comunes del hashing
  4. Cifrado y descifrado
  5. Usos comunes del cifrado
  6. Nmeros aleatorios
  7. Conclusiones

Intro

Para comenzar, tenemos el paquete Crypto de la stdlib nos va a proveer el 100% (casi siempre) de las utilidades que necesitamos. Por eso es importante tener a mano su documentacion oficial para solventar dudas de implementacin y lograr entender los pormenores.
Segundo, pero igual de importante, es que esta operacin es "one way", es decir, con el resultado no puedo volver hacia atrs y obtener el valor ingresado.

Hash con SHA512

Seguramente habrn visto la sigla SHA en algn lugar de la web, curso, etc, sta corresponde a Secure Hash Algorithm y viene de larga data acompandonos. Fue desarrollada en los Estados Unidos en el 2001, por la NSA y aprobada ese mismo ao para su uso, existen variantes del algoritmo, comenzando por SHA-0 (luego vinieron 1, 2 y 3 que es la actual) y el 512 refiere al tamao en bits de la "salida" o el digest en ingls.
EL funcionamiento bsico es muy simple de explicar sin entrar en tecnisismos: recibe una entrada (arreglo de bytes) de cualquier tamao y devuelve una palabra de siempre la misma longitud (en este caso 512 bits). Cabe destacar que la entrada puede ser realmente muy grande, segun los datos oficiales es de (2^128-1).

Ya sabemos como funcionan, ahora un pequo problema que nosotros no nos vamos a encontrar, pero si los involucrados en el desarrollo de estas fantsticas soluciones, fue que al tener un tamao de salida definido y tanta capacidad para recibir muchos valores, se encontron con la no-grata sorpresa de que destintas entradas tenian como respuesta el mismo resultado, comnmente llamadas colisiones.
La buena noticia es que a partir de SHA-2, no se volvieron a encontrar y es algo por lo cual no nos tenemos que preocupar.

Ahora pasamos un poco al cdigo

// hashShortVersion simplemente usa la funcin para del package, devuelve slice de bytes, simple y efectivo.func hashShortVersion(s string) string {    hasher := sha512.Sum512([]byte(s))    return fmt.Sprintf("%x", hasher)}// hasherVersion creamos una interface hash.Hasher, le asignamos una implemntacin de sha512 y usamos el mtodo sum de la interface. Nos puede servir para hacer composicin o polimorfismo, el resultado es distinto al anterior.func hasherVersion(s string) string {    var hasher hash.Hash    hasher = sha512.New()    b := hasher.Sum([]byte(s))    res := fmt.Sprintf("%x", b)    return res}// binaryVersion convierte a binario nuestros datos.func binaryVersion(s string) string {    var hasher hash.Hash    hasher = sha512.New()    hasher.Write([]byte(s))    m, _ := hasher.(encoding.BinaryMarshaler)    _, _ = m.MarshalBinary()    return string(hasher.Sum(nil))}

Como expresan tanto el cdigo y los comentarios, los resultados no son iguales ya que usan mtodos/funciones distintas. El MarshallBinary() no es recomandable usar para guardar los datos en un storage "normal" como bases de datos relacionales, de documentos o archivos porque tiene un formato muy distinto, adems de ser ilegible para los humanos y no podemos compararlos con el operador "==".

Usos mas comunes

Decamos que las funciones hash, tienen como objetivo captar una entrada "digerirla" y devolver un resultado siempre del mismo tamao. No importa si ingresamos un solo caracter, Don Quijote entero o todo el cdigo fuente de el Kernel de Linux, la salida tiene siempre el mismo largo. Y como toda funcin pura, ante la misma entrada, vamos a tener la misma salida, es por eso que el uso mas comn es el de garantizar la autenticidad de un software, cuando entregamos el SHA de un compilado o ejecutable, el usuario que lo descarga puede hacer el mismo proceso y validar que haya descargado el mismo que la documentacin oficial dice.
Por otra parte, un uso muy comn pero que no recomiendo, es para contraseas, ya que existen tablas con muchisimos datos llamadas Rainbow tables que se usan para poder crackear contraseas, por lo que no es un caso de uso muy acertado.

Bueno, hasta ac de hashing, ahora pasamos al cifrado

Cifrado y descifrado

LA principal diferencia con el hashing, es que aca si podemos volver a obtener lo que enviamos en un principio y la segunda, es que ante la misma entrada, podemos no obtener la misma salida (mientras menos colisiones haya, mejor) por sofisticadas funciones matmaticas que se denomina sal (o salt en ingls) y es un conjunto de bits aleatorios que su objetivo es el de, justamente, cambiar el resultado ante los mismos valores de entrada.

ejemplos en cdigo:

func Encrypt(s string) ([]byte, error) {    return bcrypt.GenerateFromPassword([]byte(s), bcrypt.MinCost) // puede ser tambin defaultCost}func Decrypt(encryptedPassword, plainPassword string) error {    return bcrypt.CompareHashAndPassword([]byte(encryptedPassword), []byte(plainPassword))}

Bueno con este si que no nos podemos quejar, lo fcil y claro que es no deja margen de dudas.
Si prueban imprimir solo el string resultante varias veces con la misma entrada, pueden ver como obtienen distintos resultados.

Usos ms comunes

Claramente el uso mas comn (hace muchsimos aos) es el de ocultar un mensaje y que un receptor pueda interpretarlo. En informtica lo vamos a usar extensamente para contraseas, tokens y valores que el usuario enva y son sensibles.

Nmeros aleatorios

Antes de empezar a abordar el tema, no son aleatorios, son pseudo aleatorios y es una definicin terica que pueden ver explicado ac.

En ste cdigo, vemos dos casos de uso muy comunes, el primero es obtener un string aleatorio dado un alfabeto. El parmetro de entrada es uno solo y corresponde a que tan larga debera ser la cadena resultante. As de simple y sencillo.

La segunda funcin, es un poco mas de lo mismo, solo que generamos nicamente nmeros y el parametro de entrada corresponde al lmete superior sin incluir, es decir, si ponemos 1000, vamos a generar un nmero entre 0 y 999.

func GenerateRandomString(n int) (string, error) {    const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"    ret := make([]byte, 0, n)    for i := 0; i < n; i++ {        num, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))        if err != nil {            return "", err        }        ret = append(ret, letters[num.Int64()])    }    return string(ret), nil}func GenerateRandNum(n int) int64 {    b, err := rand.Int(rand.Reader, big.NewInt(int64(n)))    if err != nil {        return 0    }    return b.Int64()}

Con estos dos snippets ya tienen para cubrir bastantes casos.

Conclusiones

Aprendimos (o repasamos) las principales diferencias entre el hashing y el cifrado, tanto conceptualmente como implementaciones en Golang y sus usos mas frecuentes en la industria, tambin como el desarrollos acadmicos.
Por ltimo, cubrimos brevemente que es y como se usa el paquete crypto.Rand y claramente, agregamos un poco de cdigo.

Ya saben, si quieren sponsorearme, pueden hacerlo ac!


Original Link: https://dev.to/tomaslingotti/seguridad-en-golang-4f29

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To