Mercurial > vba-linux
comparison 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 |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // Crypto/RarAes.cpp | |
2 // Note: you must include MyAes.cpp to project to initialize AES tables | |
3 | |
4 #include "StdAfx.h" | |
5 | |
6 #include "RarAes.h" | |
7 #include "Sha1.h" | |
8 | |
9 namespace NCrypto { | |
10 namespace NRar29 { | |
11 | |
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 } | |
20 | |
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 } | |
50 | |
51 static const int kMaxPasswordLength = 127 * 2; | |
52 | |
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 } | |
74 | |
75 STDMETHODIMP CDecoder::Init() | |
76 { | |
77 Calculate(); | |
78 Aes_SetKeyDecode(&Aes.aes, aesKey, kRarAesKeySize); | |
79 AesCbc_Init(&Aes, aesInit); | |
80 return S_OK; | |
81 } | |
82 | |
83 STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size) | |
84 { | |
85 return (UInt32)AesCbc_Decode(&Aes, data, size); | |
86 } | |
87 | |
88 void CDecoder::Calculate() | |
89 { | |
90 if (_needCalculate) | |
91 { | |
92 const int kSaltSize = 8; | |
93 | |
94 Byte rawPassword[kMaxPasswordLength + kSaltSize]; | |
95 | |
96 memcpy(rawPassword, buffer, buffer.GetCapacity()); | |
97 | |
98 size_t rawLength = buffer.GetCapacity(); | |
99 | |
100 if (_thereIsSalt) | |
101 { | |
102 memcpy(rawPassword + rawLength, _salt, kSaltSize); | |
103 rawLength += kSaltSize; | |
104 } | |
105 | |
106 NSha1::CContext sha; | |
107 sha.Init(); | |
108 | |
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 } | |
138 | |
139 }} |