void CryptData::SetKey20(const char *Password) { InitCRC32(CRCTab); char Psw[MAXPASSWORD]; strncpyz(Psw,Password,ASIZE(Psw)); // We'll need to modify it below. size_t PswLength=strlen(Psw); Key20[0]=0xD3A3B879L; Key20[1]=0x3F6D12F7L; Key20[2]=0x7515A235L; Key20[3]=0xA4E7F123L; memcpy(SubstTable20,InitSubstTable20,sizeof(SubstTable20)); for (int J=0;J<256;J++) for (size_t I=0;I<PswLength;I+=2) { uint N1=(byte)CRCTab [ (byte(Password[I]) - J) &0xff]; uint N2=(byte)CRCTab [ (byte(Password[I+1]) + J) &0xff]; for (int K=1;N1!=N2;N1=(N1+1)&0xff,K++) Swap20(&SubstTable20[N1],&SubstTable20[(N1+I+K)&0xff]); } // Incomplete last block of password must be zero padded. if ((PswLength & CRYPT_BLOCK_MASK)!=0) for (size_t I=PswLength;I<=(PswLength|CRYPT_BLOCK_MASK);I++) Psw[I]=0; for (size_t I=0;I<PswLength;I+=CRYPT_BLOCK_SIZE) EncryptBlock20((byte *)Psw+I); }
void CryptData::SetCryptKeys(char *Password,unsigned char *Salt,bool Encrypt,bool OldOnly) { if (*Password==0) return; if (OldOnly) { #ifndef SFX_MODULE if (CRCTab[1]==0) InitCRC(); unsigned char Psw[MAXPASSWORD]; SetOldKeys(Password); Key[0]=0xD3A3B879L; Key[1]=0x3F6D12F7L; Key[2]=0x7515A235L; Key[3]=0xA4E7F123L; memset(Psw,0,sizeof(Psw)); #if defined(_WIN_32) && !defined(GUI) CharToOemBuff(Password,(char*)Psw,strlen(Password)); #else strncpy((char *)Psw,Password,MAXPASSWORD-1); #endif int PswLength=strlen(Password); memcpy(SubstTable,InitSubstTable,sizeof(SubstTable)); for (int J=0;J<256;J++) for (int I=0;I<PswLength;I+=2) { unsigned int N1=(unsigned char)CRCTab[(Psw[I]-J)&0xff]; unsigned int N2=(unsigned char)CRCTab[(Psw[I+1]+J)&0xff]; for (int K=1;N1!=N2;N1=(N1+1)&0xff,K++) Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xff]); } for (int I=0;I<PswLength;I+=16) EncryptBlock20(&Psw[I]); #endif return; } bool Cached=false; for (int I=0;I<sizeof(Cache)/sizeof(Cache[0]);I++) if (strcmp(Cache[I].Password,Password)==0 && (Salt==NULL && !Cache[I].SaltPresent || Salt!=NULL && Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SALT_SIZE)==0)) { memcpy(AESKey,Cache[I].AESKey,sizeof(AESKey)); memcpy(AESInit,Cache[I].AESInit,sizeof(AESInit)); Cached=true; break; } if (!Cached) { wchar PswW[MAXPASSWORD]; CharToWide(Password,PswW,MAXPASSWORD-1); PswW[MAXPASSWORD-1]=0; unsigned char RawPsw[2*MAXPASSWORD+SALT_SIZE]; WideToRaw(PswW,RawPsw); int RawLength=2*strlenw(PswW); if (Salt!=NULL) { memcpy(RawPsw+RawLength,Salt,SALT_SIZE); RawLength+=SALT_SIZE; } hash_context c; hash_initial(&c); const int HashRounds=0x40000; for (int I=0;I<HashRounds;I++) { hash_process( &c, RawPsw, RawLength); unsigned char PswNum[3]; PswNum[0]=(unsigned char)I; PswNum[1]=(unsigned char)(I>>8); PswNum[2]=(unsigned char)(I>>16); hash_process( &c, PswNum, 3); if (I%(HashRounds/16)==0) { hash_context tempc=c; uint32 digest[5]; hash_final( &tempc, digest); AESInit[I/(HashRounds/16)]=(unsigned char)digest[4]; } } uint32 digest[5]; hash_final( &c, digest); for (int I=0;I<4;I++) for (int J=0;J<4;J++) AESKey[I*4+J]=(unsigned char)(digest[I]>>(J*8)); strcpy(Cache[CachePos].Password,Password); if ((Cache[CachePos].SaltPresent=(Salt!=NULL))==true) memcpy(Cache[CachePos].Salt,Salt,SALT_SIZE); memcpy(Cache[CachePos].AESKey,AESKey,sizeof(AESKey)); memcpy(Cache[CachePos].AESInit,AESInit,sizeof(AESInit)); CachePos=(CachePos+1)%(sizeof(Cache)/sizeof(Cache[0])); }
void CryptData::SetCryptKeys(const wchar *Password,const byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash) { if (*Password==0) return; if (OldOnly) { #ifndef SFX_MODULE if (CRCTab[1]==0) InitCRC(); char Psw[MAXPASSWORD]; memset(Psw,0,sizeof(Psw)); // We need to use ASCII password for older encryption algorithms. WideToChar(Password,Psw,ASIZE(Psw)); Psw[ASIZE(Psw)-1]=0; size_t PswLength=strlen(Psw); SetOldKeys(Psw); Key[0]=0xD3A3B879L; Key[1]=0x3F6D12F7L; Key[2]=0x7515A235L; Key[3]=0xA4E7F123L; memcpy(SubstTable,InitSubstTable,sizeof(SubstTable)); for (int J=0;J<256;J++) for (size_t I=0;I<PswLength;I+=2) { uint N1=(byte)CRCTab [ (byte(Psw[I]) - J) &0xff]; uint N2=(byte)CRCTab [ (byte(Psw[I+1]) + J) &0xff]; for (int K=1;N1!=N2;N1=(N1+1)&0xff,K++) Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xff]); } for (size_t I=0;I<PswLength;I+=16) EncryptBlock20((byte *)&Psw[I]); #endif return; } bool Cached=false; for (uint I=0;I<ASIZE(Cache);I++) if (wcscmp(Cache[I].Password,Password)==0 && (Salt==NULL && !Cache[I].SaltPresent || Salt!=NULL && Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SALT_SIZE)==0) && Cache[I].HandsOffHash==HandsOffHash) { memcpy(AESKey,Cache[I].AESKey,sizeof(AESKey)); memcpy(AESInit,Cache[I].AESInit,sizeof(AESInit)); Cached=true; break; } if (!Cached) { byte RawPsw[2*MAXPASSWORD+SALT_SIZE]; WideToRaw(Password,RawPsw); size_t RawLength=2*wcslen(Password); if (Salt!=NULL) { memcpy(RawPsw+RawLength,Salt,SALT_SIZE); RawLength+=SALT_SIZE; } hash_context c; hash_initial(&c); const int HashRounds=0x40000; for (int I=0;I<HashRounds;I++) { hash_process( &c, RawPsw, RawLength, HandsOffHash); byte PswNum[3]; PswNum[0]=(byte)I; PswNum[1]=(byte)(I>>8); PswNum[2]=(byte)(I>>16); hash_process( &c, PswNum, 3, HandsOffHash); if (I%(HashRounds/16)==0) { hash_context tempc=c; uint32 digest[5]; hash_final( &tempc, digest, HandsOffHash); AESInit[I/(HashRounds/16)]=(byte)digest[4]; } } uint32 digest[5]; hash_final( &c, digest, HandsOffHash); for (int I=0;I<4;I++) for (int J=0;J<4;J++) AESKey[I*4+J]=(byte)(digest[I]>>(J*8)); wcscpy(Cache[CachePos].Password,Password); if ((Cache[CachePos].SaltPresent=(Salt!=NULL))==true) memcpy(Cache[CachePos].Salt,Salt,SALT_SIZE); Cache[CachePos].HandsOffHash=HandsOffHash; memcpy(Cache[CachePos].AESKey,AESKey,sizeof(AESKey)); memcpy(Cache[CachePos].AESInit,AESInit,sizeof(AESInit)); CachePos=(CachePos+1)%(sizeof(Cache)/sizeof(Cache[0])); }