123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- <?php
- namespace RNCryptor\RNCryptor;
- use stdClass;
- /**
- * RNDecryptor for PHP
- *
- * Decrypt data interchangeably with Rob Napier's Objective-C implementation
- * of RNCryptor
- */
- class Decryptor extends Cryptor
- {
- /**
- * Decrypt RNCryptor-encrypted data
- *
- * @param string $base64EncryptedData Encrypted, Base64-encoded text
- * @param string $password Password the text was encoded with
- * @throws Exception If the detected version is unsupported
- * @return string|false Decrypted string, or false if decryption failed
- */
- public function decrypt($encryptedBase64Data, $password)
- {
- $components = $this->unpackEncryptedBase64Data($encryptedBase64Data);
- if (!$this->hmacIsValid($components, $password)) {
- return false;
- }
- $key = $this->makeKey($components->headers->encSalt, $password);
- if ($this->config->mode == 'ctr') {
- return $this->aesCtrLittleEndianCrypt($components->ciphertext, $key, $components->headers->iv);
- }
- $iv = (string)$components->headers->iv;
- $method = $this->config->algorithm . 'cbc';
- return openssl_decrypt($components->ciphertext, $method, $key, OPENSSL_RAW_DATA, (string)$iv);
- }
- private function unpackEncryptedBase64Data($encryptedBase64Data, $isPasswordBased = true)
- {
- $binaryData = base64_decode($encryptedBase64Data);
- $components = new stdClass;
- $components->headers = $this->parseHeaders($binaryData, $isPasswordBased);
- $components->hmac = substr($binaryData, -$this->config->hmac->length);
- $offset = $components->headers->length;
- $length = strlen($binaryData) - $offset - strlen($components->hmac);
- $components->ciphertext = substr($binaryData, $offset, $length);
- return $components;
- }
- private function parseHeaders($binData, $isPasswordBased = true)
- {
- $offset = 0;
- $versionChr = $binData[0];
- $offset += strlen($versionChr);
- $this->configure(ord($versionChr));
- $optionsChr = $binData[1];
- $offset += strlen($optionsChr);
- $encSalt = null;
- $hmacSalt = null;
- if ($isPasswordBased) {
- $encSalt = substr($binData, $offset, $this->config->saltLength);
- $offset += strlen($encSalt);
- $hmacSalt = substr($binData, $offset, $this->config->saltLength);
- $offset += strlen($hmacSalt);
- }
- $iv = substr($binData, $offset, $this->config->ivLength);
- $offset += strlen($iv);
- $headers = (object)[
- 'version' => $versionChr,
- 'options' => $optionsChr,
- 'encSalt' => $encSalt,
- 'hmacSalt' => $hmacSalt,
- 'iv' => $iv,
- 'length' => $offset
- ];
- return $headers;
- }
- private function hmacIsValid($components, $password)
- {
- $hmacKey = $this->makeKey($components->headers->hmacSalt, $password);
- return hash_equals($components->hmac, $this->makeHmac($components, $hmacKey));
- }
- }
|