mirror of
https://github.com/LisherSong/ps5-web-file-manager.git
synced 2026-10-06 08:00:23 +02:00
New RAR engine for v1.9, replacing dmc_unrar 1.7.0. dmc_unrar only
dispatches RAR5 compression version 5 (switch(file->version) case
0x5000); WinRAR 6.x/7.x writes version 6 -> DMC_UNRAR_FILE_UNSUPPORTED_VERSION
-> user-facing "corrupt archive" on real v6 archives (diagnosed 2026-09-05
from a v6:8M:m0:m3 test file). unrar 7.20.1 natively supports v6,
encrypted and multi-volume RAR.
Vendored into third_party/unrar7/ (new dir) so the tree stays buildable
while src/rar_extract.c still references the dmc facade. Contents are a
verbatim copy of opello/unrar @97e1780 (159 files, v7.20.1) plus two
project files:
- unrar_c_api.h (C facade shim: platform types + dll.hpp re-export)
- VENDORED.md (source pin, build model, license notes)
Build model verified on host (MinGW g++ 16.2, Windows):
- all 49 UnRARDll.vcxproj sources compile with
-std=c++17 -DRARDLL -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
- links + runs: RARGetDllVersion() = 9 (smoke binary in .build/, ignored)
- Windows link additionally needs -lpowrprof
License: UnRAR freeware license (not GPL) - free to use for handling RAR
archives; cannot be used to build a RAR-compatible archiver. THIRD_PARTY_NOTICES
update lands with the engine swap commit.
Next (v1.9 work items): engine swap in rar_extract.c, Makefile .cpp rules,
fixtures + host tests, frontend password/multi-volume, then ELF build.
70 lines
2.1 KiB
C++
70 lines
2.1 KiB
C++
void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt)
|
|
{
|
|
byte AESKey[16],AESInit[16];
|
|
|
|
bool Cached=false;
|
|
for (uint I=0;I<ASIZE(KDF3Cache);I++)
|
|
if (KDF3Cache[I].Pwd==*Password &&
|
|
(Salt==NULL && !KDF3Cache[I].SaltPresent || Salt!=NULL &&
|
|
KDF3Cache[I].SaltPresent && memcmp(KDF3Cache[I].Salt,Salt,SIZE_SALT30)==0))
|
|
{
|
|
memcpy(AESKey,KDF3Cache[I].Key,sizeof(AESKey));
|
|
SecHideData(AESKey,sizeof(AESKey),false,false);
|
|
memcpy(AESInit,KDF3Cache[I].Init,sizeof(AESInit));
|
|
Cached=true;
|
|
break;
|
|
}
|
|
|
|
if (!Cached)
|
|
{
|
|
byte RawPsw[2*MAXPASSWORD+SIZE_SALT30];
|
|
size_t PswLength=wcslen(PwdW);
|
|
size_t RawLength=2*PswLength;
|
|
WideToRaw(PwdW,PswLength,RawPsw,RawLength);
|
|
if (Salt!=NULL)
|
|
{
|
|
memcpy(RawPsw+RawLength,Salt,SIZE_SALT30);
|
|
RawLength+=SIZE_SALT30;
|
|
}
|
|
sha1_context c;
|
|
sha1_init(&c);
|
|
|
|
const uint HashRounds=0x40000;
|
|
for (uint I=0;I<HashRounds;I++)
|
|
{
|
|
sha1_process_rar29( &c, RawPsw, RawLength );
|
|
byte PswNum[3];
|
|
PswNum[0]=(byte)I;
|
|
PswNum[1]=(byte)(I>>8);
|
|
PswNum[2]=(byte)(I>>16);
|
|
sha1_process(&c, PswNum, 3);
|
|
if (I%(HashRounds/16)==0)
|
|
{
|
|
sha1_context tempc=c;
|
|
uint32 digest[5];
|
|
sha1_done( &tempc, digest );
|
|
AESInit[I/(HashRounds/16)]=(byte)digest[4];
|
|
}
|
|
}
|
|
uint32 digest[5];
|
|
sha1_done( &c, digest );
|
|
for (uint I=0;I<4;I++)
|
|
for (uint J=0;J<4;J++)
|
|
AESKey[I*4+J]=(byte)(digest[I]>>(J*8));
|
|
|
|
KDF3Cache[KDF3CachePos].Pwd=*Password;
|
|
if ((KDF3Cache[KDF3CachePos].SaltPresent=(Salt!=NULL))==true)
|
|
memcpy(KDF3Cache[KDF3CachePos].Salt,Salt,SIZE_SALT30);
|
|
memcpy(KDF3Cache[KDF3CachePos].Key,AESKey,sizeof(AESKey));
|
|
SecHideData(KDF3Cache[KDF3CachePos].Key,sizeof(KDF3Cache[KDF3CachePos].Key),true,false);
|
|
memcpy(KDF3Cache[KDF3CachePos].Init,AESInit,sizeof(AESInit));
|
|
KDF3CachePos=(KDF3CachePos+1)%ASIZE(KDF3Cache);
|
|
|
|
cleandata(RawPsw,sizeof(RawPsw));
|
|
}
|
|
rin.Init(Encrypt, AESKey, 128, AESInit);
|
|
cleandata(AESKey,sizeof(AESKey));
|
|
cleandata(AESInit,sizeof(AESInit));
|
|
}
|
|
|