Read Write PukallCipher - OOP

Applications, Games, Tools, User libs and useful stuff coded in PureBasic
User avatar
StarBootics
Addict
Addict
Posts: 984
Joined: Sun Jul 07, 2013 11:35 am
Location: Canada

Read Write PukallCipher - OOP

Post 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 <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
Last edited by StarBootics on Fri Oct 30, 2020 12:21 am, edited 1 time in total.
The Stone Age did not end due to a shortage of stones !
User avatar
Saki
Addict
Addict
Posts: 830
Joined: Sun Apr 05, 2020 11:28 am
Location: Pandora

Re: Read Write PukallCipher - OOP

Post by Saki »

Hi, nice, but unfortunately legacy and vulnerable.

These things are either safe or they are unsafe, there is nothing in between.
地球上の平和
User avatar
NicTheQuick
Addict
Addict
Posts: 1224
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: Read Write PukallCipher - OOP

Post 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.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
Post Reply