<?php
/*
WARNING!!! This routine ***ONLY*** works on PHP systems with at least 64-bit integers!!!

This implementation will FAIL on 32-bit integer systems!!!

Below is a syntax-highlighted core features and functionality extract snapshot from the
Simplexity Cypher (Beelzebub variation) -- Proof of Concept Example Implementation web page
located at http://www.SimplexityCypher.com/simplexityexample.php

Copyright (c) 2005-2014-2021+ by William H. Donnelly; All Rights Reserved

(however, you are encouraged to use this code and variation of the algorithm for educational and self-edification purposes)

Simplexity Cypher (Beelzebub variation)
Simplexity:Beelzebub
Simplexity:Key=ASCII: A-Z;Oper=ACSNXLWR;OpTyp=HLNBUWLS;KeyDir=F;DatDir=F;OperSeed=13;OpTypSeed=437;DataOffSeed=35976;DataOff=27;
*/

   define ('CS_META_OPERATOR',           0);
   define ('CS_META_OPERAND_SELECTOR',   1);
   define ('CS_META_OPERAND_VALUE',      2);
   define ('CS_META_DATASET_OFFSET',     3);
   define ('CS_META_PROC_DIR',           4);

   define ('CS_META_PROC_DIR_FORW',   1);
   define ('CS_META_PROC_DIR_BACK',  -1);

   define ('CS_OPER_ADD',             0);
   define ('CS_OPER_COMPLEMENT',      1);
   define ('CS_OPER_SUBTRACT',        2);
   define ('CS_OPER_NEGATE',          3);
   define ('CS_OPER_XOR',             4);
   define ('CS_OPER_ROTATE_LEFT',     5);
   define ('CS_OPER_SWAP',            6);
   define ('CS_OPER_ROTATE_RIGHT',    7);

   define ('CS_OPTYP_UNSIGNED_NYBBLE_HI',      0);
   define ('CS_OPTYP_UNSIGNED_NYBBLE_LO',      1);
   define ('CS_OPTYP_BOTH_UNYBBLES',           2);
   define ('CS_OPTYP_UNSIGNED_BYTE',           3);
   define ('CS_OPTYP_UNSIGNED_WORD',           4);
   define ('CS_OPTYP_SIGNED_WORD',             5);
   define ('CS_OPTYP_UNSIGNED_LONG',           6);
   define ('CS_OPTYP_SIGNED_LONG',             7);

   define ('CS_2_POW_2',                  0x04);     //                                             1000
   define ('CS_2_POW_2_MIN_1',            0x03);     //                                             0111
   define ('CS_2_POW_4',                  0x10);     //                                        0001 0000
   define ('CS_2_POW_4_MIN_1',            0x0f);     //                                        0000 1111
   define ('CS_2_POW_8',                 0x100);     //                                   0001 0000 0000
   define ('CS_2_POW_8_MIN_1',            0xff);     //                                        1111 1111
   define ('CS_2_POW_15',               0x8000);     //                             1000 0000  0000 0000
   define ('CS_2_POW_15_MIN_1',         0x7fff);     //                             0111 1111  1111 1111
   define ('CS_2_POW_16',              0x10000);     //                       0001  0000 0000  0000 0000
   define ('CS_2_POW_16_MIN_1',         0xffff);     //                             1111 1111  1111 1111
   define ('CS_2_POW_24',            0x1000000);     //            0001  0000 0000  0000 0000  0000 0000
   define ('CS_2_POW_31',           0x80000000);     //       1000 0000  0000 0000  0000 0000  0000 0000
   define ('CS_2_POW_31_MIN_1',     0x7fffffff);     //       0111 1111  1111 1111  1111 1111  1111 1111
   define ('CS_2_POW_32',          0x100000000);     // 0001  0000 0000  0000 0000  0000 0000  0000 0000
   define ('CS_2_POW_32_MIN_1',     0xffffffff);     //       1111 1111  1111 1111  1111 1111  1111 1111

   define ('CS_MASK_DIT_HI',              0x0c);     //                                       1100
   define ('CS_MASK_DIT_LO',              0x03);     //                                       0011
   define ('CS_MASK_NYBBLE_HI',           0xf0);     //                                  1111 0000
   define ('CS_MASK_NYBBLE_LO',           0x0f);     //                                  0000 1111
   define ('CS_MASK_BYTE_HI',           0xff00);     //                       1111 1111  0000 0000
   define ('CS_MASK_BYTE_LO',             0xff);     //                       0000 0000  1111 1111
   define ('CS_MASK_WORD_HI',       0xffff0000);     // 1111 1111  1111 1111  0000 0000  0000 0000
   define ('CS_MASK_WORD_LO',           0xffff);     // 0000 0000  0000 0000  1111 1111  1111 1111
   define ('CS_MASK_BYTE1',         0xff000000);     // 1111 1111  0000 0000  0000 0000  0000 0000
   define ('CS_MASK_BYTE2',           0xff0000);     // 0000 0000  1111 1111  0000 0000  0000 0000
   define ('CS_MASK_BYTE3',             0xff00);     // 0000 0000  0000 0000  1111 1111  0000 0000
   define ('CS_MASK_BYTE4',               0xff);     // 0000 0000  0000 0000  0000 0000  1111 1111
   define ('CS_MASK_BYTE',                0xff);     //                                  1111 1111
   define ('CS_MASK_WORD',              0xffff);     //                       1111 1111  1111 1111
   define ('CS_MASK_LONG',          0xffffffff);     // 1111 1111  1111 1111  1111 1111  1111 1111

   define ('CS_MASK_BITSHIFT_NYBBLE',     0x03);     // 3
   define ('CS_MASK_BITSHIFT_BYTE',       0x07);     // 7
   define ('CS_MASK_BITSHIFT_WORD',       0x0f);     // 15
   define ('CS_MASK_BITSHIFT_LONG',       0x1f);     // 31


   define ('CS_KEY_CHARS', ' ABCDEFGHIJKLMNOPQRSTUVWXYZ');

