1
1
using System ;
2
2
using System . IO ;
3
3
using System . Security . Cryptography ;
4
+ using ICSharpCode . SharpZipLib . Encryption ;
4
5
5
6
namespace ICSharpCode . SharpZipLib . Zip . Compression . Streams
6
7
{
@@ -92,9 +93,25 @@ public byte[] ClearText
92
93
public int Available
93
94
{
94
95
get { return available ; }
95
- set { available = value ; }
96
+ set
97
+ {
98
+ if ( cryptoTransform is ZipAESTransform ct )
99
+ {
100
+ ct . AppendFinal ( value ) ;
101
+ }
102
+
103
+ available = value ;
104
+ }
96
105
}
97
106
107
+ /// <summary>
108
+ /// A limitation how much data is decrypted. If null all the data in the input buffer will be decrypted.
109
+ /// Setting limit is important in case the HMAC has to be calculated for each zip entry. In that case
110
+ /// it is not possible to decrypt all available data in the input buffer, and only the data
111
+ /// belonging to the current zip entry must be decrypted so that the HMAC is correctly calculated.
112
+ /// </summary>
113
+ internal int ? DecryptionLimit { get ; set ; }
114
+
98
115
/// <summary>
99
116
/// Call <see cref="Inflater.SetInput(byte[], int, int)"/> passing the current clear text buffer contents.
100
117
/// </summary>
@@ -113,6 +130,11 @@ public void SetInflaterInput(Inflater inflater)
113
130
/// </summary>
114
131
public void Fill ( )
115
132
{
133
+ if ( cryptoTransform is ZipAESTransform ct )
134
+ {
135
+ ct . AppendAllPending ( ) ;
136
+ }
137
+
116
138
rawLength = 0 ;
117
139
int toRead = rawData . Length ;
118
140
@@ -127,13 +149,11 @@ public void Fill()
127
149
toRead -= count ;
128
150
}
129
151
152
+ clearTextLength = rawLength ;
130
153
if ( cryptoTransform != null )
131
154
{
132
- clearTextLength = cryptoTransform . TransformBlock ( rawData , 0 , rawLength , clearText , 0 ) ;
133
- }
134
- else
135
- {
136
- clearTextLength = rawLength ;
155
+ var size = CalculateDecryptionSize ( rawLength ) ;
156
+ cryptoTransform . TransformBlock ( rawData , 0 , size , clearText , 0 ) ;
137
157
}
138
158
139
159
available = clearTextLength ;
@@ -290,7 +310,9 @@ public ICryptoTransform CryptoTransform
290
310
clearTextLength = rawLength ;
291
311
if ( available > 0 )
292
312
{
293
- cryptoTransform . TransformBlock ( rawData , rawLength - available , available , clearText , rawLength - available ) ;
313
+ var size = CalculateDecryptionSize ( available ) ;
314
+
315
+ cryptoTransform . TransformBlock ( rawData , rawLength - available , size , clearText , rawLength - available ) ;
294
316
}
295
317
}
296
318
else
@@ -301,6 +323,19 @@ public ICryptoTransform CryptoTransform
301
323
}
302
324
}
303
325
326
+ private int CalculateDecryptionSize ( int availableBufferSize )
327
+ {
328
+ int size = DecryptionLimit ?? availableBufferSize ;
329
+ size = Math . Min ( size , availableBufferSize ) ;
330
+
331
+ if ( DecryptionLimit . HasValue )
332
+ {
333
+ DecryptionLimit -= size ;
334
+ }
335
+
336
+ return size ;
337
+ }
338
+
304
339
#region Instance Fields
305
340
306
341
private int rawLength ;
@@ -459,9 +494,10 @@ public long Skip(long count)
459
494
/// <summary>
460
495
/// Clear any cryptographic state.
461
496
/// </summary>
462
- protected void StopDecrypting ( )
497
+ protected virtual void StopDecrypting ( )
463
498
{
464
499
inputBuffer . CryptoTransform = null ;
500
+ inputBuffer . DecryptionLimit = null ;
465
501
}
466
502
467
503
/// <summary>
0 commit comments