It is currently Tue Mar 09, 2021 9:40 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 47 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
 Post subject: Rabbit Cipher - Module
PostPosted: Sat Oct 31, 2020 4:16 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jul 07, 2013 11:35 am
Posts: 587
Location: Canada
Hello everyone,

I know some of you are not fans of own implementation of cipher algorithm. So the following code is not for you then, so leave it.

For the others this is something fun to play with.

In the example I'm using the MD5 StringFingerprint() for the key and the InitVector and this is not recommended at all especially for the InitVector.
Maybe creating a CryptRandom() sets of values put into a DataSection will be better for security reasons.

As long as the key is 128 bits and the InitVector is 64 bits in length almost anything is possible to do.

EDIT 1 : This is the 3rd version of the example and this time the code is really safe to use and conform to the RFC 4503 Rabbit Encryption of May 2006 or at least conform to the Appendix B of the document. Sorry for the inconvenience of me posting a not so verified source code at the beginning. The example at the end of the code show how to store keys and Init Vectors into Data Section.

EDIT 2 : Code updated to version 4 due to some issue caused by the PeekL()/PokeL() plus other issues pointed out by Wilbert
EDIT 3 : Code updated to version 4.0.1 for Speed improvement with the Addition() procedure.

THE CODE IS NOW CONSIDERED SAFE TO USE



Best regards
StarBootics

Code:
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Project Name : Rabbit Cipher
; File Name : RabbitCipher - Module.pb
; File Version : 4.0.1
; Programmation : OK
; Programmed by : StarBootics
; Creation Date : October 30th, 2020
; Last update : November 8th, 2020
; Coded for PureBasic : V5.73 Beta 2
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Programming notes
;
; 1. Rabbit was designed by Martin Boesgaard, Mette Vesterager,
;    Thomas Pedersen, Jesper Christiansen and Ove Scavenius.
;
;    https://www.ecrypt.eu.org/stream/rabbitpf.html
;
; 2. Type of Algorithm : Synchronous Stream Cipher
;
; 3. Rabbit has been released into the public domain and may
;    be used freely for any purpose.
;
; 4. I deserve credit only for porting Rabbit Cipher from C to
;    PureBasic. I'm not the original designer of the algorithm
;    so no credit to me for that.
;
; 5. The software is provided "as is" without any express or
;    implied warranty. You are using it at your own risk. The
;    original authors and/or me shall not in any way be liable
;    for any use of this software.
;
; 6. Is this encryption system compatible with the RFC 4503
;    Rabbit Encryption of May 2006 ?
;
;    The Answer is YES !
;
; 7. Special thanks to Wilbert for the simplification of the
;    G function procedure and other issues.
;
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

DeclareModule RabbitCipher
 
  Declare.s Normalizer(Input.s, BitsLength.l)
  Declare Encrypt(*Key, *InitVector, *PlainText, *CipheredText, StringByteLength.l)
  Declare Decrypt(*Key, *InitVector, *PlainText, *CipheredText, StringByteLength.l)
 
EndDeclareModule

