In json mode, reveal recovered user password when otherwise unavailable

This commit is contained in:
Jay Berkenbilt 2022-05-30 10:55:07 -04:00
parent f049a77c59
commit b7bbf12e85
31 changed files with 51 additions and 2 deletions

View File

@ -1,5 +1,10 @@
2022-05-30 Jay Berkenbilt <ejb@ql.org>
* When showing encryption data in json output, when the user
password was recovered with by the owner password and the
specified password does not match the user password, reveal the
user password. This is not possible with 256-bit keys.
* Include additional information in --list-attachments --verbose
and in --json --json-key=attachments.

2
TODO
View File

@ -70,8 +70,6 @@ Remaining work:
* --show-xref: add
* --encryption: show recovered user password when available
* Consider having --check, --show-encryption, etc., just select the
right keys when in json mode. I don't think I want check on by
default, so that might be different.

View File

@ -1382,6 +1382,15 @@ QPDFJob::doJSONEncrypt(Pipeline* p, bool& first, QPDF& pdf)
j_encrypt.addDictionaryMember(
"ownerpasswordmatched",
JSON::makeBool(is_encrypted && pdf.ownerPasswordMatched()));
if (is_encrypted && (V < 5) && pdf.ownerPasswordMatched() &&
(!pdf.userPasswordMatched())) {
std::string user_password = pdf.getTrimmedUserPassword();
j_encrypt.addDictionaryMember(
"recovereduserpassword", JSON::makeString(user_password));
} else {
j_encrypt.addDictionaryMember(
"recovereduserpassword", JSON::makeNull());
}
JSON j_capabilities =
j_encrypt.addDictionaryMember("capabilities", JSON::makeDictionary());
j_capabilities.addDictionaryMember(
@ -1669,6 +1678,7 @@ QPDFJob::json_schema(int json_version, std::set<std::string>* keys)
},
"encrypted": "whether the document is encrypted",
"ownerpasswordmatched": "whether supplied password matched owner password; always false for non-encrypted files",
"recovereduserpassword": "If the owner password was used to recover the user password, reveal user password; otherwise null",
"parameters": {
"P": "P value from Encrypt dictionary",
"R": "R value from Encrypt dictionary",

View File

@ -103,6 +103,12 @@ For a detailed list of changes, please see the file
attachments is also included in the ``attachments`` json key
with ``--json``.
- For encrypted files, ``qpdf --json`` reveals the user password
when the specified password did not match the user password and
the owner password was used to recover the user password. The
user password is not recoverable from the owner password when
256-bit keys are in use.
- Library Enhancements
- New methods ``insertItemAndGet``, ``appendItemAndGet``,

View File

@ -219,6 +219,7 @@ foreach my $d (@encrypted_files)
" \"streammethod\": \"---method---\",\n" .
" \"stringmethod\": \"---method---\"\n" .
" },\n" .
" \"recovereduserpassword\": ---rup---,\n" .
" \"userpasswordmatched\": ---upm---\n" .
" }\n" .
"}\n";
@ -267,6 +268,8 @@ foreach my $d (@encrypted_files)
my $method = $bits == 256 ? "AESv3" : "RC4";
my $opm = ($pass eq $opass ? "true" : "false");
my $upm = ($pass eq $upass ? "true" : "false");
my $rup = (($pass eq $opass) && ($pass ne $upass) && ($V < 5))
? "\"$upass\"" : "null";
$enc_json =~ s/---R---/$R/;
$enc_json =~ s/---P---/$P/;
$enc_json =~ s/---V---/$V/;
@ -274,6 +277,7 @@ foreach my $d (@encrypted_files)
$enc_json =~ s/---method---/$method/g;
$enc_json =~ s/---opm---/$opm/;
$enc_json =~ s/---upm---/$upm/;
$enc_json =~ s/---rup---/$rup/;
my $eflags = "--allow-weak-crypto" .
" -encrypt \"$upass\" \"$opass\" $bits $xeflags --";

View File

@ -28,6 +28,7 @@
"streammethod": "AESv2",
"stringmethod": "AESv2"
},
"recovereduserpassword": null,
"userpasswordmatched": true
}
}

View File

@ -28,6 +28,7 @@
"streammethod": "AESv2",
"stringmethod": "AESv2"
},
"recovereduserpassword": null,
"userpasswordmatched": true
}
}

View File

@ -28,6 +28,7 @@
"streammethod": "AESv2",
"stringmethod": "AESv2"
},
"recovereduserpassword": null,
"userpasswordmatched": true
}
}

View File

@ -28,6 +28,7 @@
"streammethod": "AESv2",
"stringmethod": "AESv2"
},
"recovereduserpassword": null,
"userpasswordmatched": true
}
}

View File

@ -96,6 +96,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -96,6 +96,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -428,6 +428,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -428,6 +428,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -428,6 +428,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -428,6 +428,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -271,6 +271,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -271,6 +271,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -271,6 +271,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -271,6 +271,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -271,6 +271,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -271,6 +271,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -271,6 +271,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -271,6 +271,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -462,6 +462,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [

View File

@ -462,6 +462,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [

View File

@ -567,6 +567,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [

View File

@ -567,6 +567,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [

View File

@ -637,6 +637,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [

View File

@ -637,6 +637,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [

View File

@ -534,6 +534,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],

View File

@ -534,6 +534,7 @@
"streammethod": "none",
"stringmethod": "none"
},
"recovereduserpassword": null,
"userpasswordmatched": false
},
"outlines": [],