2
1
mirror of https://github.com/qpdf/qpdf.git synced 2025-02-02 11:58:25 +00:00

add C API for R4 encryption

git-svn-id: svn+q:///qpdf/trunk@825 71b93d88-0707-0410-a8cf-f5a4172ac649
This commit is contained in:
Jay Berkenbilt 2009-10-19 00:36:51 +00:00
parent 09175e4578
commit a8715c495b
11 changed files with 107 additions and 2 deletions

View File

@ -110,6 +110,11 @@ class DLL_EXPORT QPDFWriter
// suites. // suites.
void setStaticID(bool); void setStaticID(bool);
// Use a fixed initialization vector for AES-CBC encryption. This
// is not secure. It should be used only in test suites for
// creating predictable encrypted output.
void setStaticAesIV(bool);
// Suppress inclusion of comments indicating original object IDs // Suppress inclusion of comments indicating original object IDs
// when writing QDF files. This can also be useful for testing, // when writing QDF files. This can also be useful for testing,
// particularly when using comparison of two qdf files to // particularly when using comparison of two qdf files to

View File

@ -226,6 +226,12 @@ extern "C" {
DLL_EXPORT DLL_EXPORT
void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value); void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value);
/* Never use qpdf_set_static_aes_IV except in test suites to
* create predictable AES encrypted output.
*/
DLL_EXPORT
void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value);
DLL_EXPORT DLL_EXPORT
void qpdf_set_suppress_original_object_IDs( void qpdf_set_suppress_original_object_IDs(
qpdf_data qpdf, QPDF_BOOL value); qpdf_data qpdf, QPDF_BOOL value);
@ -258,6 +264,13 @@ extern "C" {
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract, QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
int print, int modify); int print, int modify);
DLL_EXPORT
void qpdf_set_r4_encryption_parameters(
qpdf_data qpdf, char const* user_password, char const* owner_password,
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
int print, int modify,
QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes);
DLL_EXPORT DLL_EXPORT
void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value); void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value);

View File

@ -12,6 +12,8 @@
# define srandom srand # define srandom srand
#endif #endif
bool Pl_AES_PDF::use_static_iv = false;
Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next,
bool encrypt, unsigned char const key[key_size]) : bool encrypt, unsigned char const key[key_size]) :
Pipeline(identifier, next), Pipeline(identifier, next),
@ -51,6 +53,12 @@ Pl_AES_PDF::disableCBC()
this->cbc_mode = false; this->cbc_mode = false;
} }
void
Pl_AES_PDF::useStaticIV()
{
use_static_iv = true;
}
void void
Pl_AES_PDF::write(unsigned char* data, int len) Pl_AES_PDF::write(unsigned char* data, int len)
{ {
@ -116,9 +124,19 @@ Pl_AES_PDF::initializeVector()
srandom((int)QUtil::get_current_time() ^ 0xcccc); srandom((int)QUtil::get_current_time() ^ 0xcccc);
seeded_random = true; seeded_random = true;
} }
for (unsigned int i = 0; i < this->buf_size; ++i) if (use_static_iv)
{ {
this->cbc_block[i] = (unsigned char)((random() & 0xff0) >> 4); for (unsigned int i = 0; i < this->buf_size; ++i)
{
this->cbc_block[i] = 14 * (1 + i);
}
}
else
{
for (unsigned int i = 0; i < this->buf_size; ++i)
{
this->cbc_block[i] = (unsigned char)((random() & 0xff0) >> 4);
}
} }
} }

View File

