mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-16 04:11:49 -06:00
4.44 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
804edc5756
commit
d9666cf046
3
CPP/7zip/Crypto/WzAES/StdAfx.cpp
Executable file
3
CPP/7zip/Crypto/WzAES/StdAfx.cpp
Executable file
@@ -0,0 +1,3 @@
|
||||
// StdAfx.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
8
CPP/7zip/Crypto/WzAES/StdAfx.h
Executable file
8
CPP/7zip/Crypto/WzAES/StdAfx.h
Executable file
@@ -0,0 +1,8 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#endif
|
||||
246
CPP/7zip/Crypto/WzAES/WzAES.cpp
Executable file
246
CPP/7zip/Crypto/WzAES/WzAES.cpp
Executable file
@@ -0,0 +1,246 @@
|
||||
// WzAES.cpp
|
||||
/*
|
||||
This code implements Brian Gladman's scheme
|
||||
specified in password Based File Encryption Utility.
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Windows/Defs.h"
|
||||
#include "../../Common/StreamObjects.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
#include "../Hash/Pbkdf2HmacSha1.h"
|
||||
#include "../Hash/RandGen.h"
|
||||
|
||||
#include "WzAES.h"
|
||||
|
||||
#ifdef CRYPTO_AES
|
||||
#include "../AES/MyAES.h"
|
||||
#else
|
||||
extern void GetCryptoFolderPrefix(TCHAR *path);
|
||||
#endif
|
||||
|
||||
// define it if you don't want to use speed-optimized version of Pbkdf2HmacSha1
|
||||
// #define _NO_WZAES_OPTIMIZATIONS
|
||||
|
||||
namespace NCrypto {
|
||||
namespace NWzAES {
|
||||
|
||||
const unsigned int kAesKeySizeMax = 32;
|
||||
|
||||
static const UInt32 kNumKeyGenIterations = 1000;
|
||||
|
||||
STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
||||
{
|
||||
if(size > kPasswordSizeMax)
|
||||
return E_INVALIDARG;
|
||||
_key.Password.SetCapacity(size);
|
||||
memcpy(_key.Password, data, size);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CBaseCoder::EncryptData(Byte *data, UInt32 size)
|
||||
{
|
||||
unsigned int pos = _blockPos;
|
||||
for (; size > 0; size--)
|
||||
{
|
||||
if (pos == kAesBlockSize)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < 8 && ++_counter[j] == 0; j++);
|
||||
for (j = 0; j < 8; j++)
|
||||
_buffer[j] = _counter[j];
|
||||
for (; j < kAesBlockSize; j++)
|
||||
_buffer[j] = 0;
|
||||
_aesFilter->Filter(_buffer, kAesBlockSize);
|
||||
pos = 0;
|
||||
}
|
||||
*data++ ^= _buffer[pos++];
|
||||
}
|
||||
_blockPos = pos;
|
||||
}
|
||||
|
||||
#ifndef _NO_WZAES_OPTIMIZATIONS
|
||||
|
||||
static void BytesToBeUInt32s(const Byte *src, UInt32 *dest, int destSize)
|
||||
{
|
||||
for (int i = 0 ; i < destSize; i++)
|
||||
dest[i] =
|
||||
((UInt32)(src[i * 4 + 0]) << 24) |
|
||||
((UInt32)(src[i * 4 + 1]) << 16) |
|
||||
((UInt32)(src[i * 4 + 2]) << 8) |
|
||||
((UInt32)(src[i * 4 + 3]));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CBaseCoder::Init()
|
||||
{
|
||||
UInt32 keySize = _key.GetKeySize();
|
||||
UInt32 keysTotalSize = 2 * keySize + kPwdVerifCodeSize;
|
||||
Byte buf[2 * kAesKeySizeMax + kPwdVerifCodeSize];
|
||||
|
||||
// for (int ii = 0; ii < 1000; ii++)
|
||||
{
|
||||
#ifdef _NO_WZAES_OPTIMIZATIONS
|
||||
|
||||
NSha1::Pbkdf2Hmac(
|
||||
_key.Password, _key.Password.GetCapacity(),
|
||||
_key.Salt, _key.GetSaltSize(),
|
||||
kNumKeyGenIterations,
|
||||
buf, keysTotalSize);
|
||||
|
||||
#else
|
||||
|
||||
UInt32 buf32[(2 * kAesKeySizeMax + kPwdVerifCodeSize + 3) / 4];
|
||||
UInt32 key32SizeTotal = (keysTotalSize + 3) / 4;
|
||||
UInt32 salt[kSaltSizeMax * 4];
|
||||
UInt32 saltSizeInWords = _key.GetSaltSize() / 4;
|
||||
BytesToBeUInt32s(_key.Salt, salt, saltSizeInWords);
|
||||
NSha1::Pbkdf2Hmac32(
|
||||
_key.Password, _key.Password.GetCapacity(),
|
||||
salt, saltSizeInWords,
|
||||
kNumKeyGenIterations,
|
||||
buf32, key32SizeTotal);
|
||||
for (UInt32 j = 0; j < keysTotalSize; j++)
|
||||
buf[j] = (Byte)(buf32[j / 4] >> (24 - 8 * (j & 3)));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
_hmac.SetKey(buf + keySize, keySize);
|
||||
memcpy(_key.PwdVerifComputed, buf + 2 * keySize, kPwdVerifCodeSize);
|
||||
|
||||
_blockPos = kAesBlockSize;
|
||||
for (int i = 0; i < 8; i++)
|
||||
_counter[i] = 0;
|
||||
|
||||
RINOK(CreateFilters());
|
||||
CMyComPtr<ICryptoProperties> cp;
|
||||
RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp));
|
||||
return cp->SetKey(buf, keySize);
|
||||
}
|
||||
|
||||
static HRESULT SafeWrite(ISequentialOutStream *outStream, const Byte *data, UInt32 size)
|
||||
{
|
||||
UInt32 processedSize;
|
||||
RINOK(WriteStream(outStream, data, size, &processedSize));
|
||||
return ((processedSize == size) ? S_OK : E_FAIL);
|
||||
}
|
||||
|
||||
/*
|
||||
STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
||||
{
|
||||
Byte keySizeMode = 3;
|
||||
return outStream->Write(&keySizeMode, 1, NULL);
|
||||
}
|
||||
*/
|
||||
|
||||
HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream)
|
||||
{
|
||||
UInt32 saltSize = _key.GetSaltSize();
|
||||
g_RandomGenerator.Generate(_key.Salt, saltSize);
|
||||
Init();
|
||||
RINOK(SafeWrite(outStream, _key.Salt, saltSize));
|
||||
return SafeWrite(outStream, _key.PwdVerifComputed, kPwdVerifCodeSize);
|
||||
}
|
||||
|
||||
HRESULT CEncoder::WriteFooter(ISequentialOutStream *outStream)
|
||||
{
|
||||
Byte mac[kMacSize];
|
||||
_hmac.Final(mac, kMacSize);
|
||||
return SafeWrite(outStream, mac, kMacSize);
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
{
|
||||
if (size != 1)
|
||||
return E_INVALIDARG;
|
||||
_key.Init();
|
||||
Byte keySizeMode = data[0];
|
||||
if (keySizeMode < 1 || keySizeMode > 3)
|
||||
return E_INVALIDARG;
|
||||
_key.KeySizeMode = keySizeMode;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream)
|
||||
{
|
||||
UInt32 saltSize = _key.GetSaltSize();
|
||||
UInt32 extraSize = saltSize + kPwdVerifCodeSize;
|
||||
Byte temp[kSaltSizeMax + kPwdVerifCodeSize];
|
||||
UInt32 processedSize;
|
||||
RINOK(ReadStream(inStream, temp, extraSize, &processedSize));
|
||||
if (processedSize != extraSize)
|
||||
return E_FAIL;
|
||||
UInt32 i;
|
||||
for (i = 0; i < saltSize; i++)
|
||||
_key.Salt[i] = temp[i];
|
||||
for (i = 0; i < kPwdVerifCodeSize; i++)
|
||||
_pwdVerifFromArchive[i] = temp[saltSize + i];
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static bool CompareArrays(const Byte *p1, const Byte *p2, UInt32 size)
|
||||
{
|
||||
for (UInt32 i = 0; i < size; i++)
|
||||
if (p1[i] != p2[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDecoder::CheckPasswordVerifyCode()
|
||||
{
|
||||
return CompareArrays(_key.PwdVerifComputed, _pwdVerifFromArchive, kPwdVerifCodeSize);
|
||||
}
|
||||
|
||||
HRESULT CDecoder::CheckMac(ISequentialInStream *inStream, bool &isOK)
|
||||
{
|
||||
isOK = false;
|
||||
UInt32 processedSize;
|
||||
Byte mac1[kMacSize];
|
||||
RINOK(ReadStream(inStream, mac1, kMacSize, &processedSize));
|
||||
if (processedSize != kMacSize)
|
||||
return E_FAIL;
|
||||
Byte mac2[kMacSize];
|
||||
_hmac.Final(mac2, kMacSize);
|
||||
isOK = CompareArrays(mac1, mac2, kMacSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size)
|
||||
{
|
||||
EncryptData(data, size);
|
||||
_hmac.Update(data, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
|
||||
{
|
||||
_hmac.Update(data, size);
|
||||
EncryptData(data, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CBaseCoder::CreateFilters()
|
||||
{
|
||||
if (!_aesFilter)
|
||||
{
|
||||
#ifdef CRYPTO_AES
|
||||
|
||||
_aesFilter = new CAES_ECB_Encoder;
|
||||
|
||||
#else
|
||||
|
||||
TCHAR aesLibPath[MAX_PATH + 64];
|
||||
GetCryptoFolderPrefix(aesLibPath);
|
||||
lstrcat(aesLibPath, TEXT("AES.dll"));
|
||||
RINOK(_aesLibrary.LoadAndCreateFilter(aesLibPath, CLSID_CCrypto_AES_ECB_Encoder, &_aesFilter));
|
||||
|
||||
#endif
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
126
CPP/7zip/Crypto/WzAES/WzAES.h
Executable file
126
CPP/7zip/Crypto/WzAES/WzAES.h
Executable file
@@ -0,0 +1,126 @@
|
||||
// WzAES.h
|
||||
/*
|
||||
This code implements Brian Gladman's scheme
|
||||
specified in password Based File Encryption Utility:
|
||||
- AES encryption (128,192,256-bit) in Counter (CTR) mode.
|
||||
- HMAC-SHA1 authentication for encrypted data (10 bytes)
|
||||
- Keys are derived by PPKDF2(RFC2898)-HMAC-SHA1 from ASCII password and
|
||||
Salt (saltSize = aesKeySize / 2).
|
||||
- 2 bytes contain Password Verifier's Code
|
||||
*/
|
||||
|
||||
#ifndef __CRYPTO_WZ_AES_H
|
||||
#define __CRYPTO_WZ_AES_H
|
||||
|
||||
#include "../Hash/HmacSha1.h"
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
#include "Common/Buffer.h"
|
||||
#include "Common/Vector.h"
|
||||
|
||||
#include "../../ICoder.h"
|
||||
#include "../../IPassword.h"
|
||||
|
||||
#ifndef CRYPTO_AES
|
||||
#include "../../Archive/Common/CoderLoader.h"
|
||||
#endif
|
||||
|
||||
DEFINE_GUID(CLSID_CCrypto_AES_ECB_Encoder,
|
||||
0x23170F69, 0x40C1, 0x278B, 0x06, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x01, 0x00);
|
||||
|
||||
namespace NCrypto {
|
||||
namespace NWzAES {
|
||||
|
||||
const unsigned int kAesBlockSize = 16;
|
||||
const unsigned int kSaltSizeMax = 16;
|
||||
const unsigned int kMacSize = 10;
|
||||
|
||||
const UInt32 kPasswordSizeMax = 99; // 128;
|
||||
|
||||
// Password Verification Code Size
|
||||
const unsigned int kPwdVerifCodeSize = 2;
|
||||
|
||||
class CKeyInfo
|
||||
{
|
||||
public:
|
||||
Byte KeySizeMode; // 1 - 128-bit , 2 - 192-bit , 3 - 256-bit
|
||||
Byte Salt[kSaltSizeMax];
|
||||
Byte PwdVerifComputed[kPwdVerifCodeSize];
|
||||
|
||||
CByteBuffer Password;
|
||||
|
||||
UInt32 GetKeySize() const { return (8 * (KeySizeMode & 3) + 8); }
|
||||
UInt32 GetSaltSize() const { return (4 * (KeySizeMode & 3) + 4); }
|
||||
|
||||
CKeyInfo() { Init(); }
|
||||
void Init() { KeySizeMode = 3; }
|
||||
};
|
||||
|
||||
class CBaseCoder:
|
||||
public ICompressFilter,
|
||||
public ICryptoSetPassword,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
protected:
|
||||
CKeyInfo _key;
|
||||
Byte _counter[8];
|
||||
Byte _buffer[kAesBlockSize];
|
||||
NSha1::CHmac _hmac;
|
||||
unsigned int _blockPos;
|
||||
Byte _pwdVerifFromArchive[kPwdVerifCodeSize];
|
||||
|
||||
void EncryptData(Byte *data, UInt32 size);
|
||||
|
||||
#ifndef CRYPTO_AES
|
||||
CCoderLibrary _aesLibrary;
|
||||
#endif
|
||||
CMyComPtr<ICompressFilter> _aesFilter;
|
||||
|
||||
HRESULT CreateFilters();
|
||||
public:
|
||||
STDMETHOD(Init)();
|
||||
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) = 0;
|
||||
|
||||
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
|
||||
|
||||
UInt32 GetHeaderSize() const { return _key.GetSaltSize() + kPwdVerifCodeSize; }
|
||||
};
|
||||
|
||||
class CEncoder:
|
||||
public CBaseCoder
|
||||
// public ICompressWriteCoderProperties
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ICryptoSetPassword)
|
||||
// ICompressWriteCoderProperties
|
||||
// STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
|
||||
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
|
||||
HRESULT WriteHeader(ISequentialOutStream *outStream);
|
||||
HRESULT WriteFooter(ISequentialOutStream *outStream);
|
||||
bool SetKeyMode(Byte mode)
|
||||
{
|
||||
if (mode < 1 || mode > 3)
|
||||
return false;
|
||||
_key.KeySizeMode = mode;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class CDecoder:
|
||||
public CBaseCoder,
|
||||
public ICompressSetDecoderProperties2
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(
|
||||
ICryptoSetPassword,
|
||||
ICompressSetDecoderProperties2)
|
||||
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
|
||||
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
|
||||
HRESULT ReadHeader(ISequentialInStream *inStream);
|
||||
bool CheckPasswordVerifyCode();
|
||||
HRESULT CheckMac(ISequentialInStream *inStream, bool &isOK);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user