Page 1 of 1

Read Write PukallCipher - OOP

Posted: Mon Oct 19, 2020 7:08 pm
by StarBootics
Hello everyone,

There is an OOP style library based on Guimauve's original code, see here PukallCipher - Update V1.1.0
I have stripped the security level to 256 bits (let me know if you are interested with the multiple security level feature).

I'm releasing it in hope it might be useful to some one.

Best regards
StarBootics

Code: Select all

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; AUTOMATICALLY GENERATED CODE, DO NOT MODIFY
; UNLESS YOU REALLY, REALLY, REALLY MEAN IT !!
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Code generated by : Dev-Object - V1.1.0
; Project name : Read Write PukallCipher
; File name : Read Write PukallCipher - OOP.pb
; File Version : 1.0.1
; Programmation : OK
; Programmed by : StarBootics
; Creation Date : October 18th, 2020
; Last update : October 29th, 2020
; Coded for PureBasic : V5.72
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; This library is meant to be use when security is needed to Read
; and Write a binary file. This is a symetric crypting algorythm 
; with 256 bits security level. Based on Guimauve's original code 
; see here :
;
; https://www.purebasic.fr/english/viewtopic.php?f=12&t=37733
; 
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

DeclareModule PukallCipher
  
  Interface PukallCipher
    
    GetKey.s()
    SetKey(P_Key.s)
    
    PC_WriteString(FileID.i, P_String.s)
    PC_WriteByte(FileID.i, P_Value.b)
    PC_WriteAsciiCharacter(FileID.i, P_Value.a)
    PC_WriteWord(FileID.i, P_Value.w)
    PC_WriteUnicodeCharacter(FileID.i, P_Value.u)
    PC_WriteCharacter(FileID.i, P_Value.c)
    PC_WriteLong(FileID.i, P_Value.l)
    PC_WriteQuad(FileID.i, P_Value.q)
    PC_WriteInteger(FileID.i, P_Value.i)
    PC_WriteFloat(FileID.i, P_Value.f)
    PC_WriteDouble(FileID.i, P_Value.d)
    
    PC_ReadString.s(FileID.i)
    PC_ReadByte.b(FileID.i)
    PC_ReadAsciiCharacter.a(FileID.i)
    PC_ReadWord.w(FileID.i)
    PC_ReadUnicodeCharacter.u(FileID.i)
    PC_ReadCharacter.c(FileID.i)
    PC_ReadLong.l(FileID.i)
    PC_ReadQuad.q(FileID.i)
    PC_ReadInteger.i(FileID.i)
    PC_ReadFloat.f(FileID.i)
    PC_ReadDouble.d(FileID.i)
    
    Free()
    
  EndInterface
  
  Declare.i New(P_Key.s = "PukallCipher")
  
EndDeclareModule

Module PukallCipher
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Sizing Constants <<<<<
  
  #PUKALLCIPHER_X1A0_MAX = 16
  #PUKALLCIPHER_CLE_MAX = 32
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Structures declaration <<<<<

  Structure Private_Members
    
    VirtualTable.i
    Key.s
    
  EndStructure
 
  Structure Cipher
    
    Ax.l
    Bx.l
    Cx.l
    Dx.l
    Sx.l
    X1A2.l
    Res.l
    Counter.l
    Inter.l
    X1A0.l[#PUKALLCIPHER_X1A0_MAX]
    Cle.c[#PUKALLCIPHER_CLE_MAX]
    StringLength.l
    Char.c
    Rep.c
    Dxx.c
    Exx.c
    Cfc.l
    Cfd.l
    
  EndStructure
  
  Macro Private_Code(CipherA)
    
    CipherA\Dx = CipherA\X1A2 + CipherA\Counter
    CipherA\Ax = CipherA\X1A0[CipherA\Counter] 
    CipherA\Bx = $015A
    CipherA\Cx = $4E35
    
    Swap CipherA\Ax, CipherA\Sx
    Swap CipherA\Ax, CipherA\Dx
    
    If CipherA\Ax <> 0
      CipherA\Ax = CipherA\Ax * CipherA\Bx
    EndIf
    
    Swap CipherA\Ax, CipherA\Cx
    
    If CipherA\Ax <> 0
      CipherA\Ax = CipherA\Ax * CipherA\Sx
      CipherA\Ax = CipherA\Ax + CipherA\Cx
    EndIf
    
    Swap CipherA\Ax, CipherA\Sx
    
    CipherA\Ax = CipherA\Ax * CipherA\Bx
    CipherA\Dx = CipherA\Cx + CipherA\Dx
    CipherA\Ax = CipherA\Ax + 1
    CipherA\X1A2 = CipherA\Dx
    CipherA\X1A0[CipherA\Counter] = CipherA\Ax
    CipherA\Counter = CipherA\Counter + 1
    CipherA\Res = CipherA\Ax ! CipherA\Dx
    
  EndMacro 
  
  Macro Private_Assemble(CipherA)
    
    CipherA\X1A0[0] = CipherA\Cle[0] * 256 + CipherA\Cle[1]
    
    Private_Code(CipherA)
    
    CipherA\Inter = CipherA\Res
    
    KeyIndex = 2
    
    For Index = 1 To #PUKALLCIPHER_X1A0_MAX - 1
      CipherA\X1A0[Index] = CipherA\X1A0[Index-1] ! CipherA\Cle[KeyIndex] * 256 + CipherA\Cle[KeyIndex+1]
      Private_Code(CipherA)
      CipherA\Inter = CipherA\Inter ! CipherA\Res
      KeyIndex + 2
    Next
    
    CipherA\Counter = 0
    
  EndMacro
  
  ; <<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Gettors <<<<<

  Procedure.s GetKey(*This.Private_Members)
    
    ProcedureReturn *This\Key
  EndProcedure

  ; <<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Settors <<<<<

  Procedure SetKey(*This.Private_Members, P_Key.s)
    
    If P_Key <> ""
      *This\Key = P_Key
    Else
      *This\Key = "PukallCipher"
    EndIf
    
  EndProcedure
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Write on binary file instructions <<<<<
  
  Procedure PC_WriteString(*This.Private_Members, FileID.i, P_String.s)
    
    Cipher.Cipher
    
    UseMD5Fingerprint()
    NormKey.s = StringFingerprint(*This\Key, #PB_Cipher_MD5)
    
    For KeyIndex = 0 To #PUKALLCIPHER_CLE_MAX - 1
      Cipher\Cle[KeyIndex] = Asc(Mid(NormKey, KeyIndex + 1, 1))
    Next
    
    Cipher\Sx = 0
    Cipher\X1A2 = 0
    Cipher\Counter = 0
    
    Cipher\StringLength = Len(P_String) - 1
    
    WriteLong(FileID, Cipher\StringLength)
    
    For BufferIndex = 0 To Cipher\StringLength
      
      Cipher\Char = Asc(Mid(P_String, BufferIndex + 1,1))
      
      Private_Assemble(Cipher)
      
      Cipher\Cfc = Cipher\Inter >> 8
      Cipher\Cfd = Cipher\Inter & 255
      
      For KeyIndex = 0 To #PUKALLCIPHER_CLE_MAX - 1
        Cipher\Cle[KeyIndex] = Cipher\Cle[KeyIndex] ! Cipher\Char
      Next
      
      Cipher\Char = Cipher\Char ! (Cipher\Cfc ! Cipher\Cfd)
      Cipher\Dxx = Cipher\Char >> 4
      Cipher\Exx = Cipher\Char & 15
      WriteCharacter(FileID, $61 + Cipher\Dxx)
      WriteCharacter(FileID, $61 + Cipher\Exx)
      
    Next
    
  EndProcedure
  
  Procedure PC_WriteByte(*This.Private_Members, FileID.i, P_Value.b)
    
    If P_Value < 0
      Sign.s = "-"
      P_Value = P_Value * -1
    EndIf
    
    PC_WriteString(*This, FileID, Sign + RSet(Str(P_Value), 6, "0"))
    
  EndProcedure
  
  Procedure PC_WriteAsciiCharacter(*This.Private_Members, FileID.i, P_Value.a)
    
    PC_WriteString(*This, FileID, RSet(Str(P_Value), 6, "0"))
    
  EndProcedure
  
  Procedure PC_WriteWord(*This.Private_Members, FileID.i, P_Value.w)
    
    If P_Value < 0
      Sign.s = "-"
      P_Value = P_Value * -1
    EndIf
    
    PC_WriteString(*This, FileID, Sign + RSet(Str(P_Value), 10, "0"))
    
  EndProcedure
  
  Procedure PC_WriteUnicodeCharacter(*This.Private_Members, FileID.i, P_Value.u)
    
    PC_WriteString(*This, FileID, RSet(Str(P_Value), 10, "0"))
    
  EndProcedure
  
  Procedure PC_WriteCharacter(*This.Private_Members, FileID.i, P_Value.c)
    
    PC_WriteString(*This, FileID, RSet(Str(P_Value), 10, "0"))
    
  EndProcedure
  
  Procedure PC_WriteLong(*This.Private_Members, FileID.i, P_Value.l)
    
    If P_Value < 0
      Sign.s = "-"
      P_Value = P_Value * -1
    EndIf
    
    PC_WriteString(*This, FileID, Sign + RSet(Str(P_Value), 22, "0"))
    
  EndProcedure
  
  Procedure PC_WriteQuad(*This.Private_Members, FileID.i, P_Value.q)
    
    If P_Value < 0
      Sign.s = "-"
      P_Value = P_Value * -1
    EndIf
    
    PC_WriteString(*This, FileID, Sign + RSet(Str(P_Value), 42, "0"))
    
  EndProcedure
  
  Procedure PC_WriteInteger(*This.Private_Members, FileID.i, P_Value.i)
    
    If P_Value < 0
      Sign.s = "-"
      P_Value = P_Value * -1
    EndIf
    
    PC_WriteString(*This, FileID, Sign + RSet(Str(P_Value), 42, "0"))
    
  EndProcedure
  
  Procedure PC_WriteFloat(*This.Private_Members, FileID.i, P_Value.f)
    
    PC_WriteString(*This, FileID, StrF(P_Value, 14))
    
  EndProcedure
  
  Procedure PC_WriteDouble(*This.Private_Members, FileID.i, P_Value.d)
    
    PC_WriteString(*This, FileID, StrD(P_Value, 25))
    
  EndProcedure

  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Read on binary file instructions <<<<<
  
  Procedure.s PC_ReadString(*This.Private_Members, FileID.i)
    
    Cipher.Cipher
    
    UseMD5Fingerprint()
    NormKey.s = StringFingerprint(*This\Key, #PB_Cipher_MD5)
    
    For KeyIndex = 0 To #PUKALLCIPHER_CLE_MAX - 1
      Cipher\Cle[KeyIndex] = Asc(Mid(NormKey, KeyIndex + 1,1))
    Next
    
    Cipher\Sx = 0
    Cipher\X1A2 = 0
    Cipher\Counter = 0
    
    Cipher\StringLength = ReadLong(FileID)
    
    For BufferIndex = 0 To Cipher\StringLength
      
      Cipher\Rep = ReadCharacter(FileID)
      Cipher\Dxx = (Cipher\Rep - $61) << 4
      
      Cipher\Rep = ReadCharacter(FileID)
      Cipher\Exx = Cipher\Rep - $61
      
      Cipher\Char = Cipher\Dxx + Cipher\Exx
      
      Private_Assemble(Cipher)
      
      Cipher\Cfc = Cipher\Inter >> 8
      Cipher\Cfd = Cipher\Inter & 255
      Cipher\Char = Cipher\Char ! (Cipher\Cfc ! Cipher\Cfd)
      
      For KeyIndex = 0 To #PUKALLCIPHER_CLE_MAX - 1
        Cipher\Cle[KeyIndex] = Cipher\Cle[KeyIndex] ! Cipher\Char
      Next
      
      DecryptedString.s + Chr(Cipher\Char)
      
    Next 
    
    ProcedureReturn DecryptedString
  EndProcedure
  
  Procedure.b PC_ReadByte(*This.Private_Members, FileID.i)
    
    ProcedureReturn Val(PC_ReadString(*This, FileID))
  EndProcedure
  
  Procedure.a PC_ReadAsciiCharacter(*This.Private_Members, FileID.i)
    
    ProcedureReturn Val(PC_ReadString(*This, FileID))
  EndProcedure
  
  Procedure.w PC_ReadWord(*This.Private_Members, FileID.i)
    
    ProcedureReturn Val(PC_ReadString(*This, FileID))
  EndProcedure
  
  Procedure.u PC_ReadUnicodeCharacter(*This.Private_Members, FileID.i)
    
    ProcedureReturn Val(PC_ReadString(*This, FileID))
  EndProcedure
  
  Procedure.c PC_ReadCharacter(*This.Private_Members, FileID.i)
    
    ProcedureReturn Val(PC_ReadString(*This, FileID))
  EndProcedure
  
  Procedure.l PC_ReadLong(*This.Private_Members, FileID.i)
    
    ProcedureReturn Val(PC_ReadString(*This, FileID))
  EndProcedure
  
  Procedure.q PC_ReadQuad(*This.Private_Members, FileID.i)
    
    ProcedureReturn Val(PC_ReadString(*This, FileID))
  EndProcedure
  
  Procedure.i PC_ReadInteger(*This.Private_Members, FileID.i)
    
    ProcedureReturn Val(PC_ReadString(*This, FileID))
  EndProcedure
  
  Procedure.f PC_ReadFloat(*This.Private_Members, FileID.i)
    
    ProcedureReturn ValF(PC_ReadString(*This, FileID))
  EndProcedure
  
  Procedure.d PC_ReadDouble(*This.Private_Members, FileID.i)
    
    ProcedureReturn ValD(PC_ReadString(*This, FileID))
  EndProcedure
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The destructor <<<<<

  Procedure Free(*This.Private_Members)
      
    FreeStructure(*This)
    
  EndProcedure
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Constructor <<<<<

  Procedure.i New(P_Key.s = "PukallCipher")
    
    *This.Private_Members = AllocateStructure(Private_Members)
    *This\VirtualTable = ?START_METHODS
    
    SetKey(*This, P_Key)
    
    ProcedureReturn *This
  EndProcedure
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Entries of the virtual table <<<<<

  DataSection
    START_METHODS:
    Data.i @GetKey()
    Data.i @SetKey()
    Data.i @PC_WriteString()
    Data.i @PC_WriteByte()
    Data.i @PC_WriteAsciiCharacter()
    Data.i @PC_WriteWord()
    Data.i @PC_WriteUnicodeCharacter()
    Data.i @PC_WriteCharacter()
    Data.i @PC_WriteLong()
    Data.i @PC_WriteQuad()
    Data.i @PC_WriteInteger()
    Data.i @PC_WriteFloat()
    Data.i @PC_WriteDouble()
    Data.i @PC_ReadString()
    Data.i @PC_ReadByte()
    Data.i @PC_ReadAsciiCharacter()
    Data.i @PC_ReadWord()
    Data.i @PC_ReadUnicodeCharacter()
    Data.i @PC_ReadCharacter()
    Data.i @PC_ReadLong()
    Data.i @PC_ReadQuad()
    Data.i @PC_ReadInteger()
    Data.i @PC_ReadFloat()
    Data.i @PC_ReadDouble()
    Data.i @Free()
    END_METHODS:
  EndDataSection
  
EndModule

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code generated in : 00.001 seconds (87000.00 lines/second) <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

CompilerIf #PB_Compiler_IsMainFile
  
  PC.PukallCipher::PukallCipher = PukallCipher::New()
  
  Varw.w = 32700
  Varl.l = -2147483645
  Varq.q = 9223372036854775800
  Varf.f = 2 * #PI
  Vard.d = 3 * #PI
  Text.s = "J'aime les déesses nordiques super sexy !"
  
  Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
  Debug "; Test on file "
  Debug ""
  Debug "Original data : "
  
  Debug Varw
  Debug Varl
  Debug Varq
  Debug Varf
  Debug Vard
  Debug Text
  Debug ""
  
  If CreateFile(0, "Test.pc")
    
    PC\SetKey("PureBasic 5.72")
    
    PC\PC_WriteWord(0, Varw) 
    PC\PC_WriteLong(0, Varl)  
    PC\PC_WriteQuad(0, Varq)
    
    PC\SetKey("")
    
    PC\PC_WriteFloat(0, Varf)
    PC\PC_WriteDouble(0, Vard)
    PC\PC_WriteString(0, Text)
    
    CloseFile(0)
    
  EndIf 
  
  Debug "Data from the file : " 
  
  If ReadFile(1, "Test.pc")
    
    PC\SetKey("PureBasic 5.72")
    
    Debug PC\PC_ReadWord(1)
    Debug PC\PC_ReadLong(1)
    Debug PC\PC_ReadQuad(1)
    
    PC\SetKey("")
    
    Debug PC\PC_ReadFloat(1)
    Debug PC\PC_ReadDouble(1)
    Debug PC\PC_ReadString(1)
    
    CloseFile(1)
    DeleteFile("Test.pc")
    
  EndIf 
  
  PC\Free()
  
CompilerEndIf

; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<

Re: Read Write PukallCipher - OOP

Posted: Tue Oct 20, 2020 9:42 am
by Saki
Hi, nice, but unfortunately legacy and vulnerable.

These things are either safe or they are unsafe, there is nothing in between.

Re: Read Write PukallCipher - OOP

Posted: Tue Oct 20, 2020 10:22 am
by NicTheQuick
I also would never use my own implementation of a security related algorithm if there is already the same thing available as a library in my operating system which gets automatic updates if necessary.