Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Crypto/RarAES/RarAES.cpp')
-rwxr-xr-xCPP/7zip/Crypto/RarAES/RarAES.cpp187
1 files changed, 187 insertions, 0 deletions
diff --git a/CPP/7zip/Crypto/RarAES/RarAES.cpp b/CPP/7zip/Crypto/RarAES/RarAES.cpp
new file mode 100755
index 00000000..ae22bb2a
--- /dev/null
+++ b/CPP/7zip/Crypto/RarAES/RarAES.cpp
@@ -0,0 +1,187 @@
+// Crypto/RarAES/RarAES.h
+// This code is based on UnRar sources
+
+#include "StdAfx.h"
+
+#include "RarAES.h"
+#include "../Hash/Sha1.h"
+
+extern void GetCryptoFolderPrefix(TCHAR *path);
+
+namespace NCrypto {
+namespace NRar29 {
+
+CDecoder::CDecoder():
+ _thereIsSalt(false),
+ _needCalculate(true),
+ _rar350Mode(false)
+{
+ for (int i = 0; i < sizeof(_salt); i++)
+ _salt[i] = 0;
+}
+
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
+{
+ bool thereIsSaltPrev = _thereIsSalt;
+ _thereIsSalt = false;
+ if (size == 0)
+ return S_OK;
+ if (size < 8)
+ return E_INVALIDARG;
+ _thereIsSalt = true;
+ bool same = false;
+ if (_thereIsSalt == thereIsSaltPrev)
+ {
+ same = true;
+ if (_thereIsSalt)
+ {
+ for (int i = 0; i < sizeof(_salt); i++)
+ if (_salt[i] != data[i])
+ {
+ same = false;
+ break;
+ }
+ }
+ }
+ for (int i = 0; i < sizeof(_salt); i++)
+ _salt[i] = data[i];
+ if (!_needCalculate && !same)
+ _needCalculate = true;
+ return S_OK;
+}
+
+static const int kMaxPasswordLength = 127 * 2;
+
+STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
+{
+ if (size > kMaxPasswordLength)
+ size = kMaxPasswordLength;
+ bool same = false;
+ if (size == buffer.GetCapacity())
+ {
+ same = true;
+ for (UInt32 i = 0; i < size; i++)
+ if (data[i] != buffer[i])
+ {
+ same = false;
+ break;
+ }
+ }
+ if (!_needCalculate && !same)
+ _needCalculate = true;
+ buffer.SetCapacity(size);
+ memcpy(buffer, data, size);
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::Init()
+{
+ Calculate();
+ RINOK(CreateFilter());
+ CMyComPtr<ICryptoProperties> cp;
+ RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp));
+ RINOK(cp->SetKey(aesKey, 16));
+ RINOK(cp->SetInitVector(aesInit, 16));
+ _aesFilter->Init();
+ return S_OK;
+}
+
+HRESULT CDecoder::CreateFilter()
+{
+ if (_aesFilter)
+ return S_OK;
+ TCHAR aesLibPath[MAX_PATH + 64];
+ GetCryptoFolderPrefix(aesLibPath);
+ lstrcat(aesLibPath, TEXT("AES.dll"));
+ return _aesLib.LoadAndCreateFilter(aesLibPath, CLSID_CCrypto_AES_CBC_Decoder, &_aesFilter);
+}
+
+STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
+{
+ return _aesFilter->Filter(data, size);
+}
+
+void CDecoder::Calculate()
+{
+ if (_needCalculate)
+ {
+ const int kSaltSize = 8;
+
+ Byte rawPassword[kMaxPasswordLength + kSaltSize];
+
+ memcpy(rawPassword, buffer, buffer.GetCapacity());
+
+ size_t rawLength = buffer.GetCapacity();
+
+ if (_thereIsSalt)
+ {
+ memcpy(rawPassword + rawLength, _salt, kSaltSize);
+ rawLength += kSaltSize;
+ }
+
+ NSha1::CContext sha;
+ sha.Init();
+
+ // seems rar reverts hash for sha.
+ const int hashRounds = 0x40000;
+ int i;
+ for (i = 0; i < hashRounds; i++)
+ {
+ sha.Update(rawPassword, rawLength, _rar350Mode);
+ Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) };
+ sha.Update(pswNum, 3, _rar350Mode);
+ if (i % (hashRounds / 16) == 0)
+ {
+ NSha1::CContext shaTemp = sha;
+ Byte digest[NSha1::kDigestSize];
+ shaTemp.Final(digest);
+ aesInit[i / (hashRounds / 16)] = (Byte)digest[4 * 4 + 3];
+ }
+ }
+ /*
+ // it's test message for sha
+ const char *message = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+ sha.Update((const Byte *)message, strlen(message));
+ */
+ Byte digest[20];
+ sha.Final(digest);
+ for (i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ aesKey[i * 4 + j] = (digest[i * 4 + 3 - j]);
+ }
+ _needCalculate = false;
+}
+
+
+
+/*
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream, UInt64 const *inSize,
+ const UInt64 *outSize,ICompressProgressInfo *progress)
+{
+ Calculate();
+ TCHAR aesLibPath[MAX_PATH + 64];
+ GetCryptoFolderPrefix(aesLibPath);
+ lstrcat(aesLibPath, TEXT("AES.dll"));
+ CCoderLibrary aesLib;
+ CMyComPtr<ICompressCoder2> aesDecoder;
+ RINOK(aesLib.LoadAndCreateCoder2(aesLibPath, CLSID_CCrypto_AES128_Decoder, &aesDecoder));
+
+ CSequentialInStreamImp *ivStreamSpec = new CSequentialInStreamImp;
+ CMyComPtr<ISequentialInStream> ivStream(ivStreamSpec);
+ ivStreamSpec->Init(aesInit, 16);
+
+ CSequentialInStreamImp *keyStreamSpec = new CSequentialInStreamImp;
+ CMyComPtr<ISequentialInStream> keyStream(keyStreamSpec);
+ keyStreamSpec->Init(aesKey, 16);
+
+ ISequentialInStream *inStreams[3] = { inStream, ivStream, keyStream };
+ UInt64 ivSize = 16;
+ UInt64 keySize = 16;
+ const UInt64 *inSizes[3] = { inSize, &ivSize, &ivSize, };
+ return aesDecoder->Code(inStreams, inSizes, 3,
+ &outStream, &outSize, 1, progress);
+}
+*/
+
+}}