// initialization

   $bEncrypt = FALSE;      // set for encryption (html form button click)
   $bDecrypt = FALSE;      // set for decryption (html form button click)

// get the cypher key from raw $cypherkey

         $sCypherKey = $cypherkey;
         $nCypherKey = strlen ($sCypherKey);
         $sKey = '';

         for ($nChar = 0;  $nChar < $nCypherKey;  ++$nChar) {

            $sChar = $sCypherKey[$nChar];

            if (($sChar >= 'A'  and  $sChar <= 'Z')  or  $sChar === ' ')
               $sKey .= $sChar;

         } // for

         $sKey = trim ($sKey);   // in case removal of invalid key characters causes leading or trailing SPACE characters
         $nKeyLen = strlen ($sKey);

// get the dataset from a (file) string and put into the working array $aData

         $sContents = '...';     // from file load
         $nContentLen = strlen ($sContents);

         $aData = array();
         $nDataLen = 0;

         for ($nIdx = 0;  $nIdx < $nContentLen;  ++$nIdx) {

            $aData[$nDataLen++] = ord ($sContents[$nIdx]);

         } // for

// create the Operations Processing List from the cypher key

         $aOpsProcList = array();
         $nOpsProcListCnt = 0;

         $nOperatorSeed = 13;             // arbitrarily chosen initial seed; hardcoded for this implementation (Byte)
         $nOperandSeed = 437;             // arbitrarily chosen initial seed; hardcoded for this implementation (Byte)
         $nDatasetOffsetSeed = 35976;     // arbitrarily chosen initial seed; hardcoded for this implementation (Unsigned Long)

         $nDatasetOffset = 27;            // arbitrarily chosen initial dataset offset; hardcoded for this implementation (Unsigned Long)
         $nOpValueSeed = 0;

         for ($nKeyCnt = 0;  $nKeyCnt < $nKeyLen;  ++$nKeyCnt) {

            $nKeyOperator = strpos (CS_KEY_CHARS, $sKey[$nKeyCnt]) + $nOperatorSeed;
            $nOperatorSeed = $nKeyOperator & CS_MASK_BYTE;
            $nKeyOperator = $nKeyOperator % 8;

            $nKeyOperand = strpos (CS_KEY_CHARS, $sKey[($nKeyCnt + 1) % $nKeyLen]) + $nOperandSeed;
            $nOperandSeed = $nKeyOperand & CS_MASK_BYTE;
            $nKeyOperand = $nKeyOperand % 8;

            $nKeyDataByte1 = (ord ($sKey[($nKeyCnt + 2) % $nKeyLen]) + $nOpValueSeed) & CS_MASK_BYTE;
            $nOpValueSeed = $nKeyDataByte1;

            $nKeyDataByte2 = (ord ($sKey[($nKeyCnt + 3) % $nKeyLen]) + $nOpValueSeed) & CS_MASK_BYTE;
            $nOpValueSeed = $nKeyDataByte2;

            $nKeyDataByte3 = (ord ($sKey[($nKeyCnt + 4) % $nKeyLen]) + $nOpValueSeed) & CS_MASK_BYTE;
            $nOpValueSeed = $nKeyDataByte3;

            $nKeyDataByte4 = (ord ($sKey[($nKeyCnt + 5) % $nKeyLen]) + $nOpValueSeed) & CS_MASK_BYTE;
            $nOpValueSeed = $nKeyDataByte4;

            $nOpValue = ($nKeyDataByte1 << 24) + ($nKeyDataByte2 << 16) + ($nKeyDataByte3 << 8) + $nKeyDataByte4;    // MSB

            $aOpsProcList[$nOpsProcListCnt][CS_META_OPERATOR]           = $nKeyOperator;           // Operator to execute (initial) = 0 - 7
            $aOpsProcList[$nOpsProcListCnt][CS_META_OPERAND_SELECTOR]   = $nKeyOperand;            // Operand Selector (initial) = 0 - 7
            $aOpsProcList[$nOpsProcListCnt][CS_META_OPERAND_VALUE]      = $nOpValue;               // Unsigned Long value for two-operand operations
            $aOpsProcList[$nOpsProcListCnt][CS_META_DATASET_OFFSET]     = $nDatasetOffset;         // where to start processing inside dataset
            $aOpsProcList[$nOpsProcListCnt][CS_META_PROC_DIR]           = CS_META_PROC_DIR_FORW;   // hardcoded forward direction

            $nDatasetOffset = ($nDatasetOffset + $nDatasetOffsetSeed) & CS_MASK_LONG;
            $nDatasetOffsetSeed = $nDatasetOffset + 1;     // prevent from zeroing
            $nDatasetOffset = $nDatasetOffset % $nDataLen;

            ++$nOpsProcListCnt;

         } // for

