source-class-Com.Tecnick.Pdf.Encrypt.Compute

It appears that you are using AdBlocking software. The cost of running this website is covered by advertisements. If you like it please feel free to a small amount of money to secure the future of this website.
  1: <?php
  2: /**
  3:  * Compute.php
  4:  *
  5:  * @since       2008-01-02
  6:  * @category    Library
  7:  * @package     PdfEncrypt
  8:  * @author      Nicola Asuni <info@tecnick.com>
  9:  * @copyright   2011-2015 Nicola Asuni - Tecnick.com LTD
 10:  * @license     http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
 11:  * @link        https://github.com/tecnickcom/tc-lib-pdf-encrypt
 12:  *
 13:  * This file is part of tc-lib-pdf-encrypt software library.
 14:  */
 15: 
 16: namespace Com\Tecnick\Pdf\Encrypt;
 17: 
 18: use \Com\Tecnick\Pdf\Encrypt\Exception as EncException;
 19: 
 20: /**
 21:  * Com\Tecnick\Pdf\Encrypt\Compute
 22:  *
 23:  * PHP class to generate encryption data
 24:  *
 25:  * @since       2008-01-02
 26:  * @category    Library
 27:  * @package     PdfEncrypt
 28:  * @author      Nicola Asuni <info@tecnick.com>
 29:  * @copyright   2011-2015 Nicola Asuni - Tecnick.com LTD
 30:  * @license     http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
 31:  * @link        https://github.com/tecnickcom/tc-lib-pdf-encrypt
 32:  */
 33: abstract class Compute extends \Com\Tecnick\Pdf\Encrypt\Data
 34: {
 35:     /**
 36:      * Compute UE value
 37:      *
 38:      * @return string UE value
 39:      */
 40:     protected function getUEValue()
 41:     {
 42:         $hashkey = hash('sha256', $this->encryptdata['user_password'].$this->encryptdata['UKS'], true);
 43:         return $this->encrypt('AESnopad', $this->encryptdata['key'], $hashkey);
 44:     }
 45: 
 46:     /**
 47:      * Compute OE value
 48:      * @return string OE value
 49:      */
 50:     protected function getOEValue()
 51:     {
 52:         $hashkey = hash(
 53:             'sha256',
 54:             $this->encryptdata['owner_password'].$this->encryptdata['OKS'].$this->encryptdata['U'],
 55:             true
 56:         );
 57:         return $this->encrypt('AESnopad', $this->encryptdata['key'], $hashkey);
 58:     }
 59:     
 60:     /**
 61:      * Compute U value
 62:      *
 63:      * @return string U value
 64:      */
 65:     protected function getUvalue()
 66:     {
 67:         if ($this->encryptdata['mode'] == 0) { // RC4-40
 68:             return $this->encrypt('RC4', self::$encpad, $this->encryptdata['key']);
 69:         }
 70:         if ($this->encryptdata['mode'] < 3) { // RC4-128, AES-128
 71:             $tmp = $this->encrypt('MD5-16', self::$encpad.$this->encryptdata['fileid'], 'H*');
 72:             $enc = $this->encrypt('RC4', $tmp, $this->encryptdata['key']);
 73:             $len = strlen($tmp);
 74:             for ($idx = 1; $idx <= 19; ++$idx) {
 75:                 $ekey = '';
 76:                 for ($jdx = 0; $jdx < $len; ++$jdx) {
 77:                     $ekey .= chr(ord($this->encryptdata['key'][$jdx]) ^ $idx);
 78:                 }
 79:                 $enc = $this->encrypt('RC4', $enc, $ekey);
 80:             }
 81:             $enc .= str_repeat("\x00", 16);
 82:             return substr($enc, 0, 32);
 83:         }
 84:         // AES-256 ($this->encryptdata['mode'] = 3)
 85:         $seed = $this->encrypt('MD5-16', $this->encrypt('seed'), 'H*');
 86:         // User Validation Salt
 87:         $this->encryptdata['UVS'] = substr($seed, 0, 8);
 88:         // User Key Salt
 89:         $this->encryptdata['UKS'] = substr($seed, 8, 16);
 90:         return hash('sha256', $this->encryptdata['user_password'].$this->encryptdata['UVS'], true)
 91:             .$this->encryptdata['UVS'].$this->encryptdata['UKS'];
 92:     }
 93: 
 94:     /**
 95:      * Compute O value
 96:      *
 97:      * @return string O value
 98:      */
 99:     protected function getOValue()
100:     {
101:         if ($this->encryptdata['mode'] < 3) { // RC4-40, RC4-128, AES-128
102:             $tmp = $this->encrypt('MD5-16', $this->encryptdata['owner_password'], 'H*');
103:             if ($this->encryptdata['mode'] > 0) {
104:                 for ($idx = 0; $idx < 50; ++$idx) {
105:                     $tmp = $this->encrypt('MD5-16', $tmp, 'H*');
106:                 }
107:             }
108:             $owner_key = substr($tmp, 0, ($this->encryptdata['Length'] / 8));
109:             $enc = $this->encrypt('RC4', $this->encryptdata['user_password'], $owner_key);
110:             if ($this->encryptdata['mode'] > 0) {
111:                 $len = strlen($owner_key);
112:                 for ($idx = 1; $idx <= 19; ++$idx) {
113:                     $ekey = '';
114:                     for ($jdx = 0; $jdx < $len; ++$jdx) {
115:                         $ekey .= chr(ord($owner_key[$jdx]) ^ $idx);
116:                     }
117:                     $enc = $this->encrypt('RC4', $enc, $ekey);
118:                 }
119:             }
120:             return $enc;
121:         }
122:         // AES-256 ($this->encryptdata['mode'] = 3)
123:         $seed = $this->encrypt('MD5-16', $this->encrypt('seed'), 'H*');
124:         // Owner Validation Salt
125:         $this->encryptdata['OVS'] = substr($seed, 0, 8);
126:         // Owner Key Salt
127:         $this->encryptdata['OKS'] = substr($seed, 8, 16);
128:         return hash(
129:             'sha256',
130:             $this->encryptdata['owner_password'].$this->encryptdata['OVS'].$this->encryptdata['U'],
131:             true
132:         ).$this->encryptdata['OVS'].$this->encryptdata['OKS'];
133:     }
134: 
135:     /**
136:      * Compute encryption key
137:      */
138:     protected function generateEncryptionKey()
139:     {
140:         if ($this->encryptdata['pubkey']) {
141:             $this->generatePublicEncryptionKey();
142:         } else { // standard mode
143:             $this->generateStandardEncryptionKey();
144:         }
145:     }
146: 
147:     /**
148:      * Compute standard encryption key
149:      */
150:     protected function generateStandardEncryptionKey()
151:     {
152:         $keybytelen = ($this->encryptdata['Length'] / 8);
153:         if ($this->encryptdata['mode'] == 3) { // AES-256
154:             // generate 256 bit random key
155:             $this->encryptdata['key'] = substr(hash('sha256', $this->encrypt('seed'), true), 0, $keybytelen);
156:             // truncate passwords
157:             $this->encryptdata['user_password'] = substr($this->encryptdata['user_password'], 0, 127);
158:             $this->encryptdata['owner_password'] = substr($this->encryptdata['owner_password'], 0, 127);
159:             $this->encryptdata['U'] = $this->getUValue();
160:             $this->encryptdata['UE'] = $this->getUEValue();
161:             $this->encryptdata['O'] = $this->getOValue();
162:             $this->encryptdata['OE'] = $this->getOEValue();
163:             $this->encryptdata['P'] = $this->encryptdata['protection'];
164:             // Computing the encryption dictionary's Perms (permissions) value
165:             $perms = $this->getEncPermissionsString($this->encryptdata['protection']); // bytes 0-3
166:             $perms .= chr(255).chr(255).chr(255).chr(255); // bytes 4-7
167:             $perms .= 'T'; // $this->encryptdata['CF']['EncryptMetadata'] is never set, so we always encrypt
168:             $perms .= 'adb'; // bytes 9-11
169:             $perms .= 'nick'; // bytes 12-15
170:             $this->encryptdata['perms'] = $this->encrypt('AESnopad', $perms, $this->encryptdata['key']);
171:         } else { // RC4-40, RC4-128, AES-128
172:             // Pad passwords
173:             $this->encryptdata['user_password'] = substr($this->encryptdata['user_password'].self::$encpad, 0, 32);
174:             $this->encryptdata['owner_password'] = substr($this->encryptdata['owner_password'].self::$encpad, 0, 32);
175:             $this->encryptdata['O'] = $this->getOValue();
176:             // get default permissions (reverse byte order)
177:             $permissions = $this->getEncPermissionsString($this->encryptdata['protection']);
178:             // Compute encryption key
179:             $tmp = $this->encrypt(
180:                 'MD5-16',
181:                 $this->encryptdata['user_password'].$this->encryptdata['O'].$permissions.$this->encryptdata['fileid'],
182:                 'H*'
183:             );
184:             if ($this->encryptdata['mode'] > 0) {
185:                 for ($idx = 0; $idx < 50; ++$idx) {
186:                     $tmp = $this->encrypt('MD5-16', substr($tmp, 0, $keybytelen), 'H*');
187:                 }
188:             }
189:             $this->encryptdata['key'] = substr($tmp, 0, $keybytelen);
190:             $this->encryptdata['U'] = $this->getUValue();
191:             $this->encryptdata['P'] = $this->encryptdata['protection'];
192:         }
193:     }
194: 
195:     /**
196:      * Compute public encryption key
197:      */
198:     protected function generatePublicEncryptionKey()
199:     {
200:         $keybytelen = ($this->encryptdata['Length'] / 8);
201:         // random 20-byte seed
202:         $seed = sha1($this->encrypt('seed'), true);
203:         $recipient_bytes = '';
204:         foreach ($this->encryptdata['pubkeys'] as $pubkey) {
205:             // for each public certificate
206:             if (isset($pubkey['p'])) {
207:                 $pkprotection = $this->getUserPermissionCode($pubkey['p'], $this->encryptdata['mode']);
208:             } else {
209:                 $pkprotection = $this->encryptdata['protection'];
210:             }
211:             // get default permissions (reverse byte order)
212:             $pkpermissions = $this->getEncPermissionsString($pkprotection);
213:             // envelope data
214:             $envelope = $seed.$pkpermissions;
215:             // write the envelope data to a temporary file
216:             $tempkeyfile = tempnam(
217:                 sys_get_temp_dir(),
218:                 '__tcpdf_key_'.md5($this->encryptdata['fileid'].$envelope).'_'
219:             );
220:             if (file_put_contents($tempkeyfile, $envelope) === false) {
221:                 // @codeCoverageIgnoreStart
222:                 throw new EncException('Unable to create temporary key file: '.$tempkeyfile);
223:                 // @codeCoverageIgnoreEnd
224:             }
225:             $tempencfile = tempnam(
226:                 sys_get_temp_dir(),
227:                 '__tcpdf_enc_'.md5($this->encryptdata['fileid'].$envelope).'_'
228:             );
229: 
230:             if (!function_exists('openssl_pkcs7_encrypt')) {
231:                 // @codeCoverageIgnoreStart
232:                 throw new EncException(
233:                     'Unable to encrypt the file: '.$tempkeyfile."\n"
234:                     .'Public-Key Security requires openssl_pkcs7_encrypt.'
235:                 );
236:                 // @codeCoverageIgnoreEnd
237:             } elseif (!openssl_pkcs7_encrypt(
238:                 $tempkeyfile,
239:                 $tempencfile,
240:                 file_get_contents($pubkey['c']),
241:                 array(),
242:                 PKCS7_BINARY
243:             )) {
244:                 throw new EncException(
245:                     'Unable to encrypt the file: '.$tempkeyfile."\n"
246:                     .'OpenSSL error: ' . openssl_error_string()
247:                 );
248:             }
249: 
250:             // read encryption signature
251:             $signature = file_get_contents($tempencfile);
252:             // extract signature
253:             $signature = substr($signature, strpos($signature, 'Content-Disposition'));
254:             $tmparr = explode("\n\n", $signature);
255:             $signature = trim($tmparr[1]);
256:             unset($tmparr);
257:             // decode signature
258:             $signature = base64_decode($signature);
259:             // convert signature to hex
260:             $hexsignature = current(unpack('H*', $signature));
261:             // store signature on recipients array
262:             $this->encryptdata['Recipients'][] = $hexsignature;
263:             // The bytes of each item in the Recipients array of PKCS#7 objects
264:             // in the order in which they appear in the array
265:             $recipient_bytes .= $signature;
266:         }
267:         // calculate encryption key
268:         if ($this->encryptdata['mode'] == 3) { // AES-256
269:             $this->encryptdata['key'] = substr(hash('sha256', $seed.$recipient_bytes, true), 0, $keybytelen);
270:         } else { // RC4-40, RC4-128, AES-128
271:             $this->encryptdata['key'] = substr(sha1($seed.$recipient_bytes, true), 0, $keybytelen);
272:         }
273:     }
274: }
275: 
 

© 2004-2017 – Nicola Asuni - Tecnick.com - All rights reserved.
about - disclaimer - privacy