1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
// Crypto/WzAes.h
/*
This code implements Brian Gladman's scheme
specified in "A Password Based File Encryption Utility":
- AES encryption (128,192,256-bit) in Counter (CTR) mode.
- HMAC-SHA1 authentication for encrypted data (10 bytes)
- Keys are derived by PPKDF2(RFC2898)-HMAC-SHA1 from ASCII password and
Salt (saltSize = aesKeySize / 2).
- 2 bytes contain Password Verifier's Code
*/
#ifndef __CRYPTO_WZ_AES_H
#define __CRYPTO_WZ_AES_H
#include "../../../C/Aes.h"
#include "../../Common/MyBuffer.h"
#include "../../Common/MyCom.h"
#include "../ICoder.h"
#include "../IPassword.h"
#include "HmacSha1.h"
namespace NCrypto {
namespace NWzAes {
/* ICompressFilter::Init() does nothing for this filter.
Call to init:
Encoder:
CryptoSetPassword();
WriteHeader();
Decoder:
[CryptoSetPassword();]
ReadHeader();
[CryptoSetPassword();] Init_and_CheckPassword();
[CryptoSetPassword();] Init_and_CheckPassword();
*/
const UInt32 kPasswordSizeMax = 99; // 128;
const unsigned kSaltSizeMax = 16;
const unsigned kPwdVerifSize = 2;
const unsigned kMacSize = 10;
enum EKeySizeMode
{
kKeySizeMode_AES128 = 1,
kKeySizeMode_AES192 = 2,
kKeySizeMode_AES256 = 3
};
struct CKeyInfo
{
EKeySizeMode KeySizeMode;
Byte Salt[kSaltSizeMax];
Byte PwdVerifComputed[kPwdVerifSize];
CByteBuffer Password;
unsigned GetKeySize() const { return (8 * KeySizeMode + 8); }
unsigned GetSaltSize() const { return (4 * KeySizeMode + 4); }
unsigned GetNumSaltWords() const { return (KeySizeMode + 1); }
CKeyInfo(): KeySizeMode(kKeySizeMode_AES256) {}
};
struct CAesCtr2
{
unsigned pos;
unsigned offset;
UInt32 aes[4 + AES_NUM_IVMRK_WORDS + 3];
CAesCtr2();
};
void AesCtr2_Init(CAesCtr2 *p);
void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size);
class CBaseCoder:
public ICompressFilter,
public ICryptoSetPassword,
public CMyUnknownImp
{
protected:
CKeyInfo _key;
NSha1::CHmac _hmac;
CAesCtr2 _aes;
void Init2();
public:
MY_UNKNOWN_IMP1(ICryptoSetPassword)
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
STDMETHOD(Init)();
unsigned GetHeaderSize() const { return _key.GetSaltSize() + kPwdVerifSize; }
unsigned GetAddPackSize() const { return GetHeaderSize() + kMacSize; }
bool SetKeyMode(unsigned mode)
{
if (mode < kKeySizeMode_AES128 || mode > kKeySizeMode_AES256)
return false;
_key.KeySizeMode = (EKeySizeMode)mode;
return true;
}
};
class CEncoder:
public CBaseCoder
{
public:
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
HRESULT WriteHeader(ISequentialOutStream *outStream);
HRESULT WriteFooter(ISequentialOutStream *outStream);
};
class CDecoder:
public CBaseCoder
// public ICompressSetDecoderProperties2
{
Byte _pwdVerifFromArchive[kPwdVerifSize];
public:
// ICompressSetDecoderProperties2
// STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
HRESULT ReadHeader(ISequentialInStream *inStream);
bool Init_and_CheckPassword();
HRESULT CheckMac(ISequentialInStream *inStream, bool &isOK);
};
}}
#endif
|