This commit is contained in:
Igor Pavlov
2008-12-31 00:00:00 +00:00
committed by Kornel Lesiński
parent c1f1243a70
commit 3a524e5ba2
259 changed files with 2792 additions and 4855 deletions

View File

@@ -1,8 +0,0 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#endif

View File

@@ -1,21 +1,20 @@
// 7zAES.cpp
// 7zAes.cpp
#include "StdAfx.h"
#include "Windows/Defs.h"
#include "Windows/Synchronization.h"
#include "../../Common/StreamObjects.h"
#include "../../Common/StreamUtils.h"
#include "../AES/MyAES.h"
#include "7zAES.h"
extern "C"
{
#include "../../../../C/Sha256.h"
#include "../../../C/Sha256.h"
}
#include "Windows/Synchronization.h"
#include "../Common/StreamObjects.h"
#include "../Common/StreamUtils.h"
#include "7zAes.h"
#include "MyAes.h"
#ifndef EXTRACT_ONLY
#include "../Hash/RandGen.h"
#include "RandGen.h"
#endif
using namespace NWindows;

View File

@@ -1,15 +1,14 @@
// 7zAES.h
// 7zAes.h
#ifndef __CRYPTO_7Z_AES_H
#define __CRYPTO_7Z_AES_H
#include "Common/MyCom.h"
#include "Common/Types.h"
#include "Common/Buffer.h"
#include "Common/MyCom.h"
#include "Common/MyVector.h"
#include "../../ICoder.h"
#include "../../IPassword.h"
#include "../ICoder.h"
#include "../IPassword.h"
namespace NCrypto {
namespace NSevenZ {

View File

@@ -1,10 +1,10 @@
// BranchRegister.cpp
// 7zAesRegister.cpp
#include "StdAfx.h"
#include "../../Common/RegisterCodec.h"
#include "../Common/RegisterCodec.h"
#include "7zAes.h"
#include "7zAES.h"
static void *CreateCodec() { return (void *)(ICompressFilter *)(new NCrypto::NSevenZ::CDecoder()); }
#ifndef EXTRACT_ONLY
static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new NCrypto::NSevenZ::CEncoder()); }

View File

@@ -1,8 +0,0 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#endif

View File

@@ -1,8 +1,8 @@
// HmacSha1.h
// Implements HMAC-SHA-1 (RFC2104, FIPS-198)
#ifndef _HMAC_H
#define _HMAC_H
#ifndef __CRYPTO_HMAC_SHA1_H
#define __CRYPTO_HMAC_SHA1_H
#include "Sha1.h"

View File