Module RabbitCipher
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Structures declaration <<<<<
 
  Structure Rabbit
   
    X.q[8]
    C.q[8]
    Carry.q
   
  EndStructure
 
  Structure Rabbit_Temp
   
    g.q[8]
    OldC.q[8]
   
  EndStructure
 
  Structure Buffer
   
    Buffer.a[16]
   
  EndStructure
 
  Structure Core
   
    Master.Rabbit
    Work.Rabbit
   
  EndStructure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Macros declaration <<<<<
 
  Macro U32V(v)
   
    ((v) & $FFFFFFFF)
   
  EndMacro
 
  Macro ROTL32(v, n)
   
    ((U32V((v) << (n)) | ((v) >> (32 - (n)))))
   
  EndMacro
 
  Macro SWAP32(v)
   
    ((ROTL32((v), 8) & $00FF00FF) | (ROTL32((v), 24) & $FF00FF00))
   
  EndMacro
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Procedures declaration (Private) <<<<<
 
  Procedure.q PeekU32(*Buffer)
   
    ; Even if a quad size is 64-bit, we are
    ; interested only by the first 32-bit.
   
    CopyMemory(*Buffer, @Var.q, 4)
   
    ProcedureReturn Var
  EndProcedure
 
  Procedure PokeU32(*Buffer, Var.q)
   
    ; Even if a quad size is 64-bit, we are
    ; interested only by the first 32-bit.
   
    CopyMemory(@Var, *Buffer, 4)
   
  EndProcedure
 
  Procedure.q U8TO32_LITTLE(*p)
   
    B0.a = PeekA(*p+0)
    B1.a = PeekA(*p+1)
    B2.a = PeekA(*p+2)
    B3.a = PeekA(*p+3)
   
    ProcedureReturn U32V(B0 | B1 << 8 | B2 << 16 | B3 << 24)
  EndProcedure
 
  Procedure.q RABBIT_GFunc(x.q)
   
    x * x
   
    ProcedureReturn U32V(x ! (x >> 32))
  EndProcedure

  Procedure.q Addition(VarA.q, VarB.q, VarC.q = -1)
   
    Result.q = U32V(VarA + VarB)
   
    If VarC >= 0
      Result = U32V(Result + VarC)
    EndIf
   
    ProcedureReturn Result
  EndProcedure

  Procedure RABBIT_NextState(*Rabbit.Rabbit)
   
    ; Temporary variables
    Protected Temp.Rabbit_Temp, Index.l
   
    ; Save old counter values
    For Index = 0 To 7
      Temp\OldC[Index] = *Rabbit\C[Index]
    Next
   
    ; Calculate new counter values
   
    *Rabbit\C[0] = Addition(*Rabbit\C[0], $4D34D34D + *Rabbit\Carry)
    *Rabbit\C[1] = Addition(*Rabbit\C[1], $D34D34D3 + Bool(*Rabbit\C[0] < Temp\OldC[0]))
    *Rabbit\C[2] = Addition(*Rabbit\C[2], $34D34D34 + Bool(*Rabbit\C[1] < Temp\OldC[1]))
    *Rabbit\C[3] = Addition(*Rabbit\C[3], $4D34D34D + Bool(*Rabbit\C[2] < Temp\OldC[2]))
    *Rabbit\C[4] = Addition(*Rabbit\C[4], $D34D34D3 + Bool(*Rabbit\C[3] < Temp\OldC[3]))
    *Rabbit\C[5] = Addition(*Rabbit\C[5], $34D34D34 + Bool(*Rabbit\C[4] < Temp\OldC[4]))
    *Rabbit\C[6] = Addition(*Rabbit\C[6], $4D34D34D + Bool(*Rabbit\C[5] < Temp\OldC[5]))
    *Rabbit\C[7] = Addition(*Rabbit\C[7], $D34D34D3 + Bool(*Rabbit\C[6] < Temp\OldC[6]))
    *Rabbit\Carry = Bool(*Rabbit\C[7] < Temp\OldC[7])

    ; Calculate the g-values
    For Index = 0 To 7
      Temp\g[Index] = RABBIT_GFunc(Addition(*Rabbit\X[Index], *Rabbit\C[Index]))
    Next
   
    ; Calculate new state values
    For Index = 0 To 7
      If Index & 1 = 0
        *Rabbit\X[Index] = Addition(Temp\g[Index], ROTL32(Temp\g[(Index + 7) & 7],16), ROTL32(Temp\g[(Index + 6) & 7], 16))
      Else
        *Rabbit\X[Index] = Addition(Temp\g[Index], ROTL32(Temp\g[(Index + 7) & 7], 8), Temp\g[(Index + 6) & 7])
      EndIf
    Next
   
  EndProcedure
 
  Procedure RABBIT_KeySetup(*Core.Core, *Key)
   
    ; Temporary Variables
    Protected k0.q, k1.q, k2.q, k3.q, Index.l
   
    ; Generate four subkeys
    k0 = U8TO32_LITTLE(*Key + 0)
    k1 = U8TO32_LITTLE(*Key + 4)
    k2 = U8TO32_LITTLE(*Key + 8)
    k3 = U8TO32_LITTLE(*Key + 12)
   
    ; Generate initial state variables
    *Core\Master\X[0] = k0
    *Core\Master\X[2] = k1
    *Core\Master\X[4] = k2
    *Core\Master\X[6] = k3
    *Core\Master\X[1] = U32V(k3 << 16) | (k2 >> 16)
    *Core\Master\X[3] = U32V(k0 << 16) | (k3 >> 16)
    *Core\Master\X[5] = U32V(k1 << 16) | (k0 >> 16)
    *Core\Master\X[7] = U32V(k2 << 16) | (k1 >> 16)
   
    ; Generate initial counter values
    *Core\Master\C[0] = ROTL32(k2, 16)
    *Core\Master\C[2] = ROTL32(k3, 16)
    *Core\Master\C[4] = ROTL32(k0, 16)
    *Core\Master\C[6] = ROTL32(k1, 16)
   
    *Core\Master\C[1] = (k0 & $FFFF0000) | (k1 & $FFFF)
    *Core\Master\C[3] = (k1 & $FFFF0000) | (k2 & $FFFF)
    *Core\Master\C[5] = (k2 & $FFFF0000) | (k3 & $FFFF)
    *Core\Master\C[7] = (k3 & $FFFF0000) | (k0 & $FFFF)
   
    *Core\Master\Carry = 0

    For Index = 0 To 3
      RABBIT_NextState(*Core\Master)
    Next
   
    ; Modify the counters
    For Index = 0 To 7
      *Core\Master\C[Index] ! *Core\Master\X[(Index + 4) & 7]
    Next
   
    ; Copy master instance to work instance
   
    For Index = 0 To 7
      *Core\Work\X[Index] = *Core\Master\X[Index]
      *Core\Work\C[Index] = *Core\Master\C[Index]
    Next
   
    *Core\Work\Carry = *Core\Master\Carry
   
  EndProcedure
 
  Procedure RABBIT_InitVectorSetup(*Core.Core, *InitVector)
   
    ; Temporary variables
    Protected i0.q, i1.q, i2.q, i3.q, Index.l
   
    ; Generate four subvectors
    i0 = U8TO32_LITTLE(*InitVector + 0)
    i2 = U8TO32_LITTLE(*InitVector + 4)
    i1 = (i0 >> 16) | (i2 & $FFFF0000)
    i3 = (i2 << 16) | (i0 & $0000FFFF)
   
    ; Modify counter values
   
    *Core\Work\C[0] = *Core\Master\C[0] ! i0
    *Core\Work\C[1] = *Core\Master\C[1] ! i1
    *Core\Work\C[2] = *Core\Master\C[2] ! i2
    *Core\Work\C[3] = *Core\Master\C[3] ! i3
   
    *Core\Work\C[4] = *Core\Master\C[4] ! i0
    *Core\Work\C[5] = *Core\Master\C[5] ! i1
    *Core\Work\C[6] = *Core\Master\C[6] ! i2
    *Core\Work\C[7] = *Core\Master\C[7] ! i3
   
    ; Copy state variables
   
    For Index = 0 To 7
      *Core\Work\X[Index] = *Core\Master\X[Index]
    Next
   
    *Core\Work\Carry = *Core\Master\Carry
   
    ; Iterate the system four times
   
    For index = 0 To 3
      RABBIT_NextState(*Core\Work)
    Next
   
  EndProcedure
 
  Procedure RABBIT_Process_Bytes(*Core.Core, *Input, *Output, MsgLen.l)
   
    ; Temporary variables
   
    Protected Buffer.Buffer, Index.l
   
    ; Encrypt/decrypt all full blocks
   
    While MsgLen >= 16
     
      ; Iterate the system
      RABBIT_NextState(*Core\Work)
     
      ; Encrypt/decrypt 16 bytes of data
      PokeU32(*Output + 00, PeekU32(*Input + 00) ! *Core\Work\X[0] ! (*Core\Work\X[5] >> 16) ! U32V(*Core\Work\X[3] << 16))
      PokeU32(*Output + 04, PeekU32(*Input + 04) ! *Core\Work\X[2] ! (*Core\Work\X[7] >> 16) ! U32V(*Core\Work\X[5] << 16))
      PokeU32(*Output + 08, PeekU32(*Input + 08) ! *Core\Work\X[4] ! (*Core\Work\X[1] >> 16) ! U32V(*Core\Work\X[7] << 16))
      PokeU32(*Output + 12, PeekU32(*Input + 12) ! *Core\Work\X[6] ! (*Core\Work\X[3] >> 16) ! U32V(*Core\Work\X[1] << 16))
     
      *Input + 16
      *Output + 16
      MsgLen - 16
     
    Wend
   
    ; Encrypt/decrypt remaining data
   
    If MsgLen <> 0
     
      ; Iterate the system
      RABBIT_NextState(*Core\Work)
     
      ; Generate 16 bytes of pseudo-random data */
     
      PokeU32(@Buffer + 00, *Core\Work\X[0] ! (*Core\Work\X[5]>>16) ! U32V(*Core\Work\X[3]<<16))
      PokeU32(@Buffer + 04, *Core\Work\X[2] ! (*Core\Work\X[7]>>16) ! U32V(*Core\Work\X[5]<<16))
      PokeU32(@Buffer + 06, *Core\Work\X[4] ! (*Core\Work\X[1]>>16) ! U32V(*Core\Work\X[7]<<16))
      PokeU32(@Buffer + 12, *Core\Work\X[6] ! (*Core\Work\X[3]>>16) ! U32V(*Core\Work\X[1]<<16))
     
      For Index = 0 To MsgLen - 1
        PokeA(*Output, PeekA(*Input) ! Buffer\Buffer[Index])
        *Output + 1
        *Input + 1
      Next
     
    EndIf
   
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Procedures declaration (Public) <<<<<
 
  Procedure.s Normalizer(Input.s, BitsLength.l)
   
    Bytes.l = BitsLength >> 3
    Output.s = StringFingerprint(Input, #PB_Cipher_MD5)
   
    While StringByteLength(Output) < Bytes
      Output + StringFingerprint(Output, #PB_Cipher_MD5)
    Wend
   
    ProcedureReturn Left(Output, Bytes / SizeOf(Unicode))
  EndProcedure
 
  Procedure Encrypt(*Key, *InitVector, *PlainText, *CipheredText, StringByteLength.l)
   
    RABBIT_KeySetup(Core.Core, *Key)
   
    If *InitVector <> #Null
      RABBIT_InitVectorSetup(Core, *InitVector)
    EndIf
   
    RABBIT_Process_Bytes(Core, *PlainText, *CipheredText, StringByteLength)
   
  EndProcedure
 
  Procedure Decrypt(*Key, *InitVector, *PlainText, *CipheredText, StringByteLength.l)
   
    RABBIT_KeySetup(Core.Core, *Key)
   
    If *InitVector <> #Null
      RABBIT_InitVectorSetup(Core, *InitVector)
    EndIf
   
    RABBIT_Process_Bytes(Core, *CipheredText, *PlainText, StringByteLength)
   
  EndProcedure
 
EndModule

CompilerIf #PB_Compiler_IsMainFile
 
  UseMD5Fingerprint()

  String.s = "Hello, this is a test for Rabbit Cipher !"
 
  Key.s = RabbitCipher::Normalizer("I'm the key !", 128)
  InitVector.s = RabbitCipher::Normalizer("I'm the InitVector !", 64)
 
  StringMemorySize = StringByteLength(String) + SizeOf(Character)
 
  *CipheredText = AllocateMemory(StringMemorySize)
  *CipheredText2 = AllocateMemory(StringMemorySize)
  *PlainText = AllocateMemory(StringMemorySize)
  *PlainText2 = AllocateMemory(StringMemorySize)
 
  RabbitCipher::Encrypt(@Key, @InitVector, @String, *CipheredText, StringByteLength(String))
  RabbitCipher::Encrypt(@Key, #Null, @String, *CipheredText2, StringByteLength(String))
 
  RabbitCipher::Decrypt(@Key, @InitVector, *PlainText, *CipheredText, StringByteLength(String))
  RabbitCipher::Decrypt(@Key, #Null, *PlainText2, *CipheredText2, StringByteLength(String))
 
  PlainText.s = PeekS(*PlainText)
  PlainText2.s = PeekS(*PlainText2)
 
  Debug "Test Real life : Key setup, IV setup and encryption/decryption"
  If String = PlainText
    Debug "Success"
  Else
    Debug "Failure"
  EndIf
 
  Debug "Test Real life : Key setup and encryption/decryption"
  If String = PlainText2
    Debug "Success"
  Else
    Debug "Failure"
  EndIf
 
  FreeMemory(*CipheredText)
  FreeMemory(*CipheredText2)
  FreeMemory(*PlainText)
  FreeMemory(*PlainText2)
 
CompilerEndIf

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

_________________
The Stone Age did not end due to a shortage of stones !


Last edited by StarBootics on Sun Nov 08, 2020 10:11 pm, edited 3 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Rabbit Cipher - Module
PostPosted: Sun Nov 01, 2020 8:54 pm 
Offline
Addict
Addict
User avatar

Joined: Sun Nov 05, 2006 11:42 pm
Posts: 4876
Location: Lyon - France
Works nice here and can be usefull :wink:
Thanks for sharing 8)

_________________
ImageThe happiness is a road...
Not a destination


Top
 Profile  
Reply with quote  
 Post subject: Re: Rabbit Cipher - Module
PostPosted: Sun Nov 01, 2020 10:31 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jul 07, 2013 11:35 am
Posts: 587
Location: Canada
Hello everyone,

This is the second version of the RabbitCipher module. Now you have a choice between the original 128 bits encrypting (64 bits InitVector) or the experimental 256 bits encrypting (128 bits InitVector). I would have liked to contact one of the authors to validate the 256-bit version but apparently their website is no longer online. I hope that I didn't introduce any weaknesses by expanding the 128 bits version to 256 bits.

@Kwai chang caine : You're welcome !

EDIT 1 : Update to version 2.0.1 : Found a bug inside the RABBIT_KeySetup256() procedure.
EDIT 2 : Update to version 2.0.2 : Not really a bug but in the RABBIT_NextState256() I have change the constants.
EDIT 3 : Update to version 2.0.3 : Removed unnecessary steps in the Encrypt() and Decrypt() procedures
EDIT 4 : Update to version 2.0.4 : Error inside RABBIT_KeySetup256() and RABBIT_InitVectorSetup256() procedures.
EDIT 5 : Code suppression due to very serious issue. A new version will be posted in this topic.

Best regards
StarBootics

_________________
The Stone Age did not end due to a shortage of stones !


Last edited by StarBootics on Thu Nov 05, 2020 10:29 pm, edited 2 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Rabbit Cipher - Module
PostPosted: Mon Nov 02, 2020 9:25 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Apr 05, 2020 11:28 am
Posts: 518
Location: Pandora
Nice Code

Best Regards Saki

_________________
地球上の平和


Top
 Profile  
Reply with quote  
 Post subject: Re: Rabbit Cipher - Module
PostPosted: Tue Nov 03, 2020 9:23 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jul 07, 2013 11:35 am
Posts: 587
Location: Canada
Hello everyone,

SEE THE FIRST POST OF THIS TOPIC

Best regards
StarBootics

_________________
The Stone Age did not end due to a shortage of stones !


Last edited by StarBootics on Thu Nov 05, 2020 10:31 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Rabbit Cipher - Module
PostPosted: Tue Nov 03, 2020 10:43 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jun 22, 2003 7:43 pm
Posts: 730
Location: Germany, Saarbrücken
Do you have any information about the the implemented algorithm regarding its security?

_________________
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.


Top
 Profile  
Reply with quote  
 Post subject: Re: Rabbit Cipher - Module
PostPosted: Tue Nov 03, 2020 10:47 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Apr 05, 2020 11:28 am
Posts: 518
Location: Pandora
He does these codes only for the fun of it.
It is certainly not easy to make something like this work.

_________________
地球上の平和


Top
 Profile  
Reply with quote  
 Post subject: Re: Rabbit Cipher - Module
PostPosted: Tue Nov 03, 2020 10:55 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jul 07, 2013 11:35 am
Posts: 587
Location: Canada
NicTheQuick wrote:
Do you have any information about the the implemented algorithm regarding its security?

From Wikipedia :
Quote:
Security

Rabbit claims 128-bit security against attackers whose target is one specific key. If, however, the attacker targets a large number of keys at once and does not really care which one he breaks, then the small IV size results in a reduced security level of 96 bit. This is due to generic TMD trade-off attacks.[6]

A small bias in the output of Rabbit exists,[7] resulting in a distinguisher with 2^247 complexity discovered by Jean-Philippe Aumasson in December 2006. Even though this distinguisher was improved to 2^158 in 2008,[8] it's not a threat to Rabbit's security because its complexity is significantly higher than the brute-force of the key space (2^128).


So pretty secure when implemented correctly.

Best regards
StarBootics

_________________
The Stone Age did not end due to a shortage of stones !


Top
 Profile  
Reply with quote  
 Post subject: Re: Rabbit Cipher - Module
PostPosted: Tue Nov 03, 2020 11:13 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Apr 05, 2020 11:28 am
Posts: 518
Location: Pandora
Because of the way this encryption works, implementation errors are quickly overlooked.
But with other implementations it should be easy to check if everything works correctly.
The security of the key effectively corresponds to a binary key length of 10 bytes.

_________________
地球上の平和


Top
 Profile  
Reply with quote  
 Post subject: Re: Rabbit Cipher - Module
PostPosted: Tue Nov 03, 2020 1:02 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jul 07, 2013 11:35 am
Posts: 587
Location: Canada
Saki wrote:
He does these codes only for the fun of it.
It is certainly not easy to make something like this work.


It would be easy if the original C source code was written according to the documentation. But the main problem we have with PureBasic is the lack of unsigned long integer. Programming this Cipher algorithm is another example why we need unsigned long integer. It's a shame that in 2020 even if PureBasic is a Basic programming language we don't have all standard type available in C or C++.

What I don't understand is the fact that even if the algorithm don't work as it should it's still capable to Encrypt and Decrypt successfully.

Anyway, it's time for me to go to get some sleep.

Best regards
StarBootics

_________________
The Stone Age did not end due to a shortage of stones !


Top
 Profile  
Reply with quote  
 Post subject: Re: Rabbit Cipher - Module
PostPosted: Tue Nov 03, 2020 11:21 pm 
Offline
Addict
Addict
User avatar

Joined: Tue Nov 09, 2010 10:15 pm
Posts: 1756
Maybe you can talk Wilbur into contributing his assembly magic into the routine...


Top
 Profile  
Reply with quote  
 Post subject: Re: Rabbit Cipher - Module
PostPosted: Wed Nov 04, 2020 5:04 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jul 07, 2013 11:35 am
Posts: 587
Location: Canada
Hello everyone,

Apparently using the positive part of a Quad seem to have fixed the negative values in the counter system. That being said this implementation must be very close to the standard. This means the pseudo-random system is pretty efficient as it is and can be used relatively safely. What you can't do is to send / receive encrypted data to any one who may use a standard Rabbit cipher.

If someone is willing to try to make correction to this code to match RFC 4503 Rabbit Cipher of May 2006 you might need these documents :


I had the idea to replace the code in my first post but I have change my mind and I'm posting the version 2.0.0 down here so you can see the change I made.

THE CODE DOWN BELOW IS NOT SAFE TO USE I'M KEEPING IT HERE FOR FOLLOWING POSTS REFERENCES

See the first post of this topic for the Working version.

Best regards
StarBootics
Code:
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Project Name : Rabbit Cipher
; File Name : RabbitCipher - Module.pb
; File Version : 2.0.0
; Programmation : OK
; Programmed by : StarBootics
; Creation Date : October 30th, 2020
; Last update : November 3rd, 2020
; Coded for PureBasic : V5.73 Beta 2
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Programming notes
;
; 1. Rabbit was designed by Martin Boesgaard, Mette Vesterager,
;    Thomas Pedersen, Jesper Christiansen and Ove Scavenius.
;
;    https://www.ecrypt.eu.org/stream/rabbitpf.html
;
; 2. Type of Algorithm : Synchronous Stream Cipher
;
; 3. Rabbit has been released into the public domain and may
;    be used freely for any purpose.
;
; 4. I deserve credit only for porting Rabbit Cipher from C to
;    PureBasic. I'm not the original designer of the algorithm
;    so no credit to me for that.
;
; 5. The software is provided "as is" without any express or
;    implied warranty. You are using it at your own risk. The
;    original authors and/or me shall not in any way be liable
;    for any use of this software.
;
; 6. Is this encryption system compatible with the RFC 4503
;    Rabbit Encryption of May 2006 ?
;
;    The Answer is NO ! And the reason came from the GFunc
;    calculation procedure. We need a unsigned 64-bit integer
;    to store a result of the squaring of the x value in some
;    cases.
;
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

DeclareModule RabbitCipher
 
  Declare.s Normalizer(Input.s, BitsLength.l)
  Declare Encrypt(*Key, *InitVector, *PlainText, *CipheredText, StringByteLength.l)
  Declare Decrypt(*Key, *InitVector, *PlainText, *CipheredText, StringByteLength.l)
 
EndDeclareModule

Module RabbitCipher
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Structures declaration <<<<<
 
  Structure Rabbit
   
    X.q[8]
    C.q[8]
    Carry.q
   
  EndStructure
 
  Structure Rabbit_Temp
   
    g.q[8]
    OldC.q[8]
   
  EndStructure
 
  Structure Buffer
   
    Buffer.a[16]
   
  EndStructure
 
  Structure Core
   
    Master.Rabbit
    Work.Rabbit
   
  EndStructure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Macros declaration <<<<<
 
  Macro U32V(v)
   
    ((v) & $FFFFFFFF)
   
  EndMacro
 
  Macro ROTL32(v, n)
   
    ((U32V((v) << (n)) | ((v) >> (32 - (n)))))
   
  EndMacro
 
  Macro SWAP32(v)
   
    ((ROTL32((v), 8) & $00FF00FF) | (ROTL32((v), 24) & $FF00FF00))
   
  EndMacro
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Procedures declaration (Private) <<<<<
 
  Procedure.q U32TO32_LITTLE(v.q)
   
    Temp.q = SWAP32(v)
   
    ProcedureReturn U32V(Temp)
  EndProcedure
 
  Procedure.q U8TO32_LITTLE(*p)
   
    B0.a = PeekA(*p+0)
    B1.a = PeekA(*p+1)
    B2.a = PeekA(*p+2)
    B3.a = PeekA(*p+3)
   
    ProcedureReturn U32V(B0 | B1 << 8 | B2 << 16 | B3 << 24)
  EndProcedure
 
  Procedure.q RABBIT_GFunc(x.q)
   
    ; Temporary variables
    Protected a.q, b.q, h.q, l.q
   
    ; Construct high and low argument for squaring
   
    a = x & $FFFF
    b = x >> 16
   
    ; Calculate high and low result of squaring
   
    h = (((U32V(a*a)>>17) + U32V(a*b))>>15) + b*b
    l = x*x
   
    ; Return high XOR low
   
    ProcedureReturn U32V(h ! l)
  EndProcedure
 
  Procedure RABBIT_NextState(*Rabbit.Rabbit)
   
    ; Temporary variables
    Protected Temp.Rabbit_Temp, Index.l
   
    ; Save old counter values
    For Index = 0 To 7
      Temp\OldC[Index] = *Rabbit\C[Index]
    Next
   
    ; Calculate new counter values
    *Rabbit\C[0] = U32V(*Rabbit\C[0] + $4D34D34D + *Rabbit\Carry)
    *Rabbit\C[1] = U32V(*Rabbit\C[1] + $D34D34D3 + Bool(*Rabbit\C[0] < Temp\OldC[0]))
    *Rabbit\C[2] = U32V(*Rabbit\C[2] + $34D34D34 + Bool(*Rabbit\C[1] < Temp\OldC[1]))
    *Rabbit\C[3] = U32V(*Rabbit\C[3] + $4D34D34D + Bool(*Rabbit\C[2] < Temp\OldC[2]))
 
    *Rabbit\C[4] = U32V(*Rabbit\C[4] + $D34D34D3 + Bool(*Rabbit\C[3] < Temp\OldC[3]))
    *Rabbit\C[5] = U32V(*Rabbit\C[5] + $34D34D34 + Bool(*Rabbit\C[4] < Temp\OldC[4]))
    *Rabbit\C[6] = U32V(*Rabbit\C[6] + $4D34D34D + Bool(*Rabbit\C[5] < Temp\OldC[5]))
    *Rabbit\C[7] = U32V(*Rabbit\C[7] + $D34D34D3 + Bool(*Rabbit\C[6] < Temp\OldC[6]))
   
    *Rabbit\Carry = Bool(*Rabbit\C[7] < Temp\OldC[7])

    ; Calculate the g-values
   
    For Index = 0 To 7
      Temp\g[Index] = RABBIT_GFunc(*Rabbit\X[Index] + *Rabbit\C[Index])
    Next
   
    ; Calculate new state values
    For Index = 0 To 7
      If Index & 1 = 0
        *Rabbit\X[Index] = U32V(Temp\g[Index] + ROTL32(Temp\g[(Index + 7) & 7],16) + ROTL32(Temp\g[(Index + 6) & 7], 16))
      Else
        *Rabbit\X[Index] = U32V(Temp\g[Index] + ROTL32(Temp\g[(Index + 7) & 7], 8) + Temp\g[(Index + 6) & 7])
      EndIf
    Next
   
  EndProcedure
 
  Procedure RABBIT_KeySetup(*Core.Core, *Key)
   
    ; Temporary Variables
    Protected k0.q, k1.q, k2.q, k3.q, Index.l
   
    ; Generate four subkeys
    k0 = U8TO32_LITTLE(*Key + 0)
    k1 = U8TO32_LITTLE(*Key + 4)
    k2 = U8TO32_LITTLE(*Key + 8)
    k3 = U8TO32_LITTLE(*Key + 12)
   
    ; Generate initial state variables
    *Core\Master\X[0] = k0
    *Core\Master\X[2] = k1
    *Core\Master\X[4] = k2
    *Core\Master\X[6] = k3
    *Core\Master\X[1] = U32V(k3 << 16) | (k2 >> 16)
    *Core\Master\X[3] = U32V(k0 << 16) | (k3 >> 16)
    *Core\Master\X[5] = U32V(k1 << 16) | (k0 >> 16)
    *Core\Master\X[7] = U32V(k2 << 16) | (k1 >> 16)
   
    ; Generate initial counter values
    *Core\Master\C[0] = ROTL32(k2, 16)
    *Core\Master\C[2] = ROTL32(k3, 16)
    *Core\Master\C[4] = ROTL32(k0, 16)
    *Core\Master\C[6] = ROTL32(k1, 16)
   
    *Core\Master\C[1] = (k0 & $FFFF0000) | (k1 & $FFFF)
    *Core\Master\C[3] = (k1 & $FFFF0000) | (k2 & $FFFF)
    *Core\Master\C[5] = (k2 & $FFFF0000) | (k3 & $FFFF)
    *Core\Master\C[7] = (k3 & $FFFF0000) | (k0 & $FFFF)
   
    *Core\Master\Carry = 0

    For Index = 0 To 3
      RABBIT_NextState(*Core\Master)
    Next
   
    ; Modify the counters
    For Index = 0 To 7
      *Core\Master\C[Index] ! *Core\Master\X[(Index + 4) & 7]
    Next
   
    ; Copy master instance to work instance
   
    For Index = 0 To 7
      *Core\Work\X[Index] = *Core\Master\X[Index]
      *Core\Work\C[Index] = *Core\Master\C[Index]
    Next
   
    *Core\Work\Carry = *Core\Master\Carry
   
  EndProcedure
 
  Procedure RABBIT_InitVectorSetup(*Core.Core, *InitVector)
   
    ; Temporary variables
    Protected i0.q, i1.q, i2.q, i3.q, Index.l
   
    ; Generate four subvectors
    i0 = U8TO32_LITTLE(*InitVector + 0)
    i2 = U8TO32_LITTLE(*InitVector + 4)
    i1 = (i0 >> 16) | (i2 & $FFFF0000)
    i3 = (i2 << 16) | (i0 & $0000FFFF)
   
    ; Modify counter values
   
    *Core\Work\C[0] = *Core\Master\C[0] ! i0
    *Core\Work\C[1] = *Core\Master\C[1] ! i1
    *Core\Work\C[2] = *Core\Master\C[2] ! i2
    *Core\Work\C[3] = *Core\Master\C[3] ! i3
   
    *Core\Work\C[4] = *Core\Master\C[4] ! i0
    *Core\Work\C[5] = *Core\Master\C[5] ! i1
    *Core\Work\C[6] = *Core\Master\C[6] ! i2
    *Core\Work\C[7] = *Core\Master\C[7] ! i3
   
    ; Copy state variables
   
    For Index = 0 To 7
      *Core\Work\X[Index] = *Core\Master\X[Index]
    Next
   
    *Core\Work\Carry = *Core\Master\Carry
   
    ; Iterate the system four times
   
    For index = 0 To 3
      RABBIT_NextState(*Core\Work)
    Next
   
  EndProcedure
 
  Procedure RABBIT_Process_Bytes(*Core.Core, *Input, *Output, MsgLen.l)
   
    ; Temporary variables
   
    Protected Buffer.Buffer, Index.l
   
    ; Encrypt/decrypt all full blocks
   
    While MsgLen >= 16
     
      ; Iterate the system
      RABBIT_NextState(*Core\Work)
     
      ; Encrypt/decrypt 16 bytes of data
      PokeL(*Output + 00, PeekL(*Input + 00) ! U32TO32_LITTLE(*Core\Work\X[0] ! (*Core\Work\X[5] >> 16) ! U32V(*Core\Work\X[3] << 16)))
      PokeL(*Output + 04, PeekL(*Input + 04) ! U32TO32_LITTLE(*Core\Work\X[2] ! (*Core\Work\X[7] >> 16) ! U32V(*Core\Work\X[5] << 16)))
      PokeL(*Output + 08, PeekL(*Input + 08) ! U32TO32_LITTLE(*Core\Work\X[4] ! (*Core\Work\X[1] >> 16) ! U32V(*Core\Work\X[7] << 16)))
      PokeL(*Output + 12, PeekL(*Input + 12) ! U32TO32_LITTLE(*Core\Work\X[6] ! (*Core\Work\X[3] >> 16) ! U32V(*Core\Work\X[1] << 16)))
     
      *Input + 16
      *Output + 16
      MsgLen - 16
     
    Wend
   
    ; Encrypt/decrypt remaining data
   
    If MsgLen <> 0
     
      ; Iterate the system
      RABBIT_NextState(*Core\Work)
     
      ; Generate 16 bytes of pseudo-random data */
     
      PokeL(@Buffer + 00, U32TO32_LITTLE(*Core\Work\X[0] ! (*Core\Work\X[5]>>16) ! U32V(*Core\Work\X[3]<<16)))
      PokeL(@Buffer + 04, U32TO32_LITTLE(*Core\Work\X[2] ! (*Core\Work\X[7]>>16) ! U32V(*Core\Work\X[5]<<16)))
      PokeL(@Buffer + 06, U32TO32_LITTLE(*Core\Work\X[4] ! (*Core\Work\X[1]>>16) ! U32V(*Core\Work\X[7]<<16)))
      PokeL(@Buffer + 12, U32TO32_LITTLE(*Core\Work\X[6] ! (*Core\Work\X[3]>>16) ! U32V(*Core\Work\X[1]<<16)))
     
      For Index = 0 To MsgLen - 1
        PokeA(*Output, PeekA(*Input) ! Buffer\Buffer[Index])
        *Output + 1
        *Input + 1
      Next
     
    EndIf
   
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Procedures declaration (Public) <<<<<
 
  Procedure.s Normalizer(Input.s, BitsLength.l)
   
    Bytes.l = BitsLength >> 3
    Output.s = StringFingerprint(Input, #PB_Cipher_MD5)
   
    While StringByteLength(Output) < Bytes
      Output + StringFingerprint(Output, #PB_Cipher_MD5)
    Wend
   
    ProcedureReturn Left(Output, Bytes / SizeOf(Unicode))
  EndProcedure
 
  Procedure Encrypt(*Key, *InitVector, *PlainText, *CipheredText, StringByteLength.l)
   
    RABBIT_KeySetup(Core.Core, *Key)
   
    If *InitVector <> #Null
      RABBIT_InitVectorSetup(Core, *InitVector)
    EndIf
   
    For Index = 0 To 7
      Debug Core\Work\X[Index]
    Next
    Debug ""
    For Index = 0 To 7
      Debug Core\Work\C[Index]
    Next
   
    RABBIT_Process_Bytes(Core, *PlainText, *CipheredText, StringByteLength)
   
  EndProcedure
 
  Procedure Decrypt(*Key, *InitVector, *PlainText, *CipheredText, StringByteLength.l)
   
    RABBIT_KeySetup(Core.Core, *Key)
   
    If *InitVector <> #Null
      RABBIT_InitVectorSetup(Core, *InitVector)
    EndIf
   
    RABBIT_Process_Bytes(Core, *CipheredText, *PlainText, StringByteLength)
   
  EndProcedure
 
EndModule

CompilerIf #PB_Compiler_IsMainFile
 
  UseMD5Fingerprint()

  *Key2 = AllocateMemory(?Key2Stop - ?Key2Start)
  CopyMemory(?Key2start, *Key2, MemorySize(*Key2))
  *InitVector2 = #Null
  *out2 = AllocateMemory(?out2stop - ?out2start)
  CopyMemory(?out2start, *out2, MemorySize(*out2))
  *Ciphered = AllocateMemory(MemorySize(*out2))
  *Deciphered = AllocateMemory(MemorySize(*out2))
 
  RabbitCipher::Encrypt(*Key2, #Null, *out2, *Ciphered, MemorySize(*out2))
  RabbitCipher::Decrypt(*Key2, #Null, *Deciphered, *Ciphered, MemorySize(*out2))
 
  Debug "Test 2: Key setup and encryption/decryption"
 
  If CompareMemory(*out2, *Deciphered, MemorySize(*out2))
    Debug "Success"
  Else
    Debug "Failure"
  EndIf
 
  FreeMemory(*Ciphered)
  FreeMemory(*Deciphered)
 
 
  *Key4 = AllocateMemory(128/8)
  *InitVector4 = AllocateMemory(64/8) 
  *out4 = AllocateMemory(?out4stop - ?out4start)
  CopyMemory(?out4start, *out4, MemorySize(*out4))
  *Ciphered = AllocateMemory(MemorySize(*out4))
  *Deciphered = AllocateMemory(MemorySize(*out4))
 
  RabbitCipher::Encrypt(*Key4, *InitVector4, *out4, *Ciphered, MemorySize(*out4))
  RabbitCipher::Decrypt(*Key4, *InitVector4, *Deciphered, *Ciphered, MemorySize(*out4))
 
  Debug "Test 4: Key setup, iv setup and encryption/decryption"
  If CompareMemory(*out4, *Deciphered, MemorySize(*out4))
    Debug "Success"
  Else
    Debug "Failure"
  EndIf
 
  FreeMemory(*Ciphered)
  FreeMemory(*Deciphered)
 
  *Key5 = AllocateMemory(128/8)
  *InitVector5 = AllocateMemory(?iv5Stop - ?iv5start) 
  CopyMemory(?iv5start, *InitVector5, MemorySize(*InitVector5))
 
  *out5 = AllocateMemory(?out5stop - ?out5start)
  CopyMemory(?out5start, *out5, MemorySize(*out5))
  *Ciphered = AllocateMemory(MemorySize(*out5))
  *Deciphered = AllocateMemory(MemorySize(*out5))
 
  RabbitCipher::Encrypt(*Key5, *InitVector5, *out5, *Ciphered, MemorySize(*out5))
  RabbitCipher::Decrypt(*Key5, *InitVector5, *Deciphered, *Ciphered, MemorySize(*out5))
 
  Debug "Test 5: Key setup, iv setup and encryption/decryption"
  If CompareMemory(*out5, *Deciphered, MemorySize(*out5))
    Debug "Success"
  Else
    Debug "Failure"
  EndIf
 
 
  String.s = "Hello, this is a test for Rabbit Cipher !"
 
  Key.s = RabbitCipher::Normalizer("I'm the key !", 128)
  InitVector.s = RabbitCipher::Normalizer("I'm the InitVector !", 64)
 
  StringMemorySize = StringByteLength(String) + SizeOf(Character)
 
  *CipheredText = AllocateMemory(StringMemorySize)
  *CipheredText2 = AllocateMemory(StringMemorySize)
  *PlainText = AllocateMemory(StringMemorySize)
  *PlainText2 = AllocateMemory(StringMemorySize)
 
  RabbitCipher::Encrypt(@Key, @InitVector, @String, *CipheredText, StringByteLength(String))
  RabbitCipher::Encrypt(@Key, #Null, @String, *CipheredText2, StringByteLength(String))
 
  RabbitCipher::Decrypt(@Key, @InitVector, *PlainText, *CipheredText, StringByteLength(String))
  RabbitCipher::Decrypt(@Key, #Null, *PlainText2, *CipheredText2, StringByteLength(String))
 
  PlainText.s = PeekS(*PlainText)
  PlainText2.s = PeekS(*PlainText2)
 
  Debug "Test Real life : Key setup, IV setup and encryption/decryption"
  If String = PlainText
    Debug "Success"
  Else
    Debug "Failure"
  EndIf
 
  Debug "Test Real life : Key setup and encryption/decryption"
  If String = PlainText2
    Debug "Success"
  Else
    Debug "Failure"
  EndIf
 
  FreeMemory(*CipheredText)
  FreeMemory(*CipheredText2)
  FreeMemory(*PlainText)
  FreeMemory(*PlainText2)
 
 
  DataSection
   
    Key2Start:
    Data.a $C2, $1F, $CF, $38, $81, $CD, $5E, $E8, $62, $8A, $CC, $B0, $A9, $89, $0D, $F8
    Key2Stop:
   
    out2Start:
    Data.a $3D, $02, $E0, $C7, $30, $55, $91, $12, $B4, $73, $B7, $90, $DE, $E0, $18, $DF
    Data.a $CD, $6D, $73, $0C, $E5, $4E, $19, $F0, $C3, $5E, $C4, $79, $0E, $B6, $C7, $4A
    Data.a $9F, $B4, $92, $E1, $B5, $40, $36, $3A, $E3, $83, $C0, $1F, $9F, $A2, $26, $1A
    out2Stop:
   
   
    out4start:
    Data.a $ED, $B7, $05, $67, $37, $5D, $CD, $7C, $D8, $95, $54, $F8, $5E, $27, $A7, $C6
    Data.a $8D, $4A, $DC, $70, $32, $29, $8F, $7B, $D4, $EF, $F5, $04, $AC, $A6, $29, $5F
    Data.a $66, $8F, $BF, $47, $8A, $DB, $2B, $E5, $1E, $6C, $DE, $29, $2B, $82, $DE, $2A
    out4stop:
   
   
    iv5Start:
    Data.s $59, $7E, $26, $C1, $75, $F5, $73, $C3
    iv5Stop:
   
    out5start:
    Data.a $6D, $7D, $01, $22, $92, $CC, $DC, $E0, $E2, $12, $00, $58, $B9, $4E, $CD, $1F
    Data.a $2E, $6F, $93, $ED, $FF, $99, $24, $7B, $01, $25, $21, $D1, $10, $4E, $5F, $A7
    Data.a $A7, $9B, $02, $12, $D0, $BD, $56, $23, $39, $38, $E7, $93, $C3, $12, $C1, $EB
    out5stop:
   
   
  EndDataSection
 
CompilerEndIf

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

_________________
The Stone Age did not end due to a shortage of stones !


Last edited by StarBootics on Thu Nov 05, 2020 10:36 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Rabbit Cipher - Module
PostPosted: Wed Nov 04, 2020 9:25 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3712
Location: Netherlands
Using PureBasic for an algorithm like this is complicated.
The lack of unsigned integers causes a lot of problems.
That's one of the reasons besides speed I prefer to use inline asm.

Your carry detection for example is wrong.
Code:
Bool(*Rabbit\C[0] < Temp\OldC[0]))

For an unsigned 32 bit integer, the point where the new C value is smaller as the old one, is when it crosses 0xFFFFFFFF.
For a signed 32 bit (Long) or signed 64 bit integer (Quad) this isn't the case.

_________________
macOS 10.15 Catalina, Windows 10


Top
 Profile  
Reply with quote  
 Post subject: Re: Rabbit Cipher - Module
PostPosted: Wed Nov 04, 2020 10:17 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Apr 05, 2020 11:28 am
Posts: 518
Location: Pandora
For myself it is a mystery why unsigned is not fully supported.
But you can see, if you browse here something, that this is also comprehensively desired.
It is a barrier, which only causes problems, it makes simple things complicated.
This is my own opinion.

_________________
地球上の平和


Top
 Profile  
Reply with quote  
 Post subject: Re: Rabbit Cipher - Module
PostPosted: Wed Nov 04, 2020 5:48 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jul 07, 2013 11:35 am
Posts: 587
Location: Canada
Hello everyone,

There is the original C code I have used as a reference :
Code:
static void RABBIT_next_state(RABBIT_ctx *p_instance)
{
   /* Temporary variables */
   u32 g[8], c_old[8], i;

   /* Save old counter values */
   for (i=0; i<8; i++)
      c_old[i] = p_instance->c[i];

   /* Calculate new counter values */
   p_instance->c[0] = U32V(p_instance->c[0] + 0x4D34D34D + p_instance->carry);
   p_instance->c[1] = U32V(p_instance->c[1] + 0xD34D34D3 + (p_instance->c[0] < c_old[0]));
   p_instance->c[2] = U32V(p_instance->c[2] + 0x34D34D34 + (p_instance->c[1] < c_old[1]));
   p_instance->c[3] = U32V(p_instance->c[3] + 0x4D34D34D + (p_instance->c[2] < c_old[2]));
   p_instance->c[4] = U32V(p_instance->c[4] + 0xD34D34D3 + (p_instance->c[3] < c_old[3]));
   p_instance->c[5] = U32V(p_instance->c[5] + 0x34D34D34 + (p_instance->c[4] < c_old[4]));
   p_instance->c[6] = U32V(p_instance->c[6] + 0x4D34D34D + (p_instance->c[5] < c_old[5]));
   p_instance->c[7] = U32V(p_instance->c[7] + 0xD34D34D3 + (p_instance->c[6] < c_old[6]));
   p_instance->carry = (p_instance->c[7] < c_old[7]);
   
   /* Calculate the g-values */
   for (i=0;i<8;i++)
      g[i] = RABBIT_g_func(U32V(p_instance->x[i] + p_instance->c[i]));

   /* Calculate new state values */
   p_instance->x[0] = U32V(g[0] + ROTL32(g[7],16) + ROTL32(g[6], 16));
   p_instance->x[1] = U32V(g[1] + ROTL32(g[0], 8) + g[7]);
   p_instance->x[2] = U32V(g[2] + ROTL32(g[1],16) + ROTL32(g[0], 16));
   p_instance->x[3] = U32V(g[3] + ROTL32(g[2], 8) + g[1]);
   p_instance->x[4] = U32V(g[4] + ROTL32(g[3],16) + ROTL32(g[2], 16));
   p_instance->x[5] = U32V(g[5] + ROTL32(g[4], 8) + g[3]);
   p_instance->x[6] = U32V(g[6] + ROTL32(g[5],16) + ROTL32(g[4], 16));
   p_instance->x[7] = U32V(g[7] + ROTL32(g[6], 8) + g[5]);
}


@Wilbert : You are saying that the original C code was wrong as well ?

@Saki : Unsigned integers, unsigned long and unsigned quad are not supported in PureBasic because they have, as Fred said in the past, performance issues. How C and C++ compilers have solve this problem because they have it in these languages ? That's the question that I have for years without any answers.

Best regards
StarBootics

_________________
The Stone Age did not end due to a shortage of stones !


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 47 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye