|
|
@@ -0,0 +1,261 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Diagnostics;
|
|
|
+using System.Linq;
|
|
|
+using System.Text;
|
|
|
+using System.Threading.Tasks;
|
|
|
+
|
|
|
+namespace OTSModelSharp
|
|
|
+{
|
|
|
+ class CARACrypt
|
|
|
+ {
|
|
|
+ string m_csKey;
|
|
|
+ int m_LFSR_A;
|
|
|
+ int m_LFSR_B;
|
|
|
+ uint m_LFSR_C;
|
|
|
+ int m_Mask_A;
|
|
|
+ int m_Rot1_A;
|
|
|
+ int m_Mask_B;
|
|
|
+ int m_Rot1_B;
|
|
|
+ int m_Rot0_B;
|
|
|
+ int m_Rot0_A;
|
|
|
+ int m_Mask_C;
|
|
|
+ int m_Rot1_C;
|
|
|
+ int m_Rot0_C;
|
|
|
+ public CARACrypt()
|
|
|
+ {
|
|
|
+ int m_LFSR_A = 0x13579BDF;
|
|
|
+ int m_LFSR_B = 0x2468ACE0;
|
|
|
+ uint m_LFSR_C = 0xFDB97531;
|
|
|
+
|
|
|
+ uint m_Mask_A = 0x80000062;
|
|
|
+ int m_Mask_B = 0x40000020;
|
|
|
+ int m_Mask_C = 0x10000002;
|
|
|
+
|
|
|
+ int m_Rot0_A = 0x7FFFFFFF;
|
|
|
+ int m_Rot0_B = 0x3FFFFFFF;
|
|
|
+ int m_Rot0_C = 0x0FFFFFFF;
|
|
|
+ uint m_Rot1_A = 0x80000000;
|
|
|
+ uint m_Rot1_B = 0xC0000000;
|
|
|
+ uint m_Rot1_C = 0xF0000000;
|
|
|
+ int m_csKey = 0;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public void SetKey(string csKey)
|
|
|
+ {
|
|
|
+ string csSeed;
|
|
|
+
|
|
|
+ //m_csKey = csKey;
|
|
|
+
|
|
|
+ int iLen = Convert.ToInt32(csKey);
|
|
|
+ m_csKey = new Char[iLen + 1].ToString();
|
|
|
+ String.Format(m_csKey, iLen + 1, csKey, iLen);
|
|
|
+ m_csKey = "\n";
|
|
|
+
|
|
|
+
|
|
|
+ if (Convert.ToInt32(m_csKey) == 0)
|
|
|
+ {
|
|
|
+ //Put some really outrageous characters in seed just in case.
|
|
|
+ csSeed = "\x43\xC8\x21\xD3\xF4\xB3\x10\x27\x09\xAA\x18\x56";
|
|
|
+
|
|
|
+ //TO DO: Add Message to Event Log and/or window when there is one.
|
|
|
+ // AfxMessageBox("WARNING: Missing Pass Phrase. Default in effect!");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ csSeed = m_csKey;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Make sure seed is at least 12 bytes long .
|
|
|
+
|
|
|
+ int nIdx = 0;
|
|
|
+ //int length = strlen(m_csKey);
|
|
|
+
|
|
|
+ for (nIdx = 0; Convert.ToInt32(m_csKey) < 12; nIdx++)
|
|
|
+ {
|
|
|
+ csSeed += csSeed[nIdx];
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // LFSR A, B, and C get the first, second, and
|
|
|
+ // third four bytes of the seed, respectively.
|
|
|
+
|
|
|
+ for (nIdx = 0; nIdx < 4; nIdx++)
|
|
|
+ {
|
|
|
+ m_LFSR_A = ((m_LFSR_A <<= 8) | ((int)csSeed[nIdx + 0]));
|
|
|
+
|
|
|
+ m_LFSR_B = ((m_LFSR_B <<= 8) | ((int)csSeed[nIdx + 4]));
|
|
|
+
|
|
|
+ m_LFSR_C = ((m_LFSR_C <<= 8) | ((uint)csSeed[nIdx + 8]));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // If any LFSR contains 0x00000000, load a
|
|
|
+ // non-zero default value instead. There is
|
|
|
+ // no particular "good" value. The ones here
|
|
|
+ // were selected to be distinctive during
|
|
|
+ // testing and debugging.
|
|
|
+
|
|
|
+ if (0x00000000 == m_LFSR_A)
|
|
|
+ m_LFSR_A = 0x13579BDF;
|
|
|
+
|
|
|
+ if (0x00000000 == m_LFSR_B)
|
|
|
+ m_LFSR_B = 0x2468ACE0;
|
|
|
+
|
|
|
+ if (0x00000000 == m_LFSR_C)
|
|
|
+ m_LFSR_C = 0xFDB97531;
|
|
|
+
|
|
|
+ return;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+ public void GetKey(string csKey)
|
|
|
+ {
|
|
|
+ csKey = m_csKey;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void TransformChar(byte cTarget)
|
|
|
+ {
|
|
|
+ int Counter = 0;
|
|
|
+ byte Crypto = new byte();
|
|
|
+ int Out_B = (m_LFSR_B & 0x00000001);
|
|
|
+ uint Out_C = (m_LFSR_C & 0x00000001);
|
|
|
+
|
|
|
+ // Cycle the LFSRs eight times to get eight
|
|
|
+ // pseudo-random bits. Assemble these into
|
|
|
+ // a single random character (Crypto).
|
|
|
+
|
|
|
+ for (Counter = 0; Counter < 8; Counter++)
|
|
|
+ {
|
|
|
+ if (m_LFSR_A == 0x00000001)
|
|
|
+ {
|
|
|
+ // The least-significant bit of LFSR
|
|
|
+ // A is "1". XOR LFSR A with its
|
|
|
+ // feedback mask.
|
|
|
+
|
|
|
+ m_LFSR_A = (((m_LFSR_A ^ m_Mask_A) >> 1) | m_Rot1_A);
|
|
|
+
|
|
|
+ // Clock shift register B once.
|
|
|
+ if (m_LFSR_B == 0x00000001)
|
|
|
+ {
|
|
|
+ // The LSB of LFSR B is "1". XOR
|
|
|
+ // LFSR B with its feedback mask.
|
|
|
+
|
|
|
+ m_LFSR_B = (((m_LFSR_B ^ m_Mask_B) >> 1) | m_Rot1_B);
|
|
|
+
|
|
|
+ Out_B = 0x00000001;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // The LSB of LFSR B is "0". Rotate
|
|
|
+ // the LFSR contents once.
|
|
|
+
|
|
|
+ m_LFSR_B = ((m_LFSR_B >> 1) & m_Rot0_B);
|
|
|
+
|
|
|
+ Out_B = 0x00000000;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // The LSB of LFSR A is "0".
|
|
|
+ // Rotate the LFSR contents once.
|
|
|
+
|
|
|
+ m_LFSR_A = ((m_LFSR_A >> 1) & m_Rot0_A);
|
|
|
+
|
|
|
+
|
|
|
+ // Clock shift register C once.
|
|
|
+
|
|
|
+ if (m_LFSR_C == 0x00000001)
|
|
|
+ {
|
|
|
+ // The LSB of LFSR C is "1".
|
|
|
+ // XOR LFSR C with its feedback mask.
|
|
|
+
|
|
|
+ m_LFSR_C = (uint)(((m_LFSR_C ^ m_Mask_C) >> 1) | m_Rot1_C);
|
|
|
+ Out_C = 0x00000001;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // The LSB of LFSR C is "0". Rotate
|
|
|
+ // the LFSR contents once.
|
|
|
+
|
|
|
+ m_LFSR_C = (uint) m_Rot0_C;
|
|
|
+
|
|
|
+ Out_C = 0x00000000;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // XOR the output from LFSRs B and C and
|
|
|
+ // rotate it into the right bit of Crypto.
|
|
|
+
|
|
|
+ //The follwing conversion warning is unecessary here as
|
|
|
+ //'loss of data' is a side effect and harmless.
|
|
|
+
|
|
|
+ Crypto = Convert.ToByte(Out_B);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // XOR the resulting character with the
|
|
|
+ // input character to encrypt/decrypt it.
|
|
|
+
|
|
|
+ //The follwing conversion warning not necessary here either.
|
|
|
+ //The 'loss of data', so to speak is a side effect and harmless.
|
|
|
+
|
|
|
+ cTarget = Crypto;
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void TransformString(string csKey, string csTarget)
|
|
|
+ {
|
|
|
+
|
|
|
+ // Reset the shift registers.
|
|
|
+
|
|
|
+ SetKey(csKey);
|
|
|
+
|
|
|
+ // Transform each character in the string.
|
|
|
+ //
|
|
|
+ // DEVELOPER'S NOTE
|
|
|
+ // ==========================================
|
|
|
+ // DO NOT TREAT THE OUTPUT STRING AS A NULL-
|
|
|
+ // TERMINATED STRING.
|
|
|
+ // ==========================================
|
|
|
+ // The transformation process can create '\0'
|
|
|
+ // characters in the output string. Always
|
|
|
+ // use the length() method to retrieve the full
|
|
|
+ // string when it has been transformed.
|
|
|
+
|
|
|
+ // bek NOTE: The above note does not apply to this
|
|
|
+ // implementation of Warren Ward's method.
|
|
|
+ // ARACrypt knows about NULLs and transforms them
|
|
|
+ // into XOR NULLs so the entire result can be
|
|
|
+ // treated as a 'normal' NULL terminated string.
|
|
|
+
|
|
|
+ int nLen = Convert.ToInt32(csTarget);
|
|
|
+ string tempStr;
|
|
|
+ tempStr = csTarget;
|
|
|
+ for (int nPos = 0; nPos < nLen; nPos++)
|
|
|
+ {
|
|
|
+ //The follwing conversion warning not necessary here either.
|
|
|
+ //The 'loss of data', so to speak is a side effect and harmless.
|
|
|
+
|
|
|
+
|
|
|
+ byte[] cBuff = System.Text.Encoding.Default.GetBytes(tempStr);
|
|
|
+ TransformChar( Convert.ToByte(cBuff));
|
|
|
+ csTarget = Encoding.Default.GetString(cBuff);
|
|
|
+ int str= Convert.ToInt32(tempStr);
|
|
|
+ int target = Convert.ToInt32(csTarget);
|
|
|
+ str++;
|
|
|
+ target++;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|