From 44240798be68433127e4699598ae0b98098743b8 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Wed, 13 May 2015 17:25:42 +0200 Subject: [PATCH] Convert UTF8 encoded passwords to ISO-8859-1 for |R = 6| encryption (issue 6010) For passwords where the encoding already is correct, the conversion is a no-op. Also, since `encodeURIComponent` might throw, we need to make sure that we handle that case too. Fixes 6010. --- src/core/crypto.js | 13 +++++++++++-- src/shared/util.js | 4 ++++ test/pdfs/.gitignore | 2 ++ test/pdfs/issue6010_1.pdf | 37 +++++++++++++++++++++++++++++++++++++ test/pdfs/issue6010_2.pdf | 38 ++++++++++++++++++++++++++++++++++++++ test/test_manifest.json | 17 +++++++++++++++++ 6 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 test/pdfs/issue6010_1.pdf create mode 100644 test/pdfs/issue6010_2.pdf diff --git a/src/core/crypto.js b/src/core/crypto.js index abb1d18fd..95d63b175 100644 --- a/src/core/crypto.js +++ b/src/core/crypto.js @@ -15,7 +15,8 @@ * limitations under the License. */ /* globals bytesToString, DecryptStream, error, isInt, isName, Name, - PasswordException, PasswordResponses, stringToBytes */ + PasswordException, PasswordResponses, stringToBytes, warn, + utf8StringToString */ 'use strict'; @@ -1918,6 +1919,14 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() { var fileIdBytes = stringToBytes(fileId); var passwordBytes; if (password) { + if (revision === 6) { + try { + password = utf8StringToString(password); + } catch (ex) { + warn('CipherTransformFactory: ' + + 'Unable to convert UTF8 encoded password.'); + } + } passwordBytes = stringToBytes(password); } @@ -2022,7 +2031,7 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() { CipherTransformFactory.prototype = { createCipherTransform: - function CipherTransformFactory_createCipherTransform(num, gen) { + function CipherTransformFactory_createCipherTransform(num, gen) { if (this.algorithm === 4 || this.algorithm === 5) { return new CipherTransform( buildCipherConstructor(this.cf, this.stmf, diff --git a/src/shared/util.js b/src/shared/util.js index 47736b02b..382f6437f 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -946,6 +946,10 @@ function stringToUTF8String(str) { return decodeURIComponent(escape(str)); } +function utf8StringToString(str) { + return unescape(encodeURIComponent(str)); +} + function isEmptyObj(obj) { for (var key in obj) { return false; diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 7946c42e3..ca03261e1 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -130,3 +130,5 @@ !issue5701.pdf !issue5896.pdf !issue5909.pdf +!issue6010_1.pdf +!issue6010_2.pdf diff --git a/test/pdfs/issue6010_1.pdf b/test/pdfs/issue6010_1.pdf new file mode 100644 index 000000000..504711092 --- /dev/null +++ b/test/pdfs/issue6010_1.pdf @@ -0,0 +1,37 @@ +%PDF-1.7 +% +1 0 obj +<> +endobj +2 0 obj +<> +endobj +3 0 obj +<>>>/MediaBox[0 0 200 50]/Type/Page/Contents 4 0 R>> +endobj +4 0 obj +<> +stream +62|Q$j^BHJC<w߲M%X33u찺;*iͻK9IR +endstream +endobj +5 0 obj +<> +endobj +6 0 obj +<> +endobj +xref +0 7 +0000000000 65535 f +0000000015 00000 n +0000000060 00000 n +0000000123 00000 n +0000000234 00000 n +0000000365 00000 n +0000000445 00000 n +trailer +</j_8:;)(gUe>/j_8:;)]/Encrypt<>>>/EncryptMetadata true/Length 256/R 6/O(6\(T#󃉏k6PQ鎒\n`@$Ke F)/U( 44~>WnT-:}|XSvf2,8ߛ^,}w3\f)/P -4/StrF/StdCF/StmF/StdCF/Perms(\r1ou)/OE(?O\(Q5F RVJ,VY)/UE(EblpK5PLFqID<><)>>/Root 1 0 R>> +startxref +517 +%%EOF diff --git a/test/pdfs/issue6010_2.pdf b/test/pdfs/issue6010_2.pdf new file mode 100644 index 000000000..ccb117e59 --- /dev/null +++ b/test/pdfs/issue6010_2.pdf @@ -0,0 +1,38 @@ +%PDF-1.7 +% +1 0 obj +<> +endobj +2 0 obj +<> +endobj +3 0 obj +<>>>/MediaBox[0 0 200 50]/Type/Page/Contents 4 0 R>> +endobj +4 0 obj +<> +stream +hR$֯kooElg,Qhw$YvÃ=;^us_ +##%' +endstream +endobj +5 0 obj +<> +endobj +6 0 obj +<> +endobj +xref +0 7 +0000000000 65535 f +0000000015 00000 n +0000000060 00000 n +0000000123 00000 n +0000000234 00000 n +0000000365 00000 n +0000000445 00000 n +trailer +<>>>/EncryptMetadata true/Length 256/R 6/O( 듷XXB\fp G&§q0<PxaUY)/U(WPkD_ÑL^D\f.CsrF\\NUL 4F9)/P -4/StrF/StdCF/StmF/StdCF/Perms( G^oFGQO)/OE(h7饷ⴁCnx'7+n53E)/UE(W[ZѪ=Q0y##ԭ&ڹPv)>>/Root 1 0 R>> +startxref +517 +%%EOF diff --git a/test/test_manifest.json b/test/test_manifest.json index f20b9863a..be0ec3067 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -1493,6 +1493,23 @@ "type": "eq", "about": "Rotated transparency group with blend mode." }, + { "id": "issue6010_1", + "file": "pdfs/issue6010_1.pdf", + "md5": "b58adce5dbb08936ddb0d904f0da8716", + "rounds": 1, + "link": false, + "type": "load", + "password": "abc" + }, + { "id": "issue6010_2", + "file": "pdfs/issue6010_2.pdf", + "md5": "73a8091d0ab2a47af5ca45047f04da99", + "rounds": 1, + "link": false, + "type": "load", + "password": "\u00E6\u00F8\u00E5", + "about": "The password () is UTF8 encoded." + }, { "id": "issue3458.pdf", "file": "pdfs/issue3458.pdf", "md5": "dab8bd3ad1acfc8dc82a8381a3c8ff94",