Crypto++
arc4.cpp
1 // arc4.cpp - written and placed in the public domain by Wei Dai
2 
3 // The ARC4 algorithm was first revealed in an anonymous email to the
4 // cypherpunks mailing list. This file originally contained some
5 // code copied from this email. The code has since been rewritten in order
6 // to clarify the copyright status of this file. It should now be
7 // completely in the public domain.
8 
9 #include "pch.h"
10 #define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
11 #include "arc4.h"
12 
13 NAMESPACE_BEGIN(CryptoPP)
14 namespace Weak1 {
15 
16 void ARC4_TestInstantiations()
17 {
18  ARC4 x;
19 }
20 
21 ARC4_Base::~ARC4_Base()
22 {
23  m_x = m_y = 0;
24 }
25 
26 void ARC4_Base::UncheckedSetKey(const byte *key, unsigned int keyLen, const NameValuePairs &params)
27 {
28  AssertValidKeyLength(keyLen);
29 
30  m_x = 1;
31  m_y = 0;
32 
33  unsigned int i;
34  for (i=0; i<256; i++)
35  m_state[i] = i;
36 
37  unsigned int keyIndex = 0, stateIndex = 0;
38  for (i=0; i<256; i++)
39  {
40  unsigned int a = m_state[i];
41  stateIndex += key[keyIndex] + a;
42  stateIndex &= 0xff;
43  m_state[i] = m_state[stateIndex];
44  m_state[stateIndex] = a;
45  if (++keyIndex >= keyLen)
46  keyIndex = 0;
47  }
48 
49  int discardBytes = params.GetIntValueWithDefault("DiscardBytes", GetDefaultDiscardBytes());
50  DiscardBytes(discardBytes);
51 }
52 
53 template <class T>
54 static inline unsigned int MakeByte(T &x, T &y, byte *s)
55 {
56  unsigned int a = s[x];
57  y = (y+a) & 0xff;
58  unsigned int b = s[y];
59  s[x] = b;
60  s[y] = a;
61  x = (x+1) & 0xff;
62  return s[(a+b) & 0xff];
63 }
64 
65 void ARC4_Base::GenerateBlock(byte *output, size_t size)
66 {
67  while (size--)
68  *output++ = MakeByte(m_x, m_y, m_state);
69 }
70 
71 void ARC4_Base::ProcessData(byte *outString, const byte *inString, size_t length)
72 {
73  if (length == 0)
74  return;
75 
76  byte *const s = m_state;
77  unsigned int x = m_x;
78  unsigned int y = m_y;
79 
80  if (inString == outString)
81  {
82  do
83  {
84  *outString++ ^= MakeByte(x, y, s);
85  } while (--length);
86  }
87  else
88  {
89  do
90  {
91  *outString++ = *inString++ ^ MakeByte(x, y, s);
92  }
93  while(--length);
94  }
95 
96  m_x = x;
97  m_y = y;
98 }
99 
100 void ARC4_Base::DiscardBytes(size_t length)
101 {
102  if (length == 0)
103  return;
104 
105  byte *const s = m_state;
106  unsigned int x = m_x;
107  unsigned int y = m_y;
108 
109  do
110  {
111  MakeByte(x, y, s);
112  }
113  while(--length);
114 
115  m_x = x;
116  m_y = y;
117 }
118 
119 }
120 NAMESPACE_END