@@ -8,6 +8,15 @@ module AdminAuth
88 # a hard-coded user agent when we're pre-seeding the session cookie value.
99 STATIC_USER_AGENT = "TestStaticUserAgent" . freeze
1010
11+ # lua-resty-session v4 binary header layout constants.
12+ # Header is 82 bytes: [1B type][2B flags][32B sid][5B creation_time]
13+ # [4B rolling_offset][3B data_size][16B tag][3B idling_offset][16B mac]
14+ V4_HEADER_SIZE = 82
15+ V4_HEADER_SID_OFFSET = 3
16+ V4_HEADER_SID_SIZE = 32
17+ V4_HEADER_PRE_TAG_SIZE = 47 # bytes before AES-GCM tag
18+ V4_HEADER_TAG_SIZE = 16
19+
1120 include ApiUmbrellaTestHelpers ::Selenium
1221
1322 def admin_login ( admin = nil )
@@ -333,7 +342,7 @@ def decrypt_session_cookie(cookie_value)
333342 # In v4, the DB-backed cookie is just the base64url-encoded header.
334343 # Extract the SID from the header to look up the DB record.
335344 header = session_base64_decode ( cookie_value )
336- sid = header [ 3 , 32 ]
345+ sid = header [ V4_HEADER_SID_OFFSET , V4_HEADER_SID_SIZE ]
337346 sid_encoded = session_base64_encode ( sid )
338347
339348 session = Session . find_by ( :sid => sid_encoded )
@@ -348,9 +357,9 @@ def decrypt_session_cookie(cookie_value)
348357 aes_key = sid_key [ 0 , 32 ]
349358 iv = sid_key [ 32 , 12 ]
350359
351- # The AAD is the first 47 bytes of the header ( before the tag)
352- aad = header [ 0 , 47 ]
353- tag = header [ 47 , 16 ]
360+ # The AAD is the bytes before the AES-GCM tag
361+ aad = header [ 0 , V4_HEADER_PRE_TAG_SIZE ]
362+ tag = header [ V4_HEADER_PRE_TAG_SIZE , V4_HEADER_TAG_SIZE ]
354363
355364 decipher = OpenSSL ::Cipher . new ( "aes-256-gcm" )
356365 decipher . decrypt
@@ -377,24 +386,24 @@ def encrypt_session_client_cookie(data)
377386
378387 def decrypt_session_client_cookie ( cookie_value )
379388 # The cookie value is base64url(header) + base64url(ciphertext).
380- # The header is always 82 bytes raw = 110 base64url chars (ceil(82*4/3) with no padding) .
381- header_b64_len = ( ( 82 * 4 + 2 ) / 3.0 ) . ceil
389+ # The header is always V4_HEADER_SIZE bytes raw.
390+ header_b64_len = ( ( V4_HEADER_SIZE * 4 + 2 ) / 3.0 ) . ceil
382391 header_b64 = cookie_value [ 0 , header_b64_len ]
383392 ciphertext_b64 = cookie_value [ header_b64_len ..]
384393
385394 header = session_base64_decode ( header_b64 )
386395 ciphertext = session_base64_decode ( ciphertext_b64 )
387- sid = header [ 3 , 32 ]
396+ sid = header [ V4_HEADER_SID_OFFSET , V4_HEADER_SID_SIZE ]
388397
389398 # Derive the decryption key from the SID
390399 ikm = Digest ::SHA256 . digest ( $config[ "secret_key" ] )
391400 sid_key = OpenSSL ::KDF . hkdf ( ikm , salt : "" , info : "encryption:#{ sid } " , length : 44 , hash : "SHA256" )
392401 aes_key = sid_key [ 0 , 32 ]
393402 iv = sid_key [ 32 , 12 ]
394403
395- # The AAD is the first 47 bytes of the header ( before the tag)
396- aad = header [ 0 , 47 ]
397- tag = header [ 47 , 16 ]
404+ # The AAD is the bytes before the AES-GCM tag
405+ aad = header [ 0 , V4_HEADER_PRE_TAG_SIZE ]
406+ tag = header [ V4_HEADER_PRE_TAG_SIZE , V4_HEADER_TAG_SIZE ]
398407
399408 decipher = OpenSSL ::Cipher . new ( "aes-256-gcm" )
400409 decipher . decrypt
0 commit comments