@ -139,6 +139,15 @@ QPDFWriter::setStaticID(bool val)
this->static_id = val; this->static_id = val;
} }
void
QPDFWriter::setStaticAesIV(bool val)
{
if (val)
{
Pl_AES_PDF::useStaticIV();
}
}
void void
QPDFWriter::setSuppressOriginalObjectIDs(bool val) QPDFWriter::setSuppressOriginalObjectIDs(bool val)
{ {

View File

@ -313,6 +313,12 @@ void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value)
qpdf->qpdf_writer->setStaticID(value); qpdf->qpdf_writer->setStaticID(value);
} }
void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value)
{
QTC::TC("qpdf", "qpdf-c called qpdf_set_static_aes_IV");
qpdf->qpdf_writer->setStaticAesIV(value);
}
void qpdf_set_suppress_original_object_IDs( void qpdf_set_suppress_original_object_IDs(
qpdf_data qpdf, QPDF_BOOL value) qpdf_data qpdf, QPDF_BOOL value)
{ {
@ -356,6 +362,26 @@ void qpdf_set_r3_encryption_parameters(
QPDFWriter::r3m_all)); QPDFWriter::r3m_all));
} }
void qpdf_set_r4_encryption_parameters(
qpdf_data qpdf, char const* user_password, char const* owner_password,
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
int print, int modify, QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes)
{
QTC::TC("qpdf", "qpdf-c called qpdf_set_r4_encryption_parameters");
qpdf->qpdf_writer->setR4EncryptionParameters(
user_password, owner_password,
allow_accessibility, allow_extract,
((print == QPDF_R3_PRINT_LOW) ? QPDFWriter::r3p_low :
(print == QPDF_R3_PRINT_NONE) ? QPDFWriter::r3p_none :
QPDFWriter::r3p_full),
((modify == QPDF_R3_MODIFY_ANNOTATE) ? QPDFWriter::r3m_annotate :
(modify == QPDF_R3_MODIFY_FORM) ? QPDFWriter::r3m_form :
(modify == QPDF_R3_MODIFY_ASSEMBLY) ? QPDFWriter::r3m_assembly :
(modify == QPDF_R3_MODIFY_NONE) ? QPDFWriter::r3m_none :
QPDFWriter::r3m_all),
encrypt_metadata, use_aes);
}
void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value) void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value)
{ {
QTC::TC("qpdf", "qpdf-c called qpdf_set_linearization"); QTC::TC("qpdf", "qpdf-c called qpdf_set_linearization");

View File

@ -20,12 +20,15 @@ class DLL_EXPORT Pl_AES_PDF: public Pipeline
// For testing only; PDF always uses CBC // For testing only; PDF always uses CBC
void disableCBC(); void disableCBC();
// For testing only: use a fixed initialization vector for CBC
static void useStaticIV();
private: private:
void flush(bool discard_padding); void flush(bool discard_padding);
void initializeVector(); void initializeVector();
static unsigned int const buf_size = 16; static unsigned int const buf_size = 16;
static bool use_static_iv;
bool encrypt; bool encrypt;
bool cbc_mode; bool cbc_mode;

View File

@ -229,6 +229,22 @@ static void test14(char const* infile,
report_errors(); report_errors();
} }
static void test15(char const* infile,
char const* password,
char const* outfile,
char const* outfile2)
{
qpdf_read(qpdf, infile, password);
qpdf_init_write(qpdf, outfile);
qpdf_set_static_ID(qpdf, QPDF_TRUE);
qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
qpdf_set_r4_encryption_parameters(
qpdf, "user2", "owner2", QPDF_TRUE, QPDF_TRUE,
QPDF_R3_PRINT_LOW, QPDF_R3_MODIFY_ALL, QPDF_TRUE, QPDF_TRUE);
qpdf_write(qpdf);
report_errors();
}
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
char* whoami = 0; char* whoami = 0;
@ -278,6 +294,7 @@ int main(int argc, char* argv[])
(n == 12) ? test12 : (n == 12) ? test12 :
(n == 13) ? test13 : (n == 13) ? test13 :
(n == 14) ? test14 : (n == 14) ? test14 :
(n == 15) ? test15 :
0); 0);
if (fn == 0) if (fn == 0)

View File

@ -146,6 +146,8 @@ These options can be useful for digging into PDF files or for use in\n\
automated test suites for software that uses the qpdf library.\n\ automated test suites for software that uses the qpdf library.\n\
\n\ \n\
--static-id generate static /ID: FOR TESTING ONLY!\n\ --static-id generate static /ID: FOR TESTING ONLY!\n\
--static-aes-iv use a static initialization vector for AES-CBC\n\
This is option is not secure! FOR TESTING ONLY!\n\
--no-original-object-ids suppress original object ID comments in qdf mode\n\ --no-original-object-ids suppress original object ID comments in qdf mode\n\
--show-encryption quickly show encryption parameters\n\ --show-encryption quickly show encryption parameters\n\
--check-linearization check file integrity and linearization status\n\ --check-linearization check file integrity and linearization status\n\
@ -604,6 +606,7 @@ int main(int argc, char* argv[])
std::string force_version; std::string force_version;
bool static_id = false; bool static_id = false;
bool static_aes_iv = false;
bool suppress_original_object_id = false; bool suppress_original_object_id = false;
bool show_encryption = false; bool show_encryption = false;
bool check_linearization = false; bool check_linearization = false;
@ -758,6 +761,10 @@ int main(int argc, char* argv[])
{ {
static_id = true; static_id = true;
} }
else if (strcmp(arg, "static-aes-iv") == 0)
{
static_aes_iv = true;
}
else if (strcmp(arg, "no-original-object-ids") == 0) else if (strcmp(arg, "no-original-object-ids") == 0)
{ {
suppress_original_object_id = true; suppress_original_object_id = true;
@ -1049,6 +1056,10 @@ int main(int argc, char* argv[])
{ {
w.setStaticID(true); w.setStaticID(true);
} }
if (static_aes_iv)
{
w.setStaticAesIV(true);
}
if (suppress_original_object_id) if (suppress_original_object_id)
{ {
w.setSuppressOriginalObjectIDs(true); w.setSuppressOriginalObjectIDs(true);

View File

@ -168,3 +168,5 @@ QPDF_encryption cleartext metadata 0
QPDF_encryption aes decode stream 0 QPDF_encryption aes decode stream 0
QPDFWriter forcing object stream disable 0 QPDFWriter forcing object stream disable 0
QPDFWriter forced version disabled encryption 0 QPDFWriter forced version disabled encryption 0
qpdf-c called qpdf_set_r4_encryption_parameters 0
qpdf-c called qpdf_set_static_aes_IV 0

View File

@ -954,6 +954,7 @@ $td->runtest("invalid password",
my @cenc = ( my @cenc = (
[11, 'hybrid-xref.pdf', "''", 'r2', ""], [11, 'hybrid-xref.pdf', "''", 'r2', ""],
[12, 'hybrid-xref.pdf', "''", 'r3', ""], [12, 'hybrid-xref.pdf', "''", 'r3', ""],
[15, 'hybrid-xref.pdf', "''", 'r4', ""],
[13, 'c-r2.pdf', 'user1', 'decrypt with user', [13, 'c-r2.pdf', 'user1', 'decrypt with user',
"user password: user1\n"], "user password: user1\n"],
[13, 'c-r3.pdf', 'owner2', 'decrypt with owner', [13, 'c-r3.pdf', 'owner2', 'decrypt with owner',

BIN
qpdf/qtest/qpdf/c-r4.pdf Normal file

Binary file not shown.