@@ -213,14 +213,17 @@ private function getProtection()
213
213
)
214
214
);
215
215
} else {
216
+ if ($ protection ->getSalt () == null ) {
217
+ $ protection ->setSalt (openssl_random_pseudo_bytes (16 ));
218
+ }
216
219
$ this ->settings ['w:documentProtection ' ] = array (
217
220
'@attributes ' => array (
218
221
'w:enforcement ' => 1 ,
219
222
'w:edit ' => $ protection ->getEditing (),
220
223
'w:cryptProviderType ' => 'rsaFull ' ,
221
224
'w:cryptAlgorithmClass ' => 'hash ' ,
222
225
'w:cryptAlgorithmType ' => 'typeAny ' ,
223
- 'w:cryptAlgorithmSid ' => $ protection ->getAlgorithmSid (),
226
+ 'w:cryptAlgorithmSid ' => $ protection ->getMswordAlgorithmSid (),
224
227
'w:cryptSpinCount ' => $ protection ->getSpinCount (),
225
228
'w:hash ' => $ this ->getPasswordHash ($ protection ),
226
229
'w:salt ' => $ this ->getSaltHash ($ protection ->getSalt ()),
@@ -239,11 +242,13 @@ private function getCompatibility()
239
242
{
240
243
$ compatibility = $ this ->getParentWriter ()->getPhpWord ()->getCompatibility ();
241
244
if ($ compatibility ->getOoxmlVersion () !== null ) {
242
- $ this ->settings ['w:compat ' ]['w:compatSetting ' ] = array ('@attributes ' => array (
243
- 'w:name ' => 'compatibilityMode ' ,
244
- 'w:uri ' => 'http://schemas.microsoft.com/office/word ' ,
245
- 'w:val ' => $ compatibility ->getOoxmlVersion (),
246
- ));
245
+ $ this ->settings ['w:compat ' ]['w:compatSetting ' ] = array (
246
+ '@attributes ' => array (
247
+ 'w:name ' => 'compatibilityMode ' ,
248
+ 'w:uri ' => 'http://schemas.microsoft.com/office/word ' ,
249
+ 'w:val ' => $ compatibility ->getOoxmlVersion (),
250
+ )
251
+ );
247
252
}
248
253
}
249
254
@@ -277,21 +282,19 @@ private function getPasswordHash($protection)
277
282
// build low-order word and hig-order word and combine them
278
283
$ combinedKey = $ this ->buildCombinedKey ($ byteChars );
279
284
// build reversed hexadecimal string
280
- $ hex = strtoupper (dechex ($ combinedKey & 0xFFFFFFFF ));
281
- $ reversedHex = $ hex [6 ]. $ hex [7 ]. $ hex [4 ]. $ hex [5 ]. $ hex [2 ]. $ hex [3 ]. $ hex [0 ]. $ hex [1 ];
285
+ $ hex = strtoupper (dechex ($ combinedKey & 0xFFFFFFFF ));
286
+ $ reversedHex = $ hex [6 ] . $ hex [7 ] . $ hex [4 ] . $ hex [5 ] . $ hex [2 ] . $ hex [3 ] . $ hex [0 ] . $ hex [1 ];
282
287
283
288
$ generatedKey = mb_convert_encoding ($ reversedHex , 'UCS-2LE ' , 'UTF-8 ' );
284
289
285
290
// Implementation Notes List:
286
291
// Word requires that the initial hash of the password with the salt not be considered in the count.
287
292
// The initial hash of salt + key is not included in the iteration count.
288
- $ algorithm = $ this ->getAlgorithm ($ protection ->getAlgorithmSid ());
293
+ $ algorithm = $ this ->getAlgorithm ($ protection ->getMswordAlgorithmSid ());
289
294
$ generatedKey = hash ($ algorithm , base64_decode ($ this ->getSaltHash ($ protection ->getSalt ())) . $ generatedKey , true );
290
295
291
- $ spinCount = (!empty ($ protection ->getSpinCount ())) ? $ protection ->getSpinCount () : 100000 ;
292
-
293
- for ($ i = 0 ; $ i < $ spinCount ; $ i ++) {
294
- $ generatedKey = hash ($ algorithm , $ generatedKey . pack ("CCCC " , $ i , $ i >>8 , $ i >>16 , $ i >>24 ), true );
296
+ for ($ i = 0 ; $ i < $ protection ->getSpinCount (); $ i ++) {
297
+ $ generatedKey = hash ($ algorithm , $ generatedKey . pack ("CCCC " , $ i , $ i >> 8 , $ i >> 16 , $ i >> 24 ), true );
295
298
}
296
299
$ generatedKey = base64_encode ($ generatedKey );
297
300
@@ -308,10 +311,6 @@ private function getPasswordHash($protection)
308
311
*/
309
312
private function getAlgorithm ($ sid )
310
313
{
311
- if (empty ($ sid )) {
312
- $ sid = 4 ;
313
- }
314
-
315
314
$ algorithm = self ::$ algorithmMapping [$ sid ];
316
315
if ($ algorithm == '' ) {
317
316
$ algorithm = 'sha1 ' ;
@@ -328,7 +327,7 @@ private function getAlgorithm($sid)
328
327
*/
329
328
private function getSaltHash ($ salt )
330
329
{
331
- return $ salt ;
330
+ return base64_encode ( str_pad ( substr ( $ salt, 0 , 16 ), 16 , ' 1 ' )) ;
332
331
}
333
332
334
333
/**
0 commit comments