{"record":{"id":"9cbea1230750e9ee","repo":"digininja/DVWA","slug":"iv-must-be-12-bytes-strlen-iv-passed","errorCode":null,"errorMessage":"IV must be 12 bytes, {strlen($iv)} passed","messagePattern":"IV must be 12 bytes, (.+?) passed","errorType":"exception","errorClass":"Exception","httpStatus":526,"severity":"error","filePath":"vulnerabilities/cryptography/source/token_library_impossible.php","lineNumber":23,"sourceCode":"\nfunction encrypt ($plaintext, $iv) {\n\t# Default padding is PKCS#7 which is interchangeable with PKCS#5\n\t# https://en.wikipedia.org/wiki/Padding_%28cryptography%29#PKCS#5_and_PKCS#7\n\n\tif (strlen ($iv) != 12) {\n\t\tthrow new Exception (\"IV must be 12 bytes, \" . strlen ($iv) . \" passed\");\n\t}\n\n\t$e = openssl_encrypt($plaintext, ALGO, KEY, OPENSSL_RAW_DATA, $iv, $tag);\n\tif ($e === false) {\n\t\tthrow new Exception (\"Encryption failed\");\n\t}\n\treturn $e . $tag;\n}\n\nfunction decrypt ($ciphertext, $iv) {\n\tif (strlen ($iv) != 12) {\n\t\tthrow new Exception (\"IV must be 12 bytes, \" . strlen ($iv) . \" passed\");\n\t}\n\n    $tag = substr($ciphertext, -16);\n\t$text = substr($ciphertext, 0, -16);\n\n\t$e = openssl_decrypt($text, ALGO, KEY, OPENSSL_RAW_DATA, $iv, $tag);\n\tif ($e === false) {\n\t\tthrow new Exception (\"Decryption failed\");\n\t}\n\treturn $e;\n}\n\n// Added the debug flag so that when calling from the script\n// the function can print the data used to create the token\n\nfunction create_token () {\n\t$token = \"userid:2\";\n\t$iv = openssl_random_pseudo_bytes(12, $cstrong);","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/digininja/DVWA/blob/5d5c76cced604e54462b13723f5c69af58e78748/vulnerabilities/cryptography/source/token_library_impossible.php#L5-L41","documentation":"decrypt() in the impossible-level token library enforces a 12-byte IV, the recommended nonce size for aes-256-gcm; encrypt() (line 11) applies the same guard. The token JSON carries the nonce base64-encoded in its iv field, and any decoded length other than 12 throws with the actual length in the message.","triggerScenarios":"Copying the 16-byte CBC IV (\"MTIzNDU2NzgxMjM0NTY3OA==\") from the high-level library into a GCM token; hand-built iv strings of the wrong size; base64_decode of URL-safe (-, _) or whitespace-damaged input; generating nonces with random_bytes(16) instead of 12.","commonSituations":"Migrating CBC code to GCM without changing the IV length; mixing token libraries between DVWA security levels; interop with stacks whose examples default to 16-byte nonces; non-strict base64 decoding of user input.","solutions":["Use base64 of exactly 12 random bytes - openssl_random_pseudo_bytes(12) as create_token() does.","Leave the issued token's iv field untouched when only modifying other parts.","Never mix this library's tokens with the CBC library's 16-byte IVs.","Pre-validate strlen($iv) === 12 (and strict base64_decode) before calling decrypt()."],"exampleFix":"// before\n$iv = openssl_random_pseudo_bytes(16);\n// after\n$iv = openssl_random_pseudo_bytes(12);","handlingStrategy":"validation","validationCode":"$iv = base64_decode($data_array['iv'], true);\nif ($iv === false || strlen($iv) !== 12) {\n    // reject before decrypt() can throw\n    return json_encode(['status' => 524, 'message' => 'IV must be 12 bytes']);\n}","typeGuard":"function isValidGcmNonce(string $iv): bool\n{\n    return strlen($iv) === 12;\n}","tryCatchPattern":"try {\n    $d = decrypt($ciphertext, $iv);\n} catch (Exception $e) {\n    if (str_starts_with($e->getMessage(), 'IV must be 12 bytes')) {\n        $ret = ['status' => 524, 'message' => 'Missing or malformed IV'];\n    } else {\n        $ret = ['status' => 526, 'message' => 'Unable to decrypt token'];\n    }\n}","preventionTips":["Derive the nonce length from the cipher (12 for GCM, 16 for CBC) instead of hard-coding per call site.","Always base64_decode(..., true) so malformed input fails deterministically.","Never reuse a nonce across tokens with the same key - GCM nonce reuse is catastrophic."],"tags":["php","openssl","aes-256-gcm","iv","nonce","cryptography","dvwa"],"backgroundTag":"invalid-iv-length","analyzedSha":"5d5c76cced604e54462b13723f5c69af58e78748","analyzedAt":"2026-08-21T01:20:26.904Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}