@@ -77,7 +77,13 @@ def decode_stream_header(header: bytes) -> int:
7777
7878
7979def calculate_plaintext_length (encrypted_length : int ) -> int :
80- """Return the plaintext length of an AGS1 stream that occupies `encrypted_length` bytes."""
80+ """Return the plaintext length of an AGS1 stream that occupies `encrypted_length` bytes.
81+
82+ Args:
83+ encrypted_length (int): The stream's length, which must be the trusted `file_length` from the file's
84+ `StandardKeyMetadata`, never a file system stat. The spec requires the trusted length because a
85+ stat lets an attacker drop trailing blocks while every remaining block still authenticates.
86+ """
8187 if encrypted_length < GCM_STREAM_HEADER_LENGTH :
8288 raise ValueError (f"Invalid AGS1 stream: expected at least { GCM_STREAM_HEADER_LENGTH } bytes, got { encrypted_length } " )
8389
@@ -99,7 +105,7 @@ def calculate_plaintext_length(encrypted_length: int) -> int:
99105
100106@dataclass (frozen = True )
101107class Ags1Layout :
102- """Where each block of an AGS1 stream sits, derived from the encrypted file length.
108+ """Where each block of an AGS1 stream sits, derived from the trusted encrypted file length.
103109
104110 Only the final block may hold less than `PLAIN_BLOCK_SIZE` of plaintext, so the layout
105111 follows from the encrypted length alone, without reading the stream.
@@ -111,7 +117,12 @@ class Ags1Layout:
111117
112118 @classmethod
113119 def from_encrypted_length (cls , encrypted_length : int ) -> Ags1Layout :
114- """Derive the layout of an AGS1 stream that occupies `encrypted_length` bytes."""
120+ """Derive the layout of an AGS1 stream that occupies `encrypted_length` bytes.
121+
122+ Args:
123+ encrypted_length (int): The stream's length, which must be the trusted `file_length` from the file's
124+ `StandardKeyMetadata`, never a file system stat. See `calculate_plaintext_length`.
125+ """
115126 plaintext_length = calculate_plaintext_length (encrypted_length )
116127 stream_length = encrypted_length - GCM_STREAM_HEADER_LENGTH
117128 if stream_length == 0 :
0 commit comments