@@ -315,3 +315,59 @@ func TestComputeV5KeyRejectsShortEntries(t *testing.T) {
315315 })
316316 }
317317}
318+
319+ // Owner-password path. Unlike the user path, the owner hash mixes in the
320+ // 48-byte /U entry (§7.6.4.4.10) — so userEntry here must be well-formed.
321+ func TestComputeV5KeyOwnerPath (t * testing.T ) {
322+ const R = 6
323+ password := []byte ("owner-pw" )
324+ fileKey := bytes .Repeat ([]byte {0x37 }, 32 )
325+
326+ // All-zero validation hash (first 32 bytes) can never equal v5Hash output,
327+ // forcing the user path to miss so the owner path is taken.
328+ uVS := bytes .Repeat ([]byte {0x11 }, 8 )
329+ uKS := bytes .Repeat ([]byte {0x22 }, 8 )
330+ userEntry := append (append (make ([]byte , 32 ), uVS ... ), uKS ... ) // 48 bytes
331+
332+ oVS := bytes .Repeat ([]byte {0x33 }, 8 )
333+ oKS := bytes .Repeat ([]byte {0x44 }, 8 )
334+ oValHash , err := v5Hash (password , oVS , userEntry , R )
335+ if err != nil {
336+ t .Fatalf ("v5Hash(owner validation): %v" , err )
337+ }
338+ oKeyHash , err := v5Hash (password , oKS , userEntry , R )
339+ if err != nil {
340+ t .Fatalf ("v5Hash(owner key): %v" , err )
341+ }
342+ oe := aesCBCEncryptRaw (t , oKeyHash , make ([]byte , aes .BlockSize ), fileKey )
343+ ownerEntry := append (append (append ([]byte {}, oValHash ... ), oVS ... ), oKS ... )
344+
345+ p := Params {
346+ V : 5 , R : R ,
347+ UserEntry : userEntry ,
348+ OwnerEntry : ownerEntry ,
349+ UE : make ([]byte , 32 ), // present but never reached
350+ OE : oe ,
351+ }
352+ key , err := computeV5Key (p , password )
353+ if err != nil {
354+ t .Fatalf ("computeV5Key: %v" , err )
355+ }
356+ if ! bytes .Equal (key , fileKey ) {
357+ t .Fatalf ("owner-path key mismatch:\n got %x\n want %x" , key , fileKey )
358+ }
359+ }
360+
361+ func TestComputeV5KeyWrongPassword (t * testing.T ) {
362+ p := Params {
363+ V : 5 , R : 6 ,
364+ UserEntry : bytes .Repeat ([]byte {0x01 }, 48 ),
365+ OwnerEntry : bytes .Repeat ([]byte {0x02 }, 48 ),
366+ UE : bytes .Repeat ([]byte {0x03 }, 32 ),
367+ OE : bytes .Repeat ([]byte {0x04 }, 32 ),
368+ }
369+ overlong := bytes .Repeat ([]byte {'z' }, 200 ) // > 127: exercises the spec truncation
370+ if _ , err := computeV5Key (p , overlong ); err == nil {
371+ t .Fatal ("expected an error for a non-matching password, got nil" )
372+ }
373+ }
0 commit comments