2020-09-08 08:34:21 +00:00
|
|
|
#ifndef _RAR_CRYPT_
|
|
|
|
#define _RAR_CRYPT_
|
|
|
|
|
|
|
|
|
|
|
|
enum CRYPT_METHOD {
|
|
|
|
CRYPT_NONE,CRYPT_RAR13,CRYPT_RAR15,CRYPT_RAR20,CRYPT_RAR30,CRYPT_RAR50
|
|
|
|
};
|
|
|
|
|
|
|
|
#define SIZE_SALT50 16
|
|
|
|
#define SIZE_SALT30 8
|
|
|
|
#define SIZE_INITV 16
|
|
|
|
#define SIZE_PSWCHECK 8
|
|
|
|
#define SIZE_PSWCHECK_CSUM 4
|
|
|
|
|
|
|
|
#define CRYPT_BLOCK_SIZE 16
|
|
|
|
#define CRYPT_BLOCK_MASK (CRYPT_BLOCK_SIZE-1) // 0xf
|
|
|
|
|
|
|
|
#define CRYPT5_KDF_LG2_COUNT 15 // LOG2 of PDKDF2 iteration count.
|
|
|
|
#define CRYPT5_KDF_LG2_COUNT_MAX 24 // LOG2 of maximum accepted iteration count.
|
|
|
|
#define CRYPT_VERSION 0 // Supported encryption version.
|
|
|
|
|
|
|
|
|
|
|
|
class CryptData
|
|
|
|
{
|
|
|
|
struct KDF5CacheItem
|
|
|
|
{
|
|
|
|
SecPassword Pwd;
|
|
|
|
byte Salt[SIZE_SALT50];
|
|
|
|
byte Key[32];
|
|
|
|
uint Lg2Count; // Log2 of PBKDF2 repetition count.
|
|
|
|
byte PswCheckValue[SHA256_DIGEST_SIZE];
|
|
|
|
byte HashKeyValue[SHA256_DIGEST_SIZE];
|
2023-05-19 19:24:23 +00:00
|
|
|
|
|
|
|
KDF5CacheItem() {Clean();}
|
|
|
|
~KDF5CacheItem() {Clean();}
|
|
|
|
|
|
|
|
void Clean()
|
|
|
|
{
|
|
|
|
cleandata(Salt,sizeof(Salt));
|
|
|
|
cleandata(Key,sizeof(Key));
|
|
|
|
cleandata(&Lg2Count,sizeof(Lg2Count));
|
|
|
|
cleandata(PswCheckValue,sizeof(PswCheckValue));
|
|
|
|
cleandata(HashKeyValue,sizeof(HashKeyValue));
|
|
|
|
}
|
2020-09-08 08:34:21 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct KDF3CacheItem
|
|
|
|
{
|
|
|
|
SecPassword Pwd;
|
|
|
|
byte Salt[SIZE_SALT30];
|
|
|
|
byte Key[16];
|
|
|
|
byte Init[16];
|
|
|
|
bool SaltPresent;
|
2023-05-19 19:24:23 +00:00
|
|
|
|
|
|
|
KDF3CacheItem() {Clean();}
|
|
|
|
~KDF3CacheItem() {Clean();}
|
|
|
|
|
|
|
|
void Clean()
|
|
|
|
{
|
|
|
|
cleandata(Salt,sizeof(Salt));
|
|
|
|
cleandata(Key,sizeof(Key));
|
|
|
|
cleandata(Init,sizeof(Init));
|
|
|
|
cleandata(&SaltPresent,sizeof(SaltPresent));
|
|
|
|
}
|
2020-09-08 08:34:21 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
void SetKey13(const char *Password);
|
|
|
|
void Decrypt13(byte *Data,size_t Count);
|
|
|
|
|
|
|
|
void SetKey15(const char *Password);
|
|
|
|
void Crypt15(byte *Data,size_t Count);
|
|
|
|
|
|
|
|
void SetKey20(const char *Password);
|
|
|
|
void Swap20(byte *Ch1,byte *Ch2);
|
|
|
|
void UpdKeys20(byte *Buf);
|
|
|
|
void EncryptBlock20(byte *Buf);
|
|
|
|
void DecryptBlock20(byte *Buf);
|
|
|
|
|
|
|
|
void SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt);
|
|
|
|
void SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck);
|
|
|
|
|
|
|
|
KDF3CacheItem KDF3Cache[4];
|
|
|
|
uint KDF3CachePos;
|
|
|
|
|
|
|
|
KDF5CacheItem KDF5Cache[4];
|
|
|
|
uint KDF5CachePos;
|
|
|
|
|
|
|
|
CRYPT_METHOD Method;
|
|
|
|
|
|
|
|
Rijndael rin;
|
|
|
|
|
|
|
|
uint CRCTab[256]; // For RAR 1.5 and RAR 2.0 encryption.
|
|
|
|
|
|
|
|
byte SubstTable20[256];
|
|
|
|
uint Key20[4];
|
|
|
|
|
|
|
|
byte Key13[3];
|
|
|
|
ushort Key15[4];
|
|
|
|
public:
|
|
|
|
CryptData();
|
|
|
|
bool SetCryptKeys(bool Encrypt,CRYPT_METHOD Method,SecPassword *Password,
|
|
|
|
const byte *Salt,const byte *InitV,uint Lg2Cnt,
|
|
|
|
byte *HashKey,byte *PswCheck);
|
2020-09-08 08:39:21 +00:00
|
|
|
void SetRijndalDecryptKey(byte *Key,byte *InitV);
|
2020-09-08 08:34:21 +00:00
|
|
|
void SetAV15Encryption();
|
|
|
|
void SetCmt13Encryption();
|
|
|
|
void EncryptBlock(byte *Buf,size_t Size);
|
|
|
|
void DecryptBlock(byte *Buf,size_t Size);
|
|
|
|
static void SetSalt(byte *Salt,size_t SaltSize);
|
|
|
|
};
|
|
|
|
|
2023-05-19 19:24:23 +00:00
|
|
|
|
|
|
|
class CheckPassword
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum CONFIDENCE {CONFIDENCE_HIGH,CONFIDENCE_MEDIUM,CONFIDENCE_LOW};
|
|
|
|
virtual CONFIDENCE GetConfidence()=0;
|
|
|
|
virtual bool Check(SecPassword *Password)=0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class RarCheckPassword:public CheckPassword
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
CryptData *Crypt;
|
|
|
|
uint Lg2Count;
|
|
|
|
byte Salt[SIZE_SALT50];
|
|
|
|
byte InitV[SIZE_INITV];
|
|
|
|
byte PswCheck[SIZE_PSWCHECK];
|
|
|
|
public:
|
|
|
|
RarCheckPassword()
|
|
|
|
{
|
|
|
|
Crypt=NULL;
|
|
|
|
}
|
|
|
|
~RarCheckPassword()
|
|
|
|
{
|
|
|
|
delete Crypt;
|
|
|
|
}
|
|
|
|
void Set(byte *Salt,byte *InitV,uint Lg2Count,byte *PswCheck)
|
|
|
|
{
|
|
|
|
if (Crypt==NULL)
|
|
|
|
Crypt=new CryptData;
|
|
|
|
memcpy(this->Salt,Salt,sizeof(this->Salt));
|
|
|
|
memcpy(this->InitV,InitV,sizeof(this->InitV));
|
|
|
|
this->Lg2Count=Lg2Count;
|
|
|
|
memcpy(this->PswCheck,PswCheck,sizeof(this->PswCheck));
|
|
|
|
}
|
|
|
|
bool IsSet() {return Crypt!=NULL;}
|
|
|
|
|
|
|
|
// RAR5 provides the higly reliable 64 bit password verification value.
|
|
|
|
CONFIDENCE GetConfidence() {return CONFIDENCE_HIGH;}
|
|
|
|
|
|
|
|
bool Check(SecPassword *Password)
|
|
|
|
{
|
|
|
|
byte PswCheck[SIZE_PSWCHECK];
|
|
|
|
Crypt->SetCryptKeys(false,CRYPT_RAR50,Password,Salt,InitV,Lg2Count,NULL,PswCheck);
|
|
|
|
return memcmp(PswCheck,this->PswCheck,sizeof(this->PswCheck))==0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-09-08 08:34:21 +00:00
|
|
|
void GetRnd(byte *RndBuf,size_t BufSize);
|
|
|
|
|
|
|
|
void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
|
|
|
|
size_t DataLength,byte *ResDigest);
|
|
|
|
void pbkdf2(const byte *pass, size_t pass_len, const byte *salt,
|
|
|
|
size_t salt_len,byte *key, byte *Value1, byte *Value2,
|
|
|
|
uint rounds);
|
|
|
|
|
|
|
|
void ConvertHashToMAC(HashValue *Value,byte *Key);
|
|
|
|
|
|
|
|
#endif
|