dev-resources.site
for different kinds of informations.
De C# a Go: Logrando Compatibilidad en Codificaci贸n AES y Base64
Hace un par de semanas me enfrent茅 a un problema interesante: ten铆a que migrar un algoritmo de cifrado AES de C# a Go. En la implementaci贸n en Go ya ten铆amos un algoritmo de cifrado AES, pero no era compatible con la implementaci贸n en C#, y varias pruebas fallaban porque los resultados no coincid铆an, principalmente en el 煤ltimo car谩cter.
El problema era que no ten铆a el c贸digo fuente de la implementaci贸n en C#, solo el binario, una DLL que se usaba en el proyecto de .NET.
Intent茅 obtener el c贸digo fuente de la implementaci贸n en C#, pero no tuve 茅xito. Al ser un proyecto antiguo, no hab铆a documentaci贸n disponible. Afortunadamente, mi jefe fue quien desarroll贸 esta implementaci贸n, pero no recordaba los detalles exactos. Sin embargo, s铆 sab铆a que al final del proceso de cifrado AES se utilizaba una funci贸n para codificar en base64.
Con esta pista, abr铆 el proyecto en .NET e instal茅 la extensi贸n de JetBrains para descompilar el c贸digo fuente, y obtuve el c贸digo de la librer铆a que se usaba para cifrar la informaci贸n.
Finalmente, descubr铆 que el problema no resid铆a en el algoritmo de cifrado AES, sino en la codificaci贸n en base64.
En el c贸digo de C#, al final del proceso de cifrado AES, se usaba la siguiente funci贸n para la codificaci贸n en base64: HttpServerUtility.UrlTokenEncode
.
La funci贸n UrlTokenEncode
es una funci贸n de .NET que codifica una matriz de bytes en una cadena de texto base64 para su transmisi贸n en una URL. Esta funci贸n realiza tres acciones clave que explican la diferencia en los resultados:
Codificaci贸n en Base64 segura para URLs (URL-safe): usa una variante de Base64 que es apta para URLs, reemplazando los caracteres
+
por-
y/
por_
.Eliminaci贸n de caracteres de relleno: la funci贸n elimina los caracteres de relleno
=
que se suelen utilizar en la codificaci贸n est谩ndar de Base64.Adici贸n de un n煤mero al final: la funci贸n a帽ade un n煤mero al final de la cadena para indicar cu谩ntos caracteres de relleno se eliminaron.
Todo esto lo descubr铆 gracias a ChatGPT, no porque sea un experto en base64. Con esta informaci贸n, pude modificar la implementaci贸n en Go para que fuera compatible con la de C#.
En Go, despu茅s de cifrar la informaci贸n con AES, la codificaci贸n en base64 se realiza de la siguiente manera:
encode := base64.RawURLEncoding.EncodeToString(paddedBytes)
Y, finalmente, se a帽ade el n煤mero de caracteres de relleno eliminados al final de la cadena:
// Calcular el n煤mero de caracteres de relleno (`=`) que se habr铆an a帽adido
paddingCount := (4 - len(paddedBytes)%3) % 4
// A帽adir el conteo de relleno al final de la cadena codificada (como hace UrlTokenEncode de C#)
if paddingCount > 0 {
encoded += strconv.Itoa(paddingCount)
}
En la l铆nea paddingCount := (4 - len(paddedBytes)%3) % 4
, se calcula el n煤mero de caracteres de relleno (=
) que luego se a帽aden al final de la cadena codificada en base64:
-
len(paddedBytes)%3
calcula la cantidad de bytes que no se han codificado en base64. -
(4 - len(paddedBytes)%3) % 4
calcula cu谩ntos caracteres de relleno faltan para que la longitud sea divisible por 4. Si no se necesita relleno, el resultado es 0.
En resumen, el problema no era el algoritmo de cifrado AES, sino la codificaci贸n en base64. Gracias a la informaci贸n obtenida de ChatGPT, pude modificar la implementaci贸n en Go para que fuera compatible con la de C#. En este caso, el uso de ChatGPT fue muy 煤til, ya que me ahorr贸 un mont贸n de tiempo y dolores de cabeza; eso s铆, tuve que ir ajustando cada respuesta hasta igualar los resultados de ambas implementaciones.
Featured ones: