Grandamakulo   10-08-2021, 10:03
#1
Edito para: Incluir la elegante solución de @cogier y para mostrar una comparativa de tiempos de cada uno de los métodos. El C está ausente por lo dicho al final del hilo —vamos, que no funciona—:
Código:
 
FacilCript.Main.36: A:24,84229375
FacilCript.Main.43: B:16,3204024537037
FacilCript.Main.57: D:29,4344163310185
FacilCript.Main.64: X:31,245717650463

Pues a raíz de otro comentario me puse a brujulear por la página Rosetta Code, que me encanta, pero hacía un tiempo que no me pasaba por ahí, cuando vi que el algoritmo de Rot13 no estaba implementado para Gambas3.
El algoritmo Rot13, para los pocos que no lo sepan, es una manera de casi encriptar, de encriptar por diversión con un sistema bastante débil, mensajes en foros y antiguas listas de correos por el cifrado de César con un desplazamiento de 13 sobre 26 letras —es decir, la letra 1, la "A", se sustituye por la 14, "N", la "B" por la "O"... la "M" por la "A"—. Sí, justo un desplazamiento que es la mitad del abecedario anglosajón, por eso es reversible, es decir, al aplicar dos veces el algoritmo se obtiene el texto original.
Pues me puse a implementarlo de las dos maneras habituales: por sustitución directa o por rotación, y eso es lo que os traigo: Rot13_a y Rot13_b.
—Oiga, pero bueno, si hay una Rot13_c que no funciona. ¿Qué timo es éste?
Sí, ustedes disculpen. He estado intentando hacer la sustitución directa tal cual se hace en otro lenguajes, por ejemplo con el «tr» de Linux —vaaaale, podría haber empleado «shell» o «exec», pero me parecía que lo fundamental es emplear el propio Gambas3—, pero las funciones Gambas3 no tienen el mismo modo de funcionamiento. De todas maneras, si a alguien se le ocurre cómo, que chille.
—Venga, aceptamos pulpo, etc. Pero, ¿qué c.ñ. es eso de CriptoXOR?
Mire usté, ya puestos me lie y, recordando esos juegos que tenían encriptados archivos con las características de las armas, coches o puntuaciones de forma poco, er, fuerte, y con un sistema sencillo y reversible, pues codifiqué algo parecido a lo que yo empleaba para conseguir el mejor tanque de un juego de los 90: A=((A XOR B) XOR B).
En fin, me voy a almorzar —ahora se llama brunch—. Os dejo con el código.
—Pero bueno, ¿todo este rollo para una chorrada? Pero no se vaya, oiga..., oiga...

Código:
' Gambas module file

Public Sub Main()

  Dim Textos As New String[]
  Dim Texto As String
  Dim Clave As Byte = 13
  
  Dim i As Integer
  Dim Max As Integer = 1000000
  Dim Tic, Tac As Date
  
  Textos.Add("En un lugar de La Mancha con tildes: áéíóúÁÉÍÓÚüÜñÑ¡!1234567890")
  Textos.Add("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
  Textos.Add("Cthulhu R'lyeh Ph'nglui mglw'nafh wgah'nagl fhtagn")
  
  Texto = Textos[0]
  
  Debug "   "; Texto
  Debug "A: "; Rot13_a(Texto)
  Debug "   "; Rot13_a(Rot13_a(Texto))
  Debug "B: "; Rot13_b(Texto)
  Debug "   "; Rot13_b(Rot13_b(Texto))
  Debug "C: "; Rot13_c(Texto)
  Debug "   "; Rot13_c(Rot13_c(Texto))
  Debug "D: "; Rot13_d(Texto)
  Debug "   "; Rot13_d(Rot13_d(Texto))
  Debug "X: "; CriptoXOR(Texto, Clave)
  Debug "   "; CriptoXOR(CriptoXOR(Texto, Clave), Clave)

  Tic = Timer
  For i = 1 To Max
    Rot13_a(Texto)  
  Next
  Tac = Timer
  Debug "A:"; Tac - Tic
  
  Tic = Timer
  For i = 1 To Max
    Rot13_b(Texto)  
  Next
  Tac = Timer
  Debug "B:"; Tac - Tic
  
  ' Tic = Timer
  ' For i = 1 To Max
  '   Rot13_c(Texto)  
  ' Next
  ' Tac = Timer
  ' Debug "C:"; Tac - Tic
  
  Tic = Timer
  For i = 1 To Max
    Rot13_d(Texto)  
  Next
  Tac = Timer
  Debug "D:"; Tac - Tic
  
  Tic = Timer
  For i = 1 To Max
    CriptoXOR(Texto, Clave)  
  Next
  Tac = Timer
  Debug "X:"; Tac - Tic
    
End

Private Function CriptoXOR(Texto As String, Clave As Byte) As String
  Dim Parte As New String[]
  Dim Total As String
  Dim i As Integer

  For i = 0 To Len(Texto) - 1
    Parte.Add(String.Chr(String.Code(Texto, i + 1) Xor Clave))
  Next
  Total = Parte.Join("")
  Return Total
End

Public Function Rot13_a(Texto As String) As String
    Dim i, d As Integer
    Dim Total As String
    
    For i = 0 To Len(Texto) - 1
        d = Asc(Texto[i, 1])
        If d >= 65 And d <= 90 Then
            d += 13
            If d > 90 Then d -= 26
        End If
        If d >= 97 And d <= 122 Then
            d += 13
            If d > 122 Then d -= 26
        End If
        Total = Total & Chr(d)
    Next
    Return Total
End Function

Public Function Rot13_b(Texto As String) As String
  Dim a As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  Dim b As String = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
  Dim Total As String = Texto
  Dim c As String
  Dim i As Integer
  
  For i = 0 To Len(Total) - 1
    c = Total[i, 1]
    If InStr(a, c) Then Mid(Total, i + 1, 1) = b[InStr(a, c) - 1, 1]
  Next
  Return Total
End

Public Function Rot13_c(Texto As String) As String
  Dim Total As String 
  
  Exec ["tr", "a-zA-Z", "n-za-mN-ZA-M", "<<<" & Shell$(Texto)] Wait To Total
  Return Total
End

Private Function Rot13_d(Texto As String) As String 'Cogier
  Dim sChars As String = "abcdefghijklmnopqrstuvwxyzabcdefghijklm"
  Dim iLoop As Integer
  Dim bUCase As Boolean
  Dim sWork As String
  Dim Label As String
  Label = ""
 
  For iLoop = 1 To Len(Texto)
    sWork = Texto[iLoop - 1]
    bUCase = IsUpper(sWork)
    If InStr(sChars, LCase(sWork)) > 0 Then sWork = sChars[InStr(sChars, LCase(sWork)) + 12]
    If bUCase Then sWork = UCase(sWork)
    Label &= sWork
  Next
  Return Label
End

Salidas:
Código:
FacilCript.Main.19:    En un lugar de La Mancha con tildes: áéíóúÁÉÍÓÚüÜñÑ¡!1234567890
FacilCript.Main.20: A: Ra ha yhtne qr Yn Znapun pba gvyqrf: áéíóúÁÉÍÓÚüÜñÑ¡!1234567890
FacilCript.Main.21:    En un lugar de La Mancha con tildes: áéíóúÁÉÍÓÚüÜñÑ¡!1234567890
FacilCript.Main.22: B: Ra ha yhtne qr Yn Znapun pba gvyqrf: áéíóúÁÉÍÓÚüÜñÑ¡!1234567890
FacilCript.Main.23:    En un lugar de La Mancha con tildes: áéíóúÁÉÍÓÚüÜñÑ¡!1234567890
FacilCript.Main.24: C: 
FacilCript.Main.25:    
FacilCript.Main.26: D: Ra ha yhtne qr Yn Znapun pba gvyqrf: áéíóúÁÉÍÓÚüÜñÑ¡!1234567890
FacilCript.Main.27:    En un lugar de La Mancha con tildes: áéíóúÁÉÍÓÚüÜñÑ¡!1234567890
FacilCript.Main.28: X: Hc-xc-axjl-ih-Al-@lcnel-nbc-ydaih~7-ìäàþ÷ÌÄÀÞ×ñÑüܬ,<?>98;:54=
FacilCript.Main.29:    En un lugar de La Mancha con tildes: áéíóúÁÉÍÓÚüÜñÑ¡!1234567890
FacilCript.Main.36: A:24,84229375
FacilCript.Main.43: B:16,3204024537037
FacilCript.Main.57: D:29,4344163310185
FacilCript.Main.64: X:31,245717650463

PS.—Si alguien encuentra cómo simplificar los algoritmos, que chille, me hace el favor. Y ya puestos, que lo suba a Rosetta, que a mí me da pereza  Tongue Tongue Tongue Tongue
Última modificación: 13-08-2021, 11:14 por Grandamakulo.
tercoide   10-08-2021, 12:46
#2
El algoritmo XOR lo use en mis comienzos en la programación. Es bastante tonto, pero funciona para cosas simples.  Creo que se usaba en las primeras versiones de .DOC y .XLS que se guardaban con clave. Muy débiles por cierto. Yo habia hecho un programin en VB que decodificaba el contenido con dicho algoritmo, entre otras hackeadas Cool .

Lejos de ser un experto en el tema, me parece que la fuerza de una codificación se basa en ocultar el algoritmo, mas que alargar la clave.

"Es mejor saber todo de muy poco que muy poco de todo" - anonimo
cogier   10-08-2021, 18:55
#3
Este código funciona para el alfabeto inglés.

Código:
Public Sub TextBox1_Change()

  Dim sChars As String = "abcdefghijklmnopqrstuvwxyzabcdefghijklm"
  Dim iLoop As Integer
  Dim bUCase As Boolean
  Dim sWork As String

  Label1.Text = ""

  For iLoop = 1 To Len(TextBox1.Text)
    sWork = TextBox1.Text[iLoop - 1]
    bUCase = IsUpper(sWork)
    If InStr(sChars, LCase(sWork)) > 0 Then sWork = sChars[InStr(sChars, LCase(sWork)) + 12]
    If bUCase Then sWork = UCase(sWork)
    Label1.Text &= sWork
  Next

End
Grandamakulo   13-08-2021, 11:06
#4
Una consulta muy rápida: ¿alguien sabe por qué no funciona esto?:

Código:
Public Function Rot13_c(Texto As String) As String
  Dim Total As String 
  
  Exec ["tr", "a-zA-Z", "n-za-mN-ZA-M", "<<<" & Shell$(Texto)] Wait To Total
  Return Total
End

Si lo pruebo en la consola funciona perfectamente. Al ejecutarlo en Gambas3 no da error, simplemente no devuelve resultado
Última modificación: 13-08-2021, 11:07 por Grandamakulo.
Shordi   13-08-2021, 11:42
#5
A bote pronto te sobra el Wait. Si pones to variable, el programa ya se detiene y deja la salida en la variable.
Por otra parte Exec se lleva fatal con los pipes, redireccionamientos y demás. Prueba con Shell. El motivo es que Exec no tiene un entorno de shell propio para ejcutarse y eso hace que todas esos truquitos de encadenar comandos y demás no esté disponible.
Prueba con

Shell "echo " & Shell$(Texto) & "|tr a-zA-Z n-za-mN-ZA-M " To Total

Saludos

No podemos regresar
Grandamakulo   13-08-2021, 12:27
#6
¡¡Perfecto!!, funcionó. —Y lo entendí, que es lo fundamental Smile .—
  
Usuarios navegando en este tema: 2 invitado(s)
Powered By MyBB, © 2002-2024 MyBB Group.
Made with by Curves UI.