mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 11:14:58 -06:00
17.00
This commit is contained in:
@@ -30,6 +30,8 @@ class CAesCbcCoder:
|
||||
public:
|
||||
CAesCbcCoder(bool encodeMode, unsigned keySize);
|
||||
|
||||
virtual ~CAesCbcCoder() {}; // we need virtual destructor for derived classes
|
||||
|
||||
MY_UNKNOWN_IMP3(ICompressFilter, ICryptoProperties, ICompressSetCoderProperties)
|
||||
|
||||
INTERFACE_ICompressFilter(;)
|
||||
|
||||
@@ -68,7 +68,7 @@ void CData::SetPassword(const Byte *data, unsigned size)
|
||||
for (unsigned i = 0; i < size; i += 2)
|
||||
{
|
||||
unsigned n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF];
|
||||
unsigned n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF];
|
||||
unsigned n2 = (Byte)g_CrcTable[(psw[(size_t)i + 1] + j) & 0xFF];
|
||||
for (unsigned k = 1; (n1 & 0xFF) != n2; n1++, k++)
|
||||
Swap(SubstTable[n1 & 0xFF], SubstTable[(n1 + i + k) & 0xFF]);
|
||||
}
|
||||
|
||||
@@ -20,10 +20,10 @@ class CData
|
||||
|
||||
UInt32 SubstLong(UInt32 t) const
|
||||
{
|
||||
return (UInt32)SubstTable[(unsigned)t & 255]
|
||||
| ((UInt32)SubstTable[(unsigned)(t >> 8) & 255] << 8)
|
||||
return (UInt32)SubstTable[(unsigned)t & 255]
|
||||
| ((UInt32)SubstTable[(unsigned)(t >> 8) & 255] << 8)
|
||||
| ((UInt32)SubstTable[(unsigned)(t >> 16) & 255] << 16)
|
||||
| ((UInt32)SubstTable[(unsigned)(t >> 24) & 255] << 24);
|
||||
| ((UInt32)SubstTable[(unsigned)(t >> 24) ] << 24);
|
||||
}
|
||||
void UpdateKeys(const Byte *data);
|
||||
void CryptBlock(Byte *buf, bool encrypt);
|
||||
|
||||
@@ -105,6 +105,8 @@ public:
|
||||
_key.KeySizeMode = (EKeySizeMode)mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual ~CBaseCoder() {}
|
||||
};
|
||||
|
||||
class CEncoder:
|
||||
|
||||
@@ -50,6 +50,8 @@ public:
|
||||
MY_UNKNOWN_IMP1(ICryptoSetPassword)
|
||||
STDMETHOD(Init)();
|
||||
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
|
||||
|
||||
virtual ~CCipher() {}
|
||||
};
|
||||
|
||||
class CEncoder: public CCipher
|
||||
|
||||
@@ -15,10 +15,14 @@ namespace NZipStrong {
|
||||
|
||||
static const UInt16 kAES128 = 0x660E;
|
||||
|
||||
// DeriveKey* function is similar to CryptDeriveKey() from Windows.
|
||||
// But MSDN tells that we need such scheme only if
|
||||
// "the required key length is longer than the hash value"
|
||||
// but ZipStrong uses it always.
|
||||
/*
|
||||
DeriveKey() function is similar to CryptDeriveKey() from Windows.
|
||||
New version of MSDN contains the following condition in CryptDeriveKey() description:
|
||||
"If the hash is not a member of the SHA-2 family and the required key is for either 3DES or AES".
|
||||
Now we support ZipStrong for AES only. And it uses SHA1.
|
||||
Our DeriveKey() code is equal to CryptDeriveKey() in Windows for such conditions: (SHA1 + AES).
|
||||
if (method != AES && method != 3DES), probably we need another code.
|
||||
*/
|
||||
|
||||
static void DeriveKey2(const Byte *digest, Byte c, Byte *dest)
|
||||
{
|
||||
@@ -116,7 +120,7 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK)
|
||||
|
||||
if ((flags & 0x4000) != 0)
|
||||
{
|
||||
// Use 3DES
|
||||
// Use 3DES for rd data
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
@@ -135,17 +139,21 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK)
|
||||
if (rdSize + 16 > _remSize)
|
||||
return E_NOTIMPL;
|
||||
|
||||
const unsigned kPadSize = kAesPadAllign; // is equal to blockSize of cipher for rd
|
||||
|
||||
/*
|
||||
if (cert)
|
||||
{
|
||||
// how to filter rd, if ((rdSize & 0xF) != 0) ?
|
||||
if ((rdSize & 0x7) != 0)
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
if ((rdSize & 0xF) != 0)
|
||||
// PKCS7 padding
|
||||
if (rdSize < kPadSize)
|
||||
return E_NOTIMPL;
|
||||
if ((rdSize & (kPadSize - 1)) != 0)
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
@@ -198,13 +206,18 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK)
|
||||
RINOK(SetInitVector(_iv, 16));
|
||||
RINOK(Init());
|
||||
Filter(p, rdSize);
|
||||
|
||||
rdSize -= kPadSize;
|
||||
for (unsigned i = 0; i < kPadSize; i++)
|
||||
if (p[(size_t)rdSize + i] != kPadSize)
|
||||
return S_OK; // passwOK = false;
|
||||
}
|
||||
|
||||
Byte fileKey[32];
|
||||
NSha1::CContext sha;
|
||||
sha.Init();
|
||||
sha.Update(_iv, _ivSize);
|
||||
sha.Update(p, rdSize - 16); // we don't use last 16 bytes (PAD bytes)
|
||||
sha.Update(p, rdSize);
|
||||
DeriveKey(sha, fileKey);
|
||||
|
||||
RINOK(SetKey(fileKey, _key.KeySize));
|
||||
|
||||
@@ -42,6 +42,8 @@ public:
|
||||
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
|
||||
};
|
||||
|
||||
const unsigned kAesPadAllign = AES_BLOCK_SIZE;
|
||||
|
||||
class CDecoder: public CBaseCoder
|
||||
{
|
||||
UInt32 _ivSize;
|
||||
@@ -51,6 +53,12 @@ public:
|
||||
MY_UNKNOWN_IMP1(ICryptoSetPassword)
|
||||
HRESULT ReadHeader(ISequentialInStream *inStream, UInt32 crc, UInt64 unpackSize);
|
||||
HRESULT Init_and_CheckPassword(bool &passwOK);
|
||||
UInt32 GetPadSize(UInt32 packSize32) const
|
||||
{
|
||||
// Padding is to align to blockSize of cipher.
|
||||
// Change it, if is not AES
|
||||
return kAesPadAllign - (packSize32 & (kAesPadAllign - 1));
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user