view src/win32/7zip/7z/CPP/7zip/Crypto/RarAes.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line source
1 // Crypto/RarAes.cpp
2 // Note: you must include MyAes.cpp to project to initialize AES tables
4 #include "StdAfx.h"
6 #include "RarAes.h"
7 #include "Sha1.h"
9 namespace NCrypto {
10 namespace NRar29 {
12 CDecoder::CDecoder():
13 _thereIsSalt(false),
14 _needCalculate(true),
15 _rar350Mode(false)
16 {
17 for (int i = 0; i < sizeof(_salt); i++)
18 _salt[i] = 0;
19 }
21 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
22 {
23 bool thereIsSaltPrev = _thereIsSalt;
24 _thereIsSalt = false;
25 if (size == 0)
26 return S_OK;
27 if (size < 8)
28 return E_INVALIDARG;
29 _thereIsSalt = true;
30 bool same = false;
31 if (_thereIsSalt == thereIsSaltPrev)
32 {
33 same = true;
34 if (_thereIsSalt)
35 {
36 for (int i = 0; i < sizeof(_salt); i++)
37 if (_salt[i] != data[i])
38 {
39 same = false;
40 break;
41 }
42 }
43 }
44 for (int i = 0; i < sizeof(_salt); i++)
45 _salt[i] = data[i];
46 if (!_needCalculate && !same)
47 _needCalculate = true;
48 return S_OK;
49 }
51 static const int kMaxPasswordLength = 127 * 2;
53 STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
54 {
55 if (size > kMaxPasswordLength)
56 size = kMaxPasswordLength;
57 bool same = false;
58 if (size == buffer.GetCapacity())
59 {
60 same = true;
61 for (UInt32 i = 0; i < size; i++)
62 if (data[i] != buffer[i])
63 {
64 same = false;
65 break;
66 }
67 }
68 if (!_needCalculate && !same)
69 _needCalculate = true;
70 buffer.SetCapacity(size);
71 memcpy(buffer, data, size);
72 return S_OK;
73 }
75 STDMETHODIMP CDecoder::Init()
76 {
77 Calculate();
78 Aes_SetKeyDecode(&Aes.aes, aesKey, kRarAesKeySize);
79 AesCbc_Init(&Aes, aesInit);
80 return S_OK;
81 }
83 STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
84 {
85 return (UInt32)AesCbc_Decode(&Aes, data, size);
86 }
88 void CDecoder::Calculate()
89 {
90 if (_needCalculate)
91 {
92 const int kSaltSize = 8;
94 Byte rawPassword[kMaxPasswordLength + kSaltSize];
96 memcpy(rawPassword, buffer, buffer.GetCapacity());
98 size_t rawLength = buffer.GetCapacity();
100 if (_thereIsSalt)
101 {
102 memcpy(rawPassword + rawLength, _salt, kSaltSize);
103 rawLength += kSaltSize;
104 }
106 NSha1::CContext sha;
107 sha.Init();
109 // seems rar reverts hash for sha.
110 const int hashRounds = 0x40000;
111 int i;
112 for (i = 0; i < hashRounds; i++)
113 {
114 sha.Update(rawPassword, rawLength, _rar350Mode);
115 Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) };
116 sha.Update(pswNum, 3, _rar350Mode);
117 if (i % (hashRounds / 16) == 0)
118 {
119 NSha1::CContext shaTemp = sha;
120 Byte digest[NSha1::kDigestSize];
121 shaTemp.Final(digest);
122 aesInit[i / (hashRounds / 16)] = (Byte)digest[4 * 4 + 3];
123 }
124 }
125 /*
126 // it's test message for sha
127 const char *message = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
128 sha.Update((const Byte *)message, strlen(message));
129 */
130 Byte digest[20];
131 sha.Final(digest);
132 for (i = 0; i < 4; i++)
133 for (int j = 0; j < 4; j++)
134 aesKey[i * 4 + j] = (digest[i * 4 + 3 - j]);
135 }
136 _needCalculate = false;
137 }
139 }}