1 // Crypto/ZipCrypto.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../C/7zCrc.h"
6
7 #include "../Common/StreamUtils.h"
8
9 #include "RandGen.h"
10 #include "ZipCrypto.h"
11
12 namespace NCrypto {
13 namespace NZip {
14
15 #define UPDATE_KEYS(b) { \
16 key0 = CRC_UPDATE_BYTE(key0, b); \
17 key1 = (key1 + (key0 & 0xFF)) * 0x8088405 + 1; \
18 key2 = CRC_UPDATE_BYTE(key2, (Byte)(key1 >> 24)); } \
19
20 #define DECRYPT_BYTE_1 UInt32 temp = key2 | 2;
21 #define DECRYPT_BYTE_2 ((Byte)((temp * (temp ^ 1)) >> 8))
22
Z7_COM7F_IMF(CCipher::CryptoSetPassword (const Byte * data,UInt32 size))23 Z7_COM7F_IMF(CCipher::CryptoSetPassword(const Byte *data, UInt32 size))
24 {
25 UInt32 key0 = 0x12345678;
26 UInt32 key1 = 0x23456789;
27 UInt32 key2 = 0x34567890;
28
29 for (UInt32 i = 0; i < size; i++)
30 UPDATE_KEYS(data[i])
31
32 KeyMem0 = key0;
33 KeyMem1 = key1;
34 KeyMem2 = key2;
35
36 return S_OK;
37 }
38
Z7_COM7F_IMF(CCipher::Init ())39 Z7_COM7F_IMF(CCipher::Init())
40 {
41 return S_OK;
42 }
43
WriteHeader_Check16(ISequentialOutStream * outStream,UInt16 crc)44 HRESULT CEncoder::WriteHeader_Check16(ISequentialOutStream *outStream, UInt16 crc)
45 {
46 Byte h[kHeaderSize];
47
48 /* PKZIP before 2.0 used 2 byte CRC check.
49 PKZIP 2.0+ used 1 byte CRC check. It's more secure.
50 We also use 1 byte CRC. */
51
52 MY_RAND_GEN(h, kHeaderSize - 1);
53 // h[kHeaderSize - 2] = (Byte)(crc);
54 h[kHeaderSize - 1] = (Byte)(crc >> 8);
55
56 RestoreKeys();
57 Filter(h, kHeaderSize);
58 return WriteStream(outStream, h, kHeaderSize);
59 }
60
Z7_COM7F_IMF2(UInt32,CEncoder::Filter (Byte * data,UInt32 size))61 Z7_COM7F_IMF2(UInt32, CEncoder::Filter(Byte *data, UInt32 size))
62 {
63 UInt32 key0 = this->Key0;
64 UInt32 key1 = this->Key1;
65 UInt32 key2 = this->Key2;
66
67 for (UInt32 i = 0; i < size; i++)
68 {
69 Byte b = data[i];
70 DECRYPT_BYTE_1
71 data[i] = (Byte)(b ^ DECRYPT_BYTE_2);
72 UPDATE_KEYS(b)
73 }
74
75 this->Key0 = key0;
76 this->Key1 = key1;
77 this->Key2 = key2;
78
79 return size;
80 }
81
ReadHeader(ISequentialInStream * inStream)82 HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream)
83 {
84 return ReadStream_FAIL(inStream, _header, kHeaderSize);
85 }
86
Init_BeforeDecode()87 void CDecoder::Init_BeforeDecode()
88 {
89 RestoreKeys();
90 Filter(_header, kHeaderSize);
91 }
92
Z7_COM7F_IMF2(UInt32,CDecoder::Filter (Byte * data,UInt32 size))93 Z7_COM7F_IMF2(UInt32, CDecoder::Filter(Byte *data, UInt32 size))
94 {
95 UInt32 key0 = this->Key0;
96 UInt32 key1 = this->Key1;
97 UInt32 key2 = this->Key2;
98
99 for (UInt32 i = 0; i < size; i++)
100 {
101 DECRYPT_BYTE_1
102 Byte b = (Byte)(data[i] ^ DECRYPT_BYTE_2);
103 UPDATE_KEYS(b)
104 data[i] = b;
105 }
106
107 this->Key0 = key0;
108 this->Key1 = key1;
109 this->Key2 = key2;
110
111 return size;
112 }
113
114 }}
115