mirror of https://github.com/qpdf/qpdf.git
In json mode, reveal recovered user password when otherwise unavailable
This commit is contained in:
parent
f049a77c59
commit
b7bbf12e85
|
@ -1,5 +1,10 @@
|
||||||
2022-05-30 Jay Berkenbilt <ejb@ql.org>
|
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
|
* Include additional information in --list-attachments --verbose
|
||||||
and in --json --json-key=attachments.
|
and in --json --json-key=attachments.
|
||||||
|
|
||||||
|
|
2
TODO
2
TODO
|
@ -70,8 +70,6 @@ Remaining work:
|
||||||
|
|
||||||
* --show-xref: add
|
* --show-xref: add
|
||||||
|
|
||||||
* --encryption: show recovered user password when available
|
|
||||||
|
|
||||||
* Consider having --check, --show-encryption, etc., just select the
|
* Consider having --check, --show-encryption, etc., just select the
|
||||||
right keys when in json mode. I don't think I want check on by
|
right keys when in json mode. I don't think I want check on by
|
||||||
default, so that might be different.
|
default, so that might be different.
|
||||||
|
|
|
@ -1382,6 +1382,15 @@ QPDFJob::doJSONEncrypt(Pipeline* p, bool& first, QPDF& pdf)
|
||||||
j_encrypt.addDictionaryMember(
|
j_encrypt.addDictionaryMember(
|
||||||
"ownerpasswordmatched",
|
"ownerpasswordmatched",
|
||||||
JSON::makeBool(is_encrypted && pdf.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 =
|
JSON j_capabilities =
|
||||||
j_encrypt.addDictionaryMember("capabilities", JSON::makeDictionary());
|
j_encrypt.addDictionaryMember("capabilities", JSON::makeDictionary());
|
||||||
j_capabilities.addDictionaryMember(
|
j_capabilities.addDictionaryMember(
|
||||||
|
@ -1669,6 +1678,7 @@ QPDFJob::json_schema(int json_version, std::set<std::string>* keys)
|
||||||
},
|
},
|
||||||
"encrypted": "whether the document is encrypted",
|
"encrypted": "whether the document is encrypted",
|
||||||
"ownerpasswordmatched": "whether supplied password matched owner password; always false for non-encrypted files",
|
"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": {
|
"parameters": {
|
||||||
"P": "P value from Encrypt dictionary",
|
"P": "P value from Encrypt dictionary",
|
||||||
"R": "R value from Encrypt dictionary",
|
"R": "R value from Encrypt dictionary",
|
||||||
|
|
|
@ -103,6 +103,12 @@ For a detailed list of changes, please see the file
|
||||||
attachments is also included in the ``attachments`` json key
|
attachments is also included in the ``attachments`` json key
|
||||||
with ``--json``.
|
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
|
- Library Enhancements
|
||||||
|
|
||||||
- New methods ``insertItemAndGet``, ``appendItemAndGet``,
|
- New methods ``insertItemAndGet``, ``appendItemAndGet``,
|
||||||
|
|
|
@ -219,6 +219,7 @@ foreach my $d (@encrypted_files)
|
||||||
" \"streammethod\": \"---method---\",\n" .
|
" \"streammethod\": \"---method---\",\n" .
|
||||||
" \"stringmethod\": \"---method---\"\n" .
|
" \"stringmethod\": \"---method---\"\n" .
|
||||||
" },\n" .
|
" },\n" .
|
||||||
|
" \"recovereduserpassword\": ---rup---,\n" .
|
||||||
" \"userpasswordmatched\": ---upm---\n" .
|
" \"userpasswordmatched\": ---upm---\n" .
|
||||||
" }\n" .
|
" }\n" .
|
||||||
"}\n";
|
"}\n";
|
||||||
|
@ -267,6 +268,8 @@ foreach my $d (@encrypted_files)
|
||||||
my $method = $bits == 256 ? "AESv3" : "RC4";
|
my $method = $bits == 256 ? "AESv3" : "RC4";
|
||||||
my $opm = ($pass eq $opass ? "true" : "false");
|
my $opm = ($pass eq $opass ? "true" : "false");
|
||||||
my $upm = ($pass eq $upass ? "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/---R---/$R/;
|
||||||
$enc_json =~ s/---P---/$P/;
|
$enc_json =~ s/---P---/$P/;
|
||||||
$enc_json =~ s/---V---/$V/;
|
$enc_json =~ s/---V---/$V/;
|
||||||
|
@ -274,6 +277,7 @@ foreach my $d (@encrypted_files)
|
||||||
$enc_json =~ s/---method---/$method/g;
|
$enc_json =~ s/---method---/$method/g;
|
||||||
$enc_json =~ s/---opm---/$opm/;
|
$enc_json =~ s/---opm---/$opm/;
|
||||||
$enc_json =~ s/---upm---/$upm/;
|
$enc_json =~ s/---upm---/$upm/;
|
||||||
|
$enc_json =~ s/---rup---/$rup/;
|
||||||
|
|
||||||
my $eflags = "--allow-weak-crypto" .
|
my $eflags = "--allow-weak-crypto" .
|
||||||
" -encrypt \"$upass\" \"$opass\" $bits $xeflags --";
|
" -encrypt \"$upass\" \"$opass\" $bits $xeflags --";
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"streammethod": "AESv2",
|
"streammethod": "AESv2",
|
||||||
"stringmethod": "AESv2"
|
"stringmethod": "AESv2"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": true
|
"userpasswordmatched": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"streammethod": "AESv2",
|
"streammethod": "AESv2",
|
||||||
"stringmethod": "AESv2"
|
"stringmethod": "AESv2"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": true
|
"userpasswordmatched": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"streammethod": "AESv2",
|
"streammethod": "AESv2",
|
||||||
"stringmethod": "AESv2"
|
"stringmethod": "AESv2"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": true
|
"userpasswordmatched": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"streammethod": "AESv2",
|
"streammethod": "AESv2",
|
||||||
"stringmethod": "AESv2"
|
"stringmethod": "AESv2"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": true
|
"userpasswordmatched": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -428,6 +428,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -428,6 +428,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -428,6 +428,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -428,6 +428,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -271,6 +271,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -271,6 +271,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -271,6 +271,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -271,6 +271,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -271,6 +271,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -271,6 +271,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -271,6 +271,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -271,6 +271,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -462,6 +462,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [
|
"outlines": [
|
||||||
|
|
|
@ -462,6 +462,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [
|
"outlines": [
|
||||||
|
|
|
@ -567,6 +567,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [
|
"outlines": [
|
||||||
|
|
|
@ -567,6 +567,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [
|
"outlines": [
|
||||||
|
|
|
@ -637,6 +637,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [
|
"outlines": [
|
||||||
|
|
|
@ -637,6 +637,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [
|
"outlines": [
|
||||||
|
|
|
@ -534,6 +534,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
|
@ -534,6 +534,7 @@
|
||||||
"streammethod": "none",
|
"streammethod": "none",
|
||||||
"stringmethod": "none"
|
"stringmethod": "none"
|
||||||
},
|
},
|
||||||
|
"recovereduserpassword": null,
|
||||||
"userpasswordmatched": false
|
"userpasswordmatched": false
|
||||||
},
|
},
|
||||||
"outlines": [],
|
"outlines": [],
|
||||||
|
|
Loading…
Reference in New Issue