Upstream tarball 9452
[amule.git] / src / RC4Encrypt.cpp
blob14b52a11bfc88359182d12ba9461876beb485e84
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2008 Merkur ( devs@emule-project.net / http://www.emule-project.net )
6 //
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
9 // respective authors.
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "RC4Encrypt.h"
28 #include <common/MD5Sum.h>
31 #include <stdexcept>
33 CRC4EncryptableBuffer::CRC4EncryptableBuffer() : m_encrypted(false), m_hasKey(false), m_key()
38 CRC4EncryptableBuffer::~CRC4EncryptableBuffer()
42 void CRC4EncryptableBuffer::Append(const uint8* buffer, int n)
44 wxASSERT(!m_encrypted);
45 if (!m_encrypted) {
46 CMemFile::Append(buffer, n);
47 } else {
48 throw std::runtime_error(
49 "(CRC4EncryptableBuffer::Append): "
50 "Tryed to append data to an encrypted buffer.");
55 void CRC4EncryptableBuffer::Encrypt()
57 wxASSERT(!m_encrypted);
58 RC4Crypt(GetRawBuffer(), GetRawBuffer(), GetLength());
59 m_encrypted = true;
62 void CRC4EncryptableBuffer::RC4Crypt( const uint8 *pachIn, uint8 *pachOut, uint32 nLen)
64 wxASSERT( m_hasKey && nLen > 0 );
66 if (m_hasKey) {
67 uint8 byX = m_key.byX;;
68 uint8 byY = m_key.byY;
69 uint8* pabyState = &m_key.abyState[0];;
70 uint8 byXorIndex;
72 for (uint32 i = 0; i < nLen; ++i) {
73 byX = (byX + 1) % 256;
74 byY = (pabyState[byX] + byY) % 256;
75 std::swap(pabyState[byX], pabyState[byY]);
76 byXorIndex = (pabyState[byX] + pabyState[byY]) % 256;
78 if (pachIn != NULL) {
79 pachOut[i] = pachIn[i] ^ pabyState[byXorIndex];
83 m_key.byX = byX;
84 m_key.byY = byY;
85 } else {
86 throw std::runtime_error(
87 "(CRC4EncryptableBuffer::RC4Crypt): "
88 "Encrypt() has been called without a previous call"
89 "to SetKey().");
93 uint8 *CRC4EncryptableBuffer::Detach()
95 int n = GetLength();
96 uint8 *ret = new uint8[n];
97 memcpy(ret, GetRawBuffer(), n);
98 ResetData();
99 m_encrypted = false;
100 return ret;
104 void CRC4EncryptableBuffer::SetKey(const MD5Sum& keyhash, bool bSkipDiscard)
106 wxASSERT(!m_hasKey);
107 if (!m_hasKey) {
108 m_hasKey = true;
109 RC4CreateKey( keyhash.GetRawHash(), 16, bSkipDiscard);
110 } else {
111 throw std::runtime_error( "(CRC4EncryptableBuffer::SetKey): SetKey() has been called twice.");
116 void CRC4EncryptableBuffer::RC4CreateKey(const uint8* pachKeyData, uint32 nLen, bool bSkipDiscard)
118 uint8 index1;
119 uint8 index2;
120 uint8* pabyState;
122 pabyState= &m_key.abyState[0];
123 for (int i = 0; i < 256; ++i) {
124 pabyState[i] = (uint8)i;
127 m_key.byX = 0;
128 m_key.byY = 0;
129 index1 = 0;
130 index2 = 0;
132 for (int i = 0; i < 256; ++i) {
133 index2 = (pachKeyData[index1] + pabyState[i] + index2) % 256;
134 std::swap(pabyState[i], pabyState[index2]);
135 index1 = (uint8)((index1 + 1) % nLen);
138 if (!bSkipDiscard) {
139 RC4Crypt(NULL, NULL, 1024);
143 void CRC4EncryptableBuffer::ResetData()
145 m_encrypted = false;
146 // Not touching the keys.
147 CMemFile::ResetData();
150 void CRC4EncryptableBuffer::FullReset()
152 ResetData();
153 m_hasKey = false;
154 memset(&m_key, 0, sizeof(RC4_Key_Struct));