// process the dataset (encrypt or decrypt)

         if ($bEncrypt) {
            $nOPLIdx = 0;                       // start at the beginning of the key list
            $nOPLDir = 1;                       // direction = forward
         }

         if ($bDecrypt) {
            $nOPLIdx = $nOpsProcListCnt - 1;    // start at the end of the key list
            $nOPLDir = -1;                      // reverse the direction = backward
         }

         do {     // process the Operations Processing List

            $nKeyOperator     = $aOpsProcList[$nOPLIdx][CS_META_OPERATOR];
            $nKeyOperand      = $aOpsProcList[$nOPLIdx][CS_META_OPERAND_SELECTOR];
            $nOpValue         = $aOpsProcList[$nOPLIdx][CS_META_OPERAND_VALUE];
            $nDatasetOffset   = $aOpsProcList[$nOPLIdx][CS_META_DATASET_OFFSET];
            $nDirection       = $aOpsProcList[$nOPLIdx][CS_META_PROC_DIR];

            $nKeyOperatorStart = $nKeyOperator;

            $nDataIdx = $nDatasetOffset % $nDataLen;
            $nDataCnt = $nDataLen;
            $nDatasetOffset = $nDatasetOffset % $nDataLen;     // in case offset is larger than data length for later comparison

            do {     // process the dataset -- one full pass

               $nCryptOperand = $nKeyOperand;

               if ($nCryptOperand >= CS_OPTYP_UNSIGNED_LONG  and  $nDataCnt < 4) {
                  if ($nDataCnt >= 2)
                     $nCryptOperand = CS_OPTYP_UNSIGNED_WORD;

                  else
                     $nCryptOperand = CS_OPTYP_UNSIGNED_BYTE;

               } else {
                  if ($nCryptOperand >= CS_OPTYP_UNSIGNED_WORD  and  $nDataCnt < 2)
                     $nCryptOperand = CS_OPTYP_UNSIGNED_BYTE;
               }


               switch ($nCryptOperand) {     // get datasize-converted Operand and Data Values

               case CS_OPTYP_UNSIGNED_NYBBLE_HI:   // Unsigned Nybble Hi      (4 bits)    ; H

                  $nDataSize = 1;
                  $nBitShiftMask = CS_MASK_BITSHIFT_NYBBLE;
                  $nDataValueMask = CS_MASK_NYBBLE_LO;

                  $nOperandValue = ($nOpValue & CS_MASK_NYBBLE_HI) >> 4;
                  $nOperandValueUns = $nOperandValue;

                  $nOperandData = ($aData[$nDataIdx] & CS_MASK_NYBBLE_HI) >> 4;
                  $nOperandDataUns = $nOperandData;

                  $nOpDataValue = $aData[$nDataIdx];

                  break;

               case CS_OPTYP_UNSIGNED_NYBBLE_LO:   // Unsigned Nybble Lo      (4 bits)    ; L

                  $nDataSize = 1;
                  $nBitShiftMask = CS_MASK_BITSHIFT_NYBBLE;
                  $nDataValueMask = CS_MASK_NYBBLE_LO;

                  $nOperandValue = $nOpValue & CS_MASK_NYBBLE_LO;
                  $nOperandValueUns = $nOperandValue;

                  $nOperandData = $aData[$nDataIdx] & CS_MASK_NYBBLE_LO;
                  $nOperandDataUns = $nOperandData;

                  $nOpDataValue = $aData[$nDataIdx];

                  break;

               case CS_OPTYP_BOTH_UNYBBLES:        // Both Unsigned Nybbles   (4 bits)    ; N

                  $nDataSize = 1;
                  $nBitShiftMask = CS_MASK_BITSHIFT_NYBBLE;
                  $nDataValueMask = CS_MASK_NYBBLE_LO;

                  $nOperandValue = ($nOpValue & CS_MASK_NYBBLE_HI) >> 4;
                  $nOperandValueUns = $nOperandValue;

                  $nOperandValue2 = $nOpValue & CS_MASK_NYBBLE_LO;
                  $nOperandValueUns2 = $nOperandValue2;

                  $nOperandData = ($aData[$nDataIdx] & CS_MASK_NYBBLE_HI) >> 4;
                  $nOperandDataUns = $nOperandData;

                  $nOperandData2 = $aData[$nDataIdx] & CS_MASK_NYBBLE_LO;
                  $nOperandDataUns2 = $nOperandData2;

                  break;

               case CS_OPTYP_UNSIGNED_BYTE:        // Unsigned Byte           (8 bits)    ; B

                  $nDataSize = 1;
                  $nBitShiftMask = CS_MASK_BITSHIFT_BYTE;
                  $nDataValueMask = CS_MASK_BYTE;

                  $nOperandValue = $nOpValue & CS_MASK_BYTE;
                  $nOperandValueUns = $nOperandValue;

                  $nOperandData = $aData[$nDataIdx];
                  $nOperandDataUns = $nOperandData;

                  break;

               case CS_OPTYP_UNSIGNED_WORD:        // Unsigned Word           (16 bits)   ; U

                  $nDataSize = 2;
                  $nBitShiftMask = CS_MASK_BITSHIFT_WORD;
                  $nDataValueMask = CS_MASK_WORD;

                  $nOperandValue = $nOpValue & CS_MASK_WORD;
                  $nOperandValueUns = $nOperandValue;

                  $nDataByte1 = $aData[$nDataIdx];
                  $nDataByte2 = $aData[($nDataIdx + $nDirection) % $nDataLen];
                  $nOperandData = ($nDataByte1 << 8) + $nDataByte2;  // MSB
                  $nOperandDataUns = $nOperandData;

                  break;

               case CS_OPTYP_SIGNED_WORD:          // Signed Word             (16 bits)   ; W

                  $nDataSize = 2;
                  $nBitShiftMask = CS_MASK_BITSHIFT_WORD;
                  $nDataValueMask = CS_MASK_WORD;

                  $nOperandValue = $nOpValue & CS_MASK_WORD;
                  $nOperandValueUns = $nOperandValue;
                  if ($nOperandValue >= CS_2_POW_15)
                     $nOperandValue = $nOperandValue - CS_2_POW_16;

                  $nDataByte1 = $aData[$nDataIdx];
                  $nDataByte2 = $aData[($nDataIdx + $nDirection) % $nDataLen];
                  $nOperandData = ($nDataByte1 << 8) + $nDataByte2;  // MSB
                  $nOperandDataUns = $nOperandData;
                  if ($nOperandData >= CS_2_POW_15)
                     $nOperandData = $nOperandData - CS_2_POW_16;

                  break;

               case CS_OPTYP_UNSIGNED_LONG:        // Unsigned Long           (32 bits)   ; L

                  $nDataSize = 4;
                  $nBitShiftMask = CS_MASK_BITSHIFT_LONG;
                  $nDataValueMask = CS_MASK_LONG;

                  $nOperandValue = $nOpValue;
                  $nOperandValueUns = $nOperandValue;

                  $nDataByte1 = $aData[$nDataIdx];
                  $nDataByte2 = $aData[($nDataIdx + $nDirection) % $nDataLen];
                  $nDataByte3 = $aData[($nDataIdx + $nDirection + $nDirection) % $nDataLen];
                  $nDataByte4 = $aData[($nDataIdx + $nDirection + $nDirection + $nDirection) % $nDataLen];
                  $nOperandData = ($nDataByte1 << 24) + ($nDataByte2 << 16) + ($nDataByte3 << 8) + $nDataByte4;  // MSB
                  $nOperandDataUns = $nOperandData;

                  break;

               case CS_OPTYP_SIGNED_LONG:          // Signed Long             (32 bits)   ; S

                  $nDataSize = 4;
                  $nBitShiftMask = CS_MASK_BITSHIFT_LONG;
                  $nDataValueMask = CS_MASK_LONG;

                  $nOperandValue = $nOpValue;
                  $nOperandValueUns = $nOperandValue;
                  if ($nOperandValue >= CS_2_POW_31)
                     $nOperandValue = $nOperandValue - CS_2_POW_32;

                  $nDataByte1 = $aData[$nDataIdx];
                  $nDataByte2 = $aData[($nDataIdx + $nDirection) % $nDataLen];
                  $nDataByte3 = $aData[($nDataIdx + $nDirection + $nDirection) % $nDataLen];
                  $nDataByte4 = $aData[($nDataIdx + $nDirection + $nDirection + $nDirection) % $nDataLen];
                  $nOperandData = ($nDataByte1 << 24) + ($nDataByte2 << 16) + ($nDataByte3 << 8) + $nDataByte4;  // MSB
                  $nOperandDataUns = $nOperandData;
                  if ($nOperandData >= CS_2_POW_31)
                     $nOperandData = $nOperandData - CS_2_POW_32;

                  break;

               } // switch $nCryptOperand -- get datasize-converted Operand and Data Values


               $nCryptOperator = $nKeyOperator;

               if ($bDecrypt) {     // perform the opposite operation for decryption
                  switch ($nKeyOperator) {

                  case CS_OPER_ADD:                // next key value  (1, 2, 3, or 4 bytes after OpTyp; key wrap-around)      ; A

                     $nCryptOperator = CS_OPER_SUBTRACT;

                     break;

                  case CS_OPER_COMPLEMENT:         // ones' complement (bitwise NOT; bit invert)                              ; C

                     break;

                  case CS_OPER_SUBTRACT:           // next key value  (1, 2, 3, or 4 bytes after OpTyp; key wrap-around)      ; S

                     $nCryptOperator = CS_OPER_ADD;

                     break;

                  case CS_OPER_NEGATE:             // two's complement (arithmetic negative)                                  ; N

                     break;

                  case CS_OPER_XOR:                // next key value  (1, 2, 3, or 4 bytes after OpTyp; key wrap-around)      ; X

                     break;

                  case CS_OPER_ROTATE_LEFT:        // next key value after OpTyp LSBs (2=1-3, 3=1-7, 4=1-15, 8=1-31; 0 = 1)   ; L

                     $nCryptOperator = CS_OPER_ROTATE_RIGHT;

                     break;

                  case CS_OPER_SWAP:               // (Dits, Nybbles, Bytes, Words)                                           ; W

                     break;

                  case CS_OPER_ROTATE_RIGHT:       // next key value after OpTyp LSBs (2=1-3, 3=1-7, 4=1-15, 8=1-31; 0 = 1)   ; R

                     $nCryptOperator = CS_OPER_ROTATE_LEFT;

                     break;

                  } // switch $nKeyOperator -- perform the opposite operation for decryption
               } // if decrypting


               switch ($nCryptOperator) {    // Operator execution

               case CS_OPER_ADD:             // next key value  (1, 2, 3, or 4 bytes after OpTyp; key wrap-around)      ; A

                  $nResult = $nOperandData + $nOperandValue;

                  if ($nCryptOperand == CS_OPTYP_BOTH_UNYBBLES)
                     $nResult2 = $nOperandData2 + $nOperandValue2;

                  break;

               case CS_OPER_COMPLEMENT:      // ones' complement (bitwise NOT; bit invert)                              ; C

                  $nResult = ~$nOperandDataUns;

                  if ($nCryptOperand == CS_OPTYP_BOTH_UNYBBLES)
                     $nResult2 = ~$nOperandDataUns2;

                  break;

               case CS_OPER_SUBTRACT:        // next key value  (1, 2, 3, or 4 bytes after OpTyp; key wrap-around)      ; S

                  $nResult = $nOperandData - $nOperandValue;

                  if ($nCryptOperand == CS_OPTYP_BOTH_UNYBBLES)
                     $nResult2 = $nOperandData2 - $nOperandValue2;

                  break;

               case CS_OPER_NEGATE:          // two's complement (arithmetic negative)                                  ; N

                  $nResult = -$nOperandData;

                  if ($nCryptOperand == CS_OPTYP_BOTH_UNYBBLES)
                     $nResult2 = -$nOperandData2;

                  break;

               case CS_OPER_XOR:             // next key value  (1, 2, 3, or 4 bytes after OpTyp; key wrap-around)      ; X

                  $nResult = $nOperandDataUns ^ $nOperandValueUns;

                  if ($nCryptOperand == CS_OPTYP_BOTH_UNYBBLES)
                     $nResult2 = $nOperandDataUns2 ^ $nOperandValueUns2;

                  break;

               case CS_OPER_ROTATE_LEFT:     // next key value after OpTyp LSBs (2=1-3, 3=1-7, 4=1-15, 8=1-31; 0 = 1)   ; L

                  // NOTE: PHP's right-shift bitwise operator, >>, is arithmetic, and therefore copies the sign (MSB) -- see warning at above-top

                  $nBitsToShift = ($nOperandValueUns & $nBitShiftMask);
                  $nBitsToShift = ($nBitsToShift == 0) ? 1 : $nBitsToShift;      // 0 = 1
                  $nDataMask = $nDataValueMask >> $nBitsToShift;

                  $nUpperValue = ($nOperandDataUns & $nDataMask) << $nBitsToShift;
                  $nLowerValue = $nOperandDataUns >> ($nBitShiftMask - $nBitsToShift + 1);
                  $nResult = $nUpperValue | $nLowerValue;

                  if ($nCryptOperand == CS_OPTYP_BOTH_UNYBBLES) {
                     $nUpperValue = ($nOperandDataUns2 & $nDataMask) << $nBitsToShift;
                     $nLowerValue = $nOperandDataUns2 >> ($nBitShiftMask - $nBitsToShift + 1);
                     $nResult2 = $nUpperValue | $nLowerValue;
                  }

                  break;

               case CS_OPER_SWAP:            // (Dits, Nybbles, Bytes, Words)                                           ; W

                  switch ($nCryptOperand) {     // Operand-sized swapping

                  case CS_OPTYP_UNSIGNED_NYBBLE_HI:   // Unsigned Nybble Hi      (4 bits)    ; H
                  case CS_OPTYP_UNSIGNED_NYBBLE_LO:   // Unsigned Nybble Lo      (4 bits)    ; L
                  case CS_OPTYP_BOTH_UNYBBLES:        // Both Unsigned Nybbles   (4 bits)    ; N

                     $nDitHi = ($nOperandDataUns & CS_MASK_DIT_HI) >> 2;
                     $nDitLo = $nOperandDataUns & CS_MASK_DIT_LO;
                     $nResult = ($nDitLo << 2) + $nDitHi;

                     if ($nCryptOperand == CS_OPTYP_BOTH_UNYBBLES) {
                        $nDitHi = ($nOperandDataUns2 & CS_MASK_DIT_HI) >> 2;
                        $nDitLo = $nOperandDataUns2 & CS_MASK_DIT_LO;
                        $nResult2 = ($nDitLo << 2) + $nDitHi;
                     }

                     break;

                  case CS_OPTYP_UNSIGNED_BYTE:        // Unsigned Byte           (8 bits)    ; B

                     $nNybbleHi = ($nOperandDataUns & CS_MASK_NYBBLE_HI) >> 4;
                     $nNybbleLo = $nOperandDataUns & CS_MASK_NYBBLE_LO;
                     $nResult = ($nNybbleLo << 4) + $nNybbleHi;

                     break;

                  case CS_OPTYP_UNSIGNED_WORD:        // Unsigned Word           (16 bits)   ; U
                  case CS_OPTYP_SIGNED_WORD:          // Signed Word             (16 bits)   ; W

                     $nByteHi = ($nOperandDataUns & CS_MASK_BYTE_HI) >> 8;
                     $nByteLo = $nOperandDataUns & CS_MASK_BYTE_LO;
                     $nResult = ($nByteLo << 8) + $nByteHi;

                     break;

                  case CS_OPTYP_UNSIGNED_LONG:        // Unsigned Long           (32 bits)   ; L
                  case CS_OPTYP_SIGNED_LONG:          // Signed Long             (32 bits)   ; S

                     $nWordHi = ($nOperandDataUns & CS_MASK_WORD_HI) >> 16;
                     $nWordLo = $nOperandDataUns & CS_MASK_WORD_LO;
                     $nResult = ($nWordLo << 16) + $nWordHi;

                     break;

                  } // switch $nCryptOperand -- Operand-sized swapping

                  break;

               case CS_OPER_ROTATE_RIGHT:    // next key value after OpTyp LSBs (2=1-3, 3=1-7, 4=1-15, 8=1-31; 0 = 1)   ; R

                  // NOTE: PHP's right-shift bitwise operator, >>, is arithmetic, and therefore copies the sign (MSB) -- see warning at above-top

                  $nBitsToShift = ($nOperandValueUns & $nBitShiftMask);
                  $nBitsToShift = ($nBitsToShift == 0) ? 1 : $nBitsToShift;      // 0 = 1
                  $nDataMask = $nDataValueMask >> ($nBitShiftMask - $nBitsToShift + 1);

                  $nUpperValue = ($nOperandDataUns & $nDataMask) << ($nBitShiftMask - $nBitsToShift + 1);
                  $nLowerValue = ($nOperandDataUns >> $nBitsToShift) & ($nDataValueMask  >> $nBitsToShift);
                  $nResult = $nUpperValue | $nLowerValue;

                  if ($nCryptOperand == CS_OPTYP_BOTH_UNYBBLES) {
                     $nUpperValue = ($nOperandDataUns2 & $nDataMask) << ($nBitShiftMask - $nBitsToShift + 1);
                     $nLowerValue = $nOperandDataUns2 >> $nBitsToShift;
                     $nResult2 = $nUpperValue | $nLowerValue;
                  }

                  break;

               } // switch $nCryptOperator -- Operator execution


               switch ($nCryptOperand) {     // store new result

               case CS_OPTYP_UNSIGNED_NYBBLE_HI:   // Unsigned Nybble Hi      (4 bits)    ; H

                  if ($nResult < 0)
                     $nResult += CS_2_POW_4;
                  $nResult = ($nResult & CS_MASK_NYBBLE_LO) << 4;

                  $aData[$nDataIdx] = ($nOpDataValue & CS_MASK_NYBBLE_LO) + $nResult;

                  break;

               case CS_OPTYP_UNSIGNED_NYBBLE_LO:   // Unsigned Nybble Lo      (4 bits)    ; L

                  if ($nResult < 0)
                     $nResult += CS_2_POW_4;
                  $nResult = $nResult & CS_MASK_NYBBLE_LO;

                  $aData[$nDataIdx] = ($nOpDataValue & CS_MASK_NYBBLE_HI) + $nResult;

                  break;

               case CS_OPTYP_BOTH_UNYBBLES:        // Both Unsigned Nybbles   (4 bits)    ; N

                  if ($nResult < 0)
                     $nResult += CS_2_POW_4;
                  $nResult = ($nResult & CS_MASK_NYBBLE_LO) << 4;

                  if ($nResult2 < 0)
                     $nResult2 += CS_2_POW_4;
                  $nResult2 = $nResult2 & CS_MASK_NYBBLE_LO;

                  $aData[$nDataIdx] = $nResult + $nResult2;

                  break;

               case CS_OPTYP_UNSIGNED_BYTE:        // Unsigned Byte           (8 bits)    ; B

                  if ($nResult < 0)
                     $nResult += CS_2_POW_8;
                  $nResult = $nResult & CS_MASK_BYTE;

                  $aData[$nDataIdx] = $nResult;

                  break;

               case CS_OPTYP_UNSIGNED_WORD:        // Unsigned Word           (16 bits)   ; U
               case CS_OPTYP_SIGNED_WORD:          // Signed Word             (16 bits)   ; W

                  if ($nResult < 0)
                     $nResult += CS_2_POW_16;
                  $nResult = $nResult & CS_MASK_WORD;

                  $aData[$nDataIdx] = $nResult >> 8;
                  $aData[($nDataIdx + $nDirection) % $nDataLen] = $nResult & CS_MASK_BYTE;

                  break;

               case CS_OPTYP_UNSIGNED_LONG:        // Unsigned Long           (32 bits)   ; L
               case CS_OPTYP_SIGNED_LONG:          // Signed Long             (32 bits)   ; S

                  if ($nResult < 0)
                     $nResult = $nResult + CS_2_POW_32;
                  $nResult = $nResult & CS_MASK_LONG;

                  $nDataByte1 = ($nResult & CS_MASK_BYTE1) >> 24;
                  $nDataByte2 = (($nResult & CS_MASK_BYTE2) >> 16) & CS_MASK_BYTE;
                  $nDataByte3 = (($nResult & CS_MASK_BYTE3) >> 8) & CS_MASK_BYTE;
                  $nDataByte4 = $nResult & CS_MASK_BYTE4;

                  $aData[$nDataIdx] = $nDataByte1;
                  $aData[($nDataIdx + $nDirection) % $nDataLen] = $nDataByte2;
                  $aData[($nDataIdx + $nDirection + $nDirection) % $nDataLen] = $nDataByte3;
                  $aData[($nDataIdx + $nDirection + $nDirection + $nDirection) % $nDataLen] = $nDataByte4;

                  break;

               } // switch $nCryptOperand -- // store new result


               $nDataIdx = ($nDataIdx + ($nDirection * $nDataSize)) % $nDataLen;
               $nDataCnt -= $nDataSize;

               $nKeyOperator = ($nKeyOperator + 1) % 8;
               $nKeyOperand = ($nKeyOperand + 1) % 8;

               if ($nKeyOperator == $nKeyOperatorStart)
                  $nKeyOperand = ($nKeyOperand + 1) % 8;    // ensures all Operators with all Operand sizes

            } while ($nDataIdx != $nDatasetOffset);      // process the dataset -- one full pass

            $nOPLIdx += $nOPLDir;

         } while ($nOPLIdx >= 0  and  $nOPLIdx < $nOpsProcListCnt);     // process the Operations Processing List

// output the encrypted or decrypted data (into a string for a file save)

            $sOutData = '';

            for ($nIdx = 0;  $nIdx < $nDataLen;  ++$nIdx) {

               $sOutData .= chr ($aData[$nIdx]);

            } // for

// end
?>

Copyright © 2005–2014–2021+ by William H. Donnelly — All Rights Reserved.
All worldwide intellectual property rights are hereby retained in full.