Seite 2 von 2

Re: Verzweifle an Ciphersaber-Verschlüsselung

Verfasst: 02.04.2015 19:17
von nueh
Oh, das hätte ja niemand wissen können, dass ein Verzeichnis aller Strukturen unter Strukturverzeichnis zu finden ist.
:oops:

Du hast teilweise recht, aber mittlerweile ist mir klar, dass Pointer einfach auf Speicheradressen zeigen. Und dass ich diese Zeiger nach Belieben verschieben kann. Mir fehlt vor allem Übung. Und Zeit ...

Re: Verzweifle an Ciphersaber-Verschlüsselung

Verfasst: 06.04.2015 17:47
von nueh
So, mit Hilfe von NicTheQuick und einigen Tagen Zeit ist ein einigermaßen funktionierendes Programm entstanden.

Code: Alles auswählen

; ==============================================================
; Created on:         6.4.2015
; App/Lib-Name:       ciphersaber
; Author:             Niklas Hennigs
; Version:            0.1
; Compiler:           PureBasic 5.31 (MacOS X - x64)
; ==============================================================

Macro ciphersaber
  GetFilePart(ProgramFilename())
EndMacro


Procedure usage()
  PrintN("Usage: " + ciphersaber + " [-d] [-r rounds] key < infile > outfile")
  ;   PrintN("")
EndProcedure


Procedure.s byte2hex(*buffer, length)
  ; returns a string containing *buffer's bytes as lowercase hex (aa bb cc dd ...) wrapped after 66 chars

  Protected Dim hexa.s(length)
  Protected output.s = ""

  For i = 1 To length
    hexa(i) + Hex(PeekA(*buffer + (i - 1)))
    hexa(i) = RSet(hexa(i), 2, "0")
    hexa(i) = LCase(hexa(i))
    output  = output + hexa(i) + " "
    If (i % 22) = 0
      output = output + #CRLF$
    EndIf
  Next

  ProcedureReturn output
EndProcedure


Procedure hex2byte(address, hex$)
  ; converts hex into data.
  ; By Joakim L. Christiansen a.k.a JLC
  ; https://github.com/JoakimCh/JLCs_PB_stuff/blob/master/Hex%20library/hexLibrary.pbi

  Protected i, pos, len
  hex$ = RemoveString(hex$, " ")
  len  = Len(hex$)
  For i = 1 To len Step 2
    PokeB(address + pos, Val("$" + Mid(hex$, i, 2)))
    pos + 1
  Next
EndProcedure


Procedure encrypt(*input.Ascii, inputLen, *output.Ascii, *key.Ascii, keyLen, rounds = 20)

  ; max key length of 246 bytes
  If keyLen > 246
    keyLen = 246
  EndIf

  ; define state array and key array (S2)
  Dim S.a(255)
  Dim S2.a(255)

  ; setup index variables
  i.u = 0
  j.u = 0
  n.u = 0

  ; generate random 10 byte initialization vector (IV) (conveniently at the beginning of output)
  OpenCryptRandom()
  CryptRandomData(*output, 10)

  ; put first 246 bytes of key into S2 array
  CopyMemory(*key, @S2(), keyLen)

  ; copy IV (first 10 bytes of output) to end of user key in S2 array
  CopyMemory(*output, @S2(keyLen), 10)
  *output = *output + 10

  ; fill the array repeating key and IV
  For i = keyLen + 10 To 255
    S2(i) = S2(i - keyLen - 10)
  Next

  ; set up state array
  For i = 0 To 255
    S(i) = i
  Next

  ; mix up the state array
  j = 0
  For n = 1 To rounds
    For i = 0 To 255
      j    = (j + S(i) + S2(i)) % 256
      Swap S(i), S(j)
    Next
  Next

  ; ciphering operation
  j = 0
  i = 0
  n = 0

  While inputLen
    i = (i + 1) % 256
    j = (j + S(i)) % 256
    Swap S(i), S(j)
    n         = (S(i) + S(j)) % 256
    *output\a = *input\a ! S(n)
    *input + 1
    *output + 1
    inputLen - 1
  Wend

EndProcedure


Procedure decrypt(*input.Ascii, inputLen, *output.Ascii, *key.Ascii, keyLen, rounds = 20)

  ; max key length of 246 bytes
  If keyLen > 246
    keyLen = 246
  EndIf

  ; define state array (S) and key array (S2)
  Dim S.a(255)
  Dim S2.a(255)

  ; setup index variables
  i.i = 0
  j.u = 0
  n.u = 0

  ; put first 246 bytes of key into S2 array
  CopyMemory(*key, @S2(), keyLen)

  ; copy initialization vector (IV) from beginning of input to the end of user key in S2 array
  CopyMemory(*input, @S2(keyLen), 10)

  ; move input pointer (*input) ten bytes to start of content
  *input = *input + 10

  ; fill the array repeating key and IV
  For i = keyLen + 10 To 255
    S2(i) = S2(i - keyLen - 10)
  Next

  ; set up state array
  For i = 0 To 255
    S(i) = i
  Next

  ; mix up the state array
  j = 0
  For n = 1 To rounds
    For i = 0 To 255
      j = (j + S(i) + S2(i)) % 256
      Swap S(i), S(j)
    Next
  Next

  ; ciphering operation
  j = 0
  i = 0
  n = 0

  While inputLen
    i = (i + 1) % 256
    j = (j + S(i)) % 256
    Swap S(i), S(j)
    n         = (S(i) + S(j)) % 256
    *output\a = *input\a ! S(n)
    *input + 1
    *output + 1
    inputLen - 1
  Wend

EndProcedure


OpenConsole()

Define argc = CountProgramParameters()

If argc < 1 Or argc > 5
  usage()
  CloseConsole()
  End 1
EndIf

Define key.s   = ""
Define *key
Define decrypt = 0
Define rounds  = 20
Define armored = 0

For i = 0 To argc
  If ProgramParameter(i) = "-d"
    decrypt = 1
  ElseIf ProgramParameter(i) = "-a"
    armored = 1
  ElseIf ProgramParameter(i) = "-r"
    i      = i + 1
    rounds = Val(ProgramParameter(i))
  ElseIf key = ""
    key = ProgramParameter(i)
  EndIf
Next


*key        = AllocateMemory(Len(key))
PokeS(*key, key, -1, #PB_Ascii | #PB_String_NoZero)

ConsoleError("rounds = " + Str(rounds))

; --------------------- read input from stdin
Define TotalSize  = 0
Define BufferFree = 10000
Define *Buffer    = AllocateMemory(BufferFree)

Repeat
  ReadSize = ReadConsoleData(*Buffer + TotalSize, BufferFree) ; read a block of data
  TotalSize + ReadSize
  BufferFree - ReadSize
  If BufferFree < 100  ; resize the buffer if it is not large enough
    BufferFree = 10000
    *Buffer    = ReAllocateMemory(*Buffer, TotalSize + 10000)
  EndIf
Until ReadSize = 0 ; once 0 is returned, there is nothing else to read
; --------------------- read input from stdin

If TotalSize > 0
  Define length            = TotalSize
  Define *input            = *Buffer
  Define *output

  If decrypt
    *output = AllocateMemory(length - 10)
    If armored ; TODO: Ascii-armored Text fabriziert beim Entschlüsseln nur Mist!
      *output      = AllocateMemory(length / 3 - 10)
      Define *temp = AllocateMemory(MemorySize(*input))
      hex2byte(*temp, PeekS(*input, length))
      CopyMemory(*temp, *input, length)
      decrypt(*input, (length / 3), *output, *key, Len(key), rounds)
    Else
      decrypt(*input, (length), *output, *key, Len(key), rounds)
    EndIf
    WriteConsoleData(*output, MemorySize(*output))
  Else
    *output = AllocateMemory(length + 10)
    encrypt(*input, length, *output, *key, Len(key), rounds)
    If armored
      PrintN(byte2hex(*output, MemorySize(*output)))
    Else
      WriteConsoleData(*output, MemorySize(*output))
    EndIf
  EndIf

EndIf
Vielleicht kann ja jemand etwas damit anfangen.
Ich habe noch versucht, Ein- und Ausgabe auch als 'ASCII-armored' Text zu ermöglichen (mit dem Schalter -a). Einige Implementationen bieten das an, z.B. CipherSaber Encryption & Decryption Tool. Die Ausgabe funktioniert kompatibel zu den mir bekannten Programmen, aber die Entschlüsselung haut noch überhaupt nicht hin.

Viele Grüße
Niklas