@@ -1,8 +1,8 @@
// Crypto/AES/MyAES.cpp
// Crypto/MyAes.cpp
#include "StdAfx.h"
#include "MyAES.h"
#include "MyAes.h"
namespace NCrypto {

View File

@@ -1,18 +1,18 @@
// Crypto/AES/MyAES.h
// Crypto/MyAes.h
#ifndef __CIPHER_MYAES_H
#define __CIPHER_MYAES_H
#include "Common/Types.h"
#include "Common/MyCom.h"
#include "../../ICoder.h"
#ifndef __CRYPTO_MY_AES_H
#define __CRYPTO_MY_AES_H
extern "C"
{
#include "../../../../C/Aes.h"
#include "../../../C/Aes.h"
}
#include "../../Common/MyCom.h"
#include "../../Common/Types.h"
#include "../ICoder.h"
namespace NCrypto {
class CAesCbcEncoder:

View File

@@ -1,11 +1,11 @@
// Pbkdf2HmacSha1.h
// Password-Based Key Derivation Function (RFC 2898, PKCS #5) based on HMAC-SHA-1
#ifndef __PBKDF2HMACSHA1_H
#define __PBKDF2HMACSHA1_H
#ifndef __CRYPTO_PBKDF2_HMAC_SHA1_H
#define __CRYPTO_PBKDF2_HMAC_SHA1_H
#include <stddef.h>
#include "../../../Common/Types.h"
#include "../../Common/Types.h"
namespace NCrypto {
namespace NSha1 {

View File

@@ -3,9 +3,7 @@
#include "StdAfx.h"
#include <stdio.h>
#include "Windows/Synchronization.h"
#include "RandGen.h"
#ifndef _WIN32

View File

@@ -1,7 +1,7 @@
// RandGen.h
#ifndef __RANDGEN_H
#define __RANDGEN_H
#ifndef __CRYPTO_RAND_GEN_H
#define __CRYPTO_RAND_GEN_H
#include "Sha1.h"

View File

@@ -1,35 +0,0 @@
// Crypto/Rar20Cipher.cpp
#include "StdAfx.h"
#include "Rar20Cipher.h"
#include "Windows/Defs.h"
namespace NCrypto {
namespace NRar20 {
STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
{
_coder.SetPassword(data, size);
return S_OK;
}
STDMETHODIMP CDecoder::Init()
{
return S_OK;
}
STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
{
const UInt16 kBlockSize = 16;
if (size > 0 && size < kBlockSize)
return kBlockSize;
UInt32 i;
for (i = 0; i + kBlockSize <= size; i += kBlockSize)
{
_coder.DecryptBlock(data + i);
}
return i;
}
}}

View File

@@ -1,35 +0,0 @@
// Crypto/Rar20Cipher.h
#ifndef __CRYPTO_RAR20_CIPHER_H
#define __CRYPTO_RAR20_CIPHER_H
#include "../../ICoder.h"
#include "../../IPassword.h"
#include "Common/MyCom.h"
#include "Common/Types.h"
#include "Rar20Crypto.h"
namespace NCrypto {
namespace NRar20 {
class CDecoder:
public ICompressFilter,
public ICryptoSetPassword,
public CMyUnknownImp
{
public:
CData _coder;
MY_UNKNOWN_IMP1(ICryptoSetPassword)
STDMETHOD(Init)();
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
};
}}
#endif

View File

@@ -1,8 +0,0 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#endif

View File

@@ -1,15 +1,15 @@
// Crypto/Rar20/Crypto.cpp
// Crypto/Rar20Crypto.cpp
#include "StdAfx.h"
#include "Rar20Crypto.h"
extern "C"
{
#include "../../../../C/7zCrc.h"
#include "../../../C/7zCrc.h"
#include "../../../C/CpuArch.h"
#include "../../../C/RotateDefs.h"
}
#define rol(x,n) (((x) << (n)) | ((x) >> (8 * sizeof(x) - (n))))
#define ror(x,n) (((x) >> (n)) | ((x) << (8 * sizeof(x) - (n))))
#include "Rar20Crypto.h"
namespace NCrypto {
namespace NRar20 {
@@ -49,10 +49,8 @@ static void Swap(Byte *b1, Byte *b2)
*b2 = b;
}
void CData::SetPassword(const Byte *password, UInt32 passwordLength)
void CData::SetPassword(const Byte *password, UInt32 passwordLen)
{
// SetOldKeys(password);
Keys[0] = 0xD3A3B879L;
Keys[1] = 0x3F6D12F7L;
Keys[2] = 0x7515A235L;
@@ -60,54 +58,40 @@ void CData::SetPassword(const Byte *password, UInt32 passwordLength)
Byte psw[256];
memset(psw, 0, sizeof(psw));
memmove(psw, password, passwordLength);
memcpy(psw, password, passwordLen);
memcpy(SubstTable, InitSubstTable, sizeof(SubstTable));
for (UInt32 j = 0; j < 256; j++)
for (UInt32 i = 0; i < passwordLength; i += 2)
for (UInt32 i = 0; i < passwordLen; i += 2)
{
UInt32 n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF];
UInt32 n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF];
for (UInt32 k = 1; (n1 & 0xFF) != n2; n1++, k++)
Swap(&SubstTable[n1 & 0xFF], &SubstTable[(n1 + i + k) & 0xFF]);
}
for (UInt32 i = 0; i < passwordLength; i+= 16)
for (UInt32 i = 0; i < passwordLen; i+= 16)
EncryptBlock(&psw[i]);
}
static inline UInt32 GetUInt32FromMemLE(const Byte *p)
{
return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24);
}
static inline void WriteUInt32ToMemLE(UInt32 v, Byte *p)
{
p[0] = (Byte)v;
p[1] = (Byte)(v >> 8);
p[2] = (Byte)(v >> 16);
p[3] = (Byte)(v >> 24);
}
void CData::CryptBlock(Byte *buf, bool encrypt)
{
Byte inBuf[16];
UInt32 A, B, C, D, T, TA, TB;
A = GetUInt32FromMemLE(buf + 0) ^ Keys[0];
B = GetUInt32FromMemLE(buf + 4) ^ Keys[1];
C = GetUInt32FromMemLE(buf + 8) ^ Keys[2];
D = GetUInt32FromMemLE(buf + 12) ^ Keys[3];
A = GetUi32(buf + 0) ^ Keys[0];
B = GetUi32(buf + 4) ^ Keys[1];
C = GetUi32(buf + 8) ^ Keys[2];
D = GetUi32(buf + 12) ^ Keys[3];
if (!encrypt)
memcpy(inBuf, buf, sizeof(inBuf));
for(int i = 0; i < kNumRounds; i++)
for (int i = 0; i < kNumRounds; i++)
{
UInt32 key = Keys[(encrypt ? i : (kNumRounds - 1 - i)) & 3];
T = ((C + rol(D, 11)) ^ key);
T = ((C + rotlFixed(D, 11)) ^ key);
TA = A ^ SubstLong(T);
T = ((D ^ rol(C, 17)) + key);
T = ((D ^ rotlFixed(C, 17)) + key);
TB = B ^ SubstLong(T);
A = C;
B = D;
@@ -115,13 +99,38 @@ void CData::CryptBlock(Byte *buf, bool encrypt)
D = TB;
}
WriteUInt32ToMemLE(C ^ Keys[0], buf + 0);
WriteUInt32ToMemLE(D ^ Keys[1], buf + 4);
WriteUInt32ToMemLE(A ^ Keys[2], buf + 8);
WriteUInt32ToMemLE(B ^ Keys[3], buf + 12);
SetUi32(buf + 0, C ^ Keys[0]);
SetUi32(buf + 4, D ^ Keys[1]);
SetUi32(buf + 8, A ^ Keys[2]);
SetUi32(buf + 12, B ^ Keys[3]);
UpdateKeys(encrypt ? buf : inBuf);
}
STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
{
_cipher.SetPassword(data, size);
return S_OK;
}
STDMETHODIMP CDecoder::Init()
{
return S_OK;
}
static const UInt32 kBlockSize = 16;
STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
{
if (size == 0)
return 0;
if (size < kBlockSize)
return kBlockSize;
UInt32 i;
size -= kBlockSize;
for (i = 0; i <= size; i += kBlockSize)
_cipher.DecryptBlock(data + i);
return i;
}
}}

View File

@@ -1,9 +1,12 @@
// Crypto/Rar20/Crypto.h
// Crypto/Rar20Crypto.h
#ifndef __CRYPTO_RAR20_CRYPTO_H
#define __CRYPTO_RAR20_CRYPTO_H
#include "../../../Common/Types.h"
#include "Common/MyCom.h"
#include "../ICoder.h"
#include "../IPassword.h"
namespace NCrypto {
namespace NRar20 {
@@ -12,6 +15,7 @@ class CData
{
Byte SubstTable[256];
UInt32 Keys[4];
UInt32 SubstLong(UInt32 t)
{
return (UInt32)SubstTable[(int)t & 255] |
@@ -19,13 +23,26 @@ class CData
((UInt32)SubstTable[(int)(t >> 16) & 255] << 16) |
((UInt32)SubstTable[(int)(t >> 24) & 255] << 24);
}
void UpdateKeys(const Byte *data);
void CryptBlock(Byte *buf, bool encrypt);
public:
void EncryptBlock(Byte *buf) { CryptBlock(buf, true); }
void DecryptBlock(Byte *buf) { CryptBlock(buf, false); }
void SetPassword(const Byte *password, UInt32 passwordLength);
void SetPassword(const Byte *password, UInt32 passwordLen);
};
class CDecoder:
public ICompressFilter,
public ICryptoSetPassword,
public CMyUnknownImp
{
CData _cipher;
public:
MY_UNKNOWN_IMP1(ICryptoSetPassword)
STDMETHOD(Init)();
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
};
}}

View File

@@ -1,8 +0,0 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#endif

View File

@@ -1,11 +1,10 @@
// RarAES.cpp
// Note: you must include Crypto/AES/MyAES.cpp to project to initialize AES tables
// Crypto/RarAes.cpp
// Note: you must include MyAes.cpp to project to initialize AES tables
#include "StdAfx.h"
#include "RarAES.h"
#include "../../Common/MethodId.h"
#include "../Hash/Sha1.h"
#include "RarAes.h"
#include "Sha1.h"
namespace NCrypto {
namespace NRar29 {

View File

@@ -1,20 +1,19 @@
// RarAES.h
// Crypto/RarAes.h
#ifndef __CRYPTO_RARAES_H
#define __CRYPTO_RARAES_H
#include "Common/MyCom.h"
#include "Common/Types.h"
#include "Common/Buffer.h"
#include "../../ICoder.h"
#include "../../IPassword.h"
#ifndef __CRYPTO_RAR_AES_H
#define __CRYPTO_RAR_AES_H
extern "C"
{
#include "../../../../C/Aes.h"
#include "../../../C/Aes.h"
}
#include "Common/Buffer.h"
#include "Common/MyCom.h"
#include "../ICoder.h"
#include "../IPassword.h"
namespace NCrypto {
namespace NRar29 {

View File

@@ -1,4 +1,4 @@
// Sha1.cpp
// Crypto/Sha1.cpp
// This file is based on public domain
// Steve Reid and Wei Dai's code from Crypto++
@@ -7,7 +7,7 @@
#include "Sha1.h"
extern "C"
{
#include "../../../../C/RotateDefs.h"
#include "../../../C/RotateDefs.h"
}
namespace NCrypto {
@@ -16,7 +16,7 @@ namespace NSha1 {
// define it for speed optimization
// #define _SHA1_UNROLL
static const unsigned int kNumW =
static const unsigned kNumW =
#ifdef _SHA1_UNROLL
16;
#else
@@ -103,9 +103,9 @@ void CContextBase::GetBlockDigest(UInt32 *data, UInt32 *destDigest, bool returnR
// a = b = c = d = e = 0;
}
void CContextBase::PrepareBlock(UInt32 *block, unsigned int size) const
void CContextBase::PrepareBlock(UInt32 *block, unsigned size) const
{
unsigned int curBufferPos = size & 0xF;
unsigned curBufferPos = size & 0xF;
block[curBufferPos++] = 0x80000000;
while (curBufferPos != (16 - 2))
block[curBufferPos++] = 0;
@@ -117,7 +117,7 @@ void CContextBase::PrepareBlock(UInt32 *block, unsigned int size) const
void CContext::Update(Byte *data, size_t size, bool rar350Mode)
{
bool returnRes = false;
unsigned int curBufferPos = _count2;
unsigned curBufferPos = _count2;
while (size-- > 0)
{
int pos = (int)(curBufferPos & 3);
@@ -146,7 +146,7 @@ void CContext::Update(Byte *data, size_t size, bool rar350Mode)
void CContext::Final(Byte *digest)
{
const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 3);
unsigned int curBufferPos = _count2;
unsigned curBufferPos = _count2;
int pos = (int)(curBufferPos & 3);
curBufferPos >>= 2;
if (pos == 0)
@@ -195,7 +195,7 @@ void CContext32::Update(const UInt32 *data, size_t size)
void CContext32::Final(UInt32 *digest)
{
const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 5);
unsigned int curBufferPos = _count2;
unsigned curBufferPos = _count2;
_buffer[curBufferPos++] = 0x80000000;
while (curBufferPos != (16 - 2))
{

View File

@@ -1,12 +1,12 @@
// Sha1.h
// Crypto/Sha1.h
// This file is based on public domain
// Steve Reid and Wei Dai's code from Crypto++
#ifndef __SHA1_H
#define __SHA1_H
#ifndef __CRYPTO_SHA1_H
#define __CRYPTO_SHA1_H
#include <stddef.h>
#include "../../../Common/Types.h"
#include "../../Common/Types.h"
// Sha1 implementation in RAR before version 3.60 has bug:
// it changes data bytes in some cases.
@@ -15,11 +15,11 @@
namespace NCrypto {
namespace NSha1 {
const unsigned int kBlockSize = 64;
const unsigned int kDigestSize = 20;
const unsigned kBlockSize = 64;
const unsigned kDigestSize = 20;
const unsigned int kBlockSizeInWords = (kBlockSize >> 2);
const unsigned int kDigestSizeInWords = (kDigestSize >> 2);
const unsigned kBlockSizeInWords = (kBlockSize >> 2);
const unsigned kDigestSizeInWords = (kDigestSize >> 2);
class CContextBase
{
@@ -41,7 +41,7 @@ public:
class CContextBase2: public CContextBase
{
protected:
unsigned int _count2;
unsigned _count2;
UInt32 _buffer[kBlockSizeInWords];
void UpdateBlock() { CContextBase::UpdateBlock(_buffer); }
public:

View File

@@ -3,6 +3,6 @@
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#include "../../Common/MyWindows.h"
#endif

View File

@@ -1,8 +0,0 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#endif

View File

@@ -1,26 +1,25 @@
// WzAES.cpp
// Crypto/WzAes.cpp
/*
This code implements Brian Gladman's scheme
specified in password Based File Encryption Utility.
Note: you must include Crypto/AES/MyAES.cpp to project to initialize AES tables
Note: you must include MyAes.cpp to project to initialize AES tables
*/
#include "StdAfx.h"
#include "Windows/Defs.h"
#include "../../Common/StreamObjects.h"
#include "../../Common/StreamUtils.h"
#include "../Hash/Pbkdf2HmacSha1.h"
#include "../Hash/RandGen.h"
#include "../Common/StreamObjects.h"
#include "../Common/StreamUtils.h"
#include "WzAES.h"
#include "Pbkdf2HmacSha1.h"
#include "RandGen.h"
#include "WzAes.h"
// define it if you don't want to use speed-optimized version of Pbkdf2HmacSha1
// #define _NO_WZAES_OPTIMIZATIONS
namespace NCrypto {
namespace NWzAES {
namespace NWzAes {
const unsigned int kAesKeySizeMax = 32;

View File

@@ -1,4 +1,4 @@
// WzAES.h
// Crypto/WzAes.h
/*
This code implements Brian Gladman's scheme
specified in password Based File Encryption Utility:
@@ -12,22 +12,22 @@ specified in password Based File Encryption Utility:
#ifndef __CRYPTO_WZ_AES_H
#define __CRYPTO_WZ_AES_H
#include "../Hash/HmacSha1.h"
#include "Common/MyCom.h"
#include "Common/Buffer.h"
#include "Common/MyVector.h"
#include "../../ICoder.h"
#include "../../IPassword.h"
extern "C"
{
#include "../../../../C/Aes.h"
#include "../../../C/Aes.h"
}
#include "Common/Buffer.h"
#include "Common/MyCom.h"
#include "Common/MyVector.h"
#include "../ICoder.h"
#include "../IPassword.h"
#include "HmacSha1.h"
namespace NCrypto {
namespace NWzAES {
namespace NWzAes {
const unsigned int kSaltSizeMax = 16;
const unsigned int kMacSize = 10;

View File

@@ -1,8 +0,0 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#endif

View File

@@ -1,63 +0,0 @@
// Crypto/ZipCrypto.cpp
#include "StdAfx.h"
#include "ZipCipher.h"
extern "C"
{
#include "../../../../C/7zCrc.h"
}
namespace NCrypto {
namespace NZip {
void CCipher::UpdateKeys(Byte b)
{
Keys[0] = CRC_UPDATE_BYTE(Keys[0], b);
Keys[1] += Keys[0] & 0xff;
Keys[1] = Keys[1] * 134775813L + 1;
Keys[2] = CRC_UPDATE_BYTE(Keys[2], (Byte)(Keys[1] >> 24));
}
void CCipher::SetPassword(const Byte *password, UInt32 passwordLength)
{
Keys[0] = 305419896L;
Keys[1] = 591751049L;
Keys[2] = 878082192L;
for (UInt32 i = 0; i < passwordLength; i++)
UpdateKeys(password[i]);
}
Byte CCipher::DecryptByteSpec()
{
UInt32 temp = Keys[2] | 2;
return (Byte)((temp * (temp ^ 1)) >> 8);
}
Byte CCipher::DecryptByte(Byte encryptedByte)
{
Byte c = (Byte)(encryptedByte ^ DecryptByteSpec());
UpdateKeys(c);
return c;
}
Byte CCipher::EncryptByte(Byte b)
{
Byte c = (Byte)(b ^ DecryptByteSpec());
UpdateKeys(b);
return c;
}
void CCipher::DecryptHeader(Byte *buffer)
{
for (int i = 0; i < 12; i++)
buffer[i] = DecryptByte(buffer[i]);
}
void CCipher::EncryptHeader(Byte *buffer)
{
for (int i = 0; i < 12; i++)
buffer[i] = EncryptByte(buffer[i]);
}
}}

View File

@@ -1,26 +0,0 @@
// Crypto/ZipCrypto.h
#ifndef __CRYPTO_ZIP_CRYPTO_H
#define __CRYPTO_ZIP_CRYPTO_H
namespace NCrypto {
namespace NZip {
const int kHeaderSize = 12;
class CCipher
{
UInt32 Keys[3];
void UpdateKeys(Byte b);
Byte DecryptByteSpec();
public:
void SetPassword(const Byte *password, UInt32 passwordLength);
Byte DecryptByte(Byte encryptedByte);
Byte EncryptByte(Byte b);
void DecryptHeader(Byte *buffer);
void EncryptHeader(Byte *buffer);
};
}}
#endif

View File

@@ -1,16 +1,69 @@
// Crypto/ZipCipher.h
// Crypto/ZipCrypto.cpp
#include "StdAfx.h"
#include "ZipCipher.h"
#include "Windows/Defs.h"
extern "C"
{
#include "../../../C/7zCrc.h"
}
#include "../../Common/StreamUtils.h"
#include "../Hash/RandGen.h"
#include "../Common/StreamUtils.h"
#include "RandGen.h"
#include "ZipCrypto.h"
namespace NCrypto {
namespace NZip {
void CCipher::UpdateKeys(Byte b)
{
Keys[0] = CRC_UPDATE_BYTE(Keys[0], b);
Keys[1] += Keys[0] & 0xff;
Keys[1] = Keys[1] * 134775813L + 1;
Keys[2] = CRC_UPDATE_BYTE(Keys[2], (Byte)(Keys[1] >> 24));
}
void CCipher::SetPassword(const Byte *password, UInt32 passwordLen)
{
Keys[0] = 305419896L;
Keys[1] = 591751049L;
Keys[2] = 878082192L;
for (UInt32 i = 0; i < passwordLen; i++)
UpdateKeys(password[i]);
}
Byte CCipher::DecryptByteSpec()
{
UInt32 temp = Keys[2] | 2;
return (Byte)((temp * (temp ^ 1)) >> 8);
}
Byte CCipher::DecryptByte(Byte b)
{
Byte c = (Byte)(b ^ DecryptByteSpec());
UpdateKeys(c);
return c;
}
Byte CCipher::EncryptByte(Byte b)
{
Byte c = (Byte)(b ^ DecryptByteSpec());
UpdateKeys(b);
return c;
}
void CCipher::DecryptHeader(Byte *buf)
{
for (unsigned i = 0; i < kHeaderSize; i++)
buf[i] = DecryptByte(buf[i]);
}
void CCipher::EncryptHeader(Byte *buf)
{
for (unsigned i = 0; i < kHeaderSize; i++)
buf[i] = EncryptByte(buf[i]);
}
STDMETHODIMP CEncoder::CryptoSetPassword(const Byte *data, UInt32 size)
{
_cipher.SetPassword(data, size);

View File

@@ -1,19 +1,32 @@
// Crypto/ZipCipher.h
// Crypto/ZipCrypto.h
#ifndef __CRYPTO_ZIPCIPHER_H
#define __CRYPTO_ZIPCIPHER_H
#ifndef __CRYPTO_ZIP_CRYPTO_H
#define __CRYPTO_ZIP_CRYPTO_H
#include "Common/MyCom.h"
#include "Common/Types.h"
#include "../../ICoder.h"
#include "../../IPassword.h"
#include "ZipCrypto.h"
#include "../ICoder.h"
#include "../IPassword.h"
namespace NCrypto {
namespace NZip {
const unsigned kHeaderSize = 12;
class CCipher
{
UInt32 Keys[3];
void UpdateKeys(Byte b);
Byte DecryptByteSpec();
public:
void SetPassword(const Byte *password, UInt32 passwordLen);
Byte DecryptByte(Byte b);
Byte EncryptByte(Byte b);
void DecryptHeader(Byte *buf);
void EncryptHeader(Byte *buf);
};
class CEncoder :
public ICompressFilter,
public ICryptoSetPassword,
@@ -40,20 +53,19 @@ class CDecoder:
public ICompressFilter,
public ICryptoSetPassword,
public CMyUnknownImp
// public CBuffer2
{
CCipher _cipher;
public:
MY_UNKNOWN_IMP1(ICryptoSetPassword)
STDMETHOD(Init)();
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
HRESULT ReadHeader(ISequentialInStream *inStream);
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
};
}}
#endif

180
CPP/7zip/Crypto/ZipStrong.cpp Executable file
View File

@@ -0,0 +1,180 @@
// Crypto/ZipStrong.cpp
#include "StdAfx.h"
extern "C"
{
#include "../../../C/7zCrc.h"
#include "../../../C/CpuArch.h"
}
#include "../Common/StreamUtils.h"
#include "MyAES.h"
#include "Sha1.h"
#include "ZipStrong.h"
namespace NCrypto {
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.
static void DeriveKey2(const Byte *digest, Byte c, Byte *dest)
{
Byte buf[64];
memset(buf, c, 64);
for (unsigned i = 0; i < NSha1::kDigestSize; i++)
buf[i] ^= digest[i];
NSha1::CContext sha;
sha.Init();
sha.Update(buf, 64);
sha.Final(dest);
}
static void DeriveKey(NSha1::CContext &sha, Byte *key)
{
Byte digest[NSha1::kDigestSize];
sha.Final(digest);
Byte temp[NSha1::kDigestSize * 2];
DeriveKey2(digest, 0x36, temp);
DeriveKey2(digest, 0x5C, temp + NSha1::kDigestSize);
memcpy(key, temp, 32);
}
void CKeyInfo::SetPassword(const Byte *data, UInt32 size)
{
NSha1::CContext sha;
sha.Init();
sha.Update(data, size);
DeriveKey(sha, MasterKey);
}
STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)
{
_key.SetPassword(data, size);
return S_OK;
}
STDMETHODIMP CBaseCoder::Init()
{
return S_OK;
}
HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream, UInt32 /* crc */, UInt64 /* unpackSize */)
{
Byte temp[4];
RINOK(ReadStream_FALSE(inStream, temp, 2));
_ivSize = GetUi16(temp);
if (_ivSize == 0)
{
return E_NOTIMPL;
/*
SetUi32(_iv, crc);
for (int i = 0; i < 8; i++)
_iv[4 + i] = (Byte)(unpackSize >> (8 * i));
SetUi32(_iv + 12, 0);
*/
}
else if (_ivSize == 16)
{
RINOK(ReadStream_FALSE(inStream, _iv, _ivSize));
}
else
return E_NOTIMPL;
RINOK(ReadStream_FALSE(inStream, temp, 4));
_remSize = GetUi32(temp);
if (_remSize > _buf.GetCapacity())
{
_buf.Free();
_buf.SetCapacity(_remSize);
}
return ReadStream_FALSE(inStream, _buf, _remSize);
}
HRESULT CDecoder::CheckPassword(bool &passwOK)
{
passwOK = false;
if (_remSize < 10)
return E_NOTIMPL;
Byte *p = _buf;
UInt16 format = GetUi16(p);
if (format != 3)
return E_NOTIMPL;
UInt16 algId = GetUi16(p + 2);
if (algId < kAES128)
return E_NOTIMPL;
algId -= kAES128;
if (algId > 2)
return E_NOTIMPL;
UInt16 bitLen = GetUi16(p + 4);
UInt16 flags = GetUi16(p + 6);
if (algId * 64 + 128 != bitLen)
return E_NOTIMPL;
_key.KeySize = 16 + algId * 8;
if ((flags & 1) == 0)
return E_NOTIMPL;
UInt32 rdSize = GetUi16(p + 8);
UInt32 pos = 10;
Byte *rd = p + pos;
pos += rdSize;
if (pos + 4 > _remSize)
return E_NOTIMPL;
UInt32 reserved = GetUi32(p + pos);
pos += 4;
if (reserved != 0)
return E_NOTIMPL;
if (pos + 2 > _remSize)
return E_NOTIMPL;
UInt32 validSize = GetUi16(p + pos);
pos += 2;
Byte *validData = p + pos;
if (pos + validSize != _remSize)
return E_NOTIMPL;
if (!_aesFilter)
_aesFilter = new CAesCbcDecoder;
CMyComPtr<ICryptoProperties> cp;
RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp));
{
RINOK(cp->SetKey(_key.MasterKey, _key.KeySize));
RINOK(cp->SetInitVector(_iv, 16));
_aesFilter->Init();
if (_aesFilter->Filter(rd, rdSize) != rdSize)
return E_NOTIMPL;
}
Byte fileKey[32];
NSha1::CContext sha;
sha.Init();
sha.Update(_iv, 16);
sha.Update(rd, rdSize - 16); // we don't use last 16 bytes (PAD bytes)
DeriveKey(sha, fileKey);
RINOK(cp->SetKey(fileKey, _key.KeySize));
RINOK(cp->SetInitVector(_iv, 16));
_aesFilter->Init();
if (_aesFilter->Filter(validData, validSize) != validSize)
return E_NOTIMPL;
if (validSize < 4)
return E_NOTIMPL;
validSize -= 4;
if (GetUi32(validData + validSize) != CrcCalc(validData, validSize))
return S_OK;
passwOK = true;
_aesFilter->Init();
return S_OK;
}
STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
{
return _aesFilter->Filter(data, size);
}
}}

53
CPP/7zip/Crypto/ZipStrong.h Executable file
View File

@@ -0,0 +1,53 @@
// Crypto/ZipStrong.h
#ifndef __CRYPTO_ZIP_STRONG_H
#define __CRYPTO_ZIP_STRONG_H
#include "Common/MyCom.h"
#include "Common/Buffer.h"
#include "../ICoder.h"
#include "../IPassword.h"
namespace NCrypto {
namespace NZipStrong {
struct CKeyInfo
{
Byte MasterKey[32];
UInt32 KeySize;
void SetPassword(const Byte *data, UInt32 size);
};
class CBaseCoder:
public ICompressFilter,
public ICryptoSetPassword,
public CMyUnknownImp
{
protected:
CKeyInfo _key;
CMyComPtr<ICompressFilter> _aesFilter;
CByteBuffer _buf;
public:
STDMETHOD(Init)();
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) = 0;
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
};
class CDecoder:
public CBaseCoder
{
UInt32 _ivSize;
Byte _iv[16];
UInt32 _remSize;
public:
MY_UNKNOWN_IMP1(ICryptoSetPassword)
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
HRESULT ReadHeader(ISequentialInStream *inStream, UInt32 crc, UInt64 unpackSize);
HRESULT CheckPassword(bool &passwOK);
};
}}
#endif

View File

@@ -1,7 +0,0 @@
DIRS = \
7zAES\~ \
all: $(DIRS)
$(DIRS):
!include "../SubBuild.mak"