Decryptor.php 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. <?php
  2. namespace RNCryptor;
  3. /**
  4. * RNDecryptor for PHP
  5. *
  6. * Decrypt data interchangeably with Rob Napier's Objective-C implementation
  7. * of RNCryptor
  8. */
  9. class Decryptor extends Cryptor {
  10. /**
  11. * Decrypt RNCryptor-encrypted data
  12. *
  13. * @param string $base64EncryptedData Encrypted, Base64-encoded text
  14. * @param string $password Password the text was encoded with
  15. * @throws Exception If the detected version is unsupported
  16. * @return string|false Decrypted string, or false if decryption failed
  17. */
  18. public function decrypt($encryptedBase64Data, $password) {
  19. $components = $this->_unpackEncryptedBase64Data($encryptedBase64Data);
  20. if (!$this->_hmacIsValid($components, $password)) {
  21. return false;
  22. }
  23. $key = $this->_generateKey($components->headers->encSalt, $password);
  24. switch ($this->_settings->mode) {
  25. case 'ctr':
  26. $plaintext = $this->_aesCtrLittleEndianCrypt($components->ciphertext, $key, $components->headers->iv);
  27. break;
  28. case 'cbc':
  29. $paddedPlaintext = mcrypt_decrypt($this->_settings->algorithm, $key, $components->ciphertext, 'cbc', $components->headers->iv);
  30. $plaintext = $this->_stripPKCS7Padding($paddedPlaintext);
  31. break;
  32. }
  33. return $plaintext;
  34. }
  35. private function _unpackEncryptedBase64Data($encryptedBase64Data) {
  36. $binaryData = base64_decode($encryptedBase64Data);
  37. $components = new \stdClass();
  38. $components->headers = $this->_parseHeaders($binaryData);
  39. $components->hmac = substr($binaryData, - $this->_settings->hmac->length);
  40. $headerLength = $components->headers->length;
  41. $components->ciphertext = substr($binaryData, $headerLength, strlen($binaryData) - $headerLength - strlen($components->hmac));
  42. return $components;
  43. }
  44. private function _parseHeaders($binData) {
  45. $offset = 0;
  46. $versionChr = $binData[0];
  47. $offset += strlen($versionChr);
  48. $this->_configureSettings(ord($versionChr));
  49. $optionsChr = $binData[1];
  50. $offset += strlen($optionsChr);
  51. $encSalt = substr($binData, $offset, $this->_settings->saltLength);
  52. $offset += strlen($encSalt);
  53. $hmacSalt = substr($binData, $offset, $this->_settings->saltLength);
  54. $offset += strlen($hmacSalt);
  55. $iv = substr($binData, $offset, $this->_settings->ivLength);
  56. $offset += strlen($iv);
  57. $headers = (object)array(
  58. 'version' => $versionChr,
  59. 'options' => $optionsChr,
  60. 'encSalt' => $encSalt,
  61. 'hmacSalt' => $hmacSalt,
  62. 'iv' => $iv,
  63. 'length' => $offset
  64. );
  65. return $headers;
  66. }
  67. private function _stripPKCS7Padding($plaintext) {
  68. $padLength = ord($plaintext[strlen($plaintext)-1]);
  69. return substr($plaintext, 0, strlen($plaintext) - $padLength);
  70. }
  71. private function _hmacIsValid($components, $password) {
  72. $hmacKey = $this->_generateKey($components->headers->hmacSalt, $password);
  73. return ($components->hmac == $this->_generateHmac($components, $hmacKey));
  74. }
  75. }