DefuseCryptoCrypto

The WooCommerce Germanized Defuse Crypto class.

Defined (1)

The class is defined in the following location(s).

/includes/gateways/direct-debit/libraries/php-encryption/Crypto.php  
  1. class Crypto 
  2. /** 
  3. * Encrypts a string with a Key. 
  4. * @param string $plaintext 
  5. * @param Key $key 
  6. * @param bool $raw_binary 
  7. * @throws Defuse\Crypto\Exception\EnvironmentIsBrokenException 
  8. * @return string 
  9. */ 
  10. public static function encrypt($plaintext, Key $key, $raw_binary = false) 
  11. return self::encryptInternal( 
  12. $plaintext,  
  13. KeyOrPassword::createFromKey($key),  
  14. $raw_binary 
  15. ); 
  16.  
  17. /** 
  18. * Encrypts a string with a password, using a slow key derivation function 
  19. * to make password cracking more expensive. 
  20. * @param string $plaintext 
  21. * @param string $password 
  22. * @param bool $raw_binary 
  23. * @throws Defuse\Crypto\Exception\EnvironmentIsBrokenException 
  24. * @return string 
  25. */ 
  26. public static function encryptWithPassword($plaintext, $password, $raw_binary = false) 
  27. return self::encryptInternal( 
  28. $plaintext,  
  29. KeyOrPassword::createFromPassword($password),  
  30. $raw_binary 
  31. ); 
  32.  
  33. /** 
  34. * Decrypts a ciphertext to a string with a Key. 
  35. * @param string $ciphertext 
  36. * @param Key $key 
  37. * @param bool $raw_binary 
  38. * @throws Defuse\Crypto\Exception\EnvironmentIsBrokenException 
  39. * @throws Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException 
  40. * @return string 
  41. */ 
  42. public static function decrypt($ciphertext, Key $key, $raw_binary = false) 
  43. return self::decryptInternal( 
  44. $ciphertext,  
  45. KeyOrPassword::createFromKey($key),  
  46. $raw_binary 
  47. ); 
  48.  
  49. /** 
  50. * Decrypts a ciphertext to a string with a password, using a slow key 
  51. * derivation function to make password cracking more expensive. 
  52. * @param string $ciphertext 
  53. * @param string $password 
  54. * @param bool $raw_binary 
  55. * @throws Defuse\Crypto\Exception\EnvironmentIsBrokenException 
  56. * @throws Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException 
  57. * @return string 
  58. */ 
  59. public static function decryptWithPassword($ciphertext, $password, $raw_binary = false) 
  60. return self::decryptInternal( 
  61. $ciphertext,  
  62. KeyOrPassword::createFromPassword($password),  
  63. $raw_binary 
  64. ); 
  65.  
  66. /** 
  67. * Decrypts a legacy ciphertext produced by version 1 of this library. 
  68. * @param string $ciphertext 
  69. * @param string $key 
  70. * @throws Ex\EnvironmentIsBrokenException 
  71. * @throws Ex\WrongKeyOrModifiedCiphertextException 
  72. * @return string 
  73. */ 
  74. public static function legacyDecrypt($ciphertext, $key) 
  75. RuntimeTests::runtimeTest(); 
  76.  
  77. // Extract the HMAC from the front of the ciphertext. 
  78. if (Core::ourStrlen($ciphertext) <= Core::LEGACY_MAC_BYTE_SIZE) { 
  79. throw new Ex\WrongKeyOrModifiedCiphertextException( 
  80. 'Ciphertext is too short.' 
  81. ); 
  82. $hmac = Core::ourSubstr($ciphertext, 0, Core::LEGACY_MAC_BYTE_SIZE); 
  83. if ($hmac === false) { 
  84. throw new Ex\EnvironmentIsBrokenException(); 
  85. $ciphertext = Core::ourSubstr($ciphertext, Core::LEGACY_MAC_BYTE_SIZE); 
  86. if ($ciphertext === false) { 
  87. throw new Ex\EnvironmentIsBrokenException(); 
  88.  
  89. // Regenerate the same authentication sub-key. 
  90. $akey = Core::HKDF( 
  91. Core::LEGACY_HASH_FUNCTION_NAME,  
  92. $key,  
  93. Core::LEGACY_KEY_BYTE_SIZE,  
  94. Core::LEGACY_AUTHENTICATION_INFO_STRING,  
  95. null 
  96. ); 
  97.  
  98. if (self::verifyHMAC($hmac, $ciphertext, $akey)) { 
  99. // Regenerate the same encryption sub-key. 
  100. $ekey = Core::HKDF( 
  101. Core::LEGACY_HASH_FUNCTION_NAME,  
  102. $key,  
  103. Core::LEGACY_KEY_BYTE_SIZE,  
  104. Core::LEGACY_ENCRYPTION_INFO_STRING,  
  105. null 
  106. ); 
  107.  
  108. // Extract the IV from the ciphertext. 
  109. if (Core::ourStrlen($ciphertext) <= Core::LEGACY_BLOCK_BYTE_SIZE) { 
  110. throw new Ex\WrongKeyOrModifiedCiphertextException( 
  111. 'Ciphertext is too short.' 
  112. ); 
  113. $iv = Core::ourSubstr($ciphertext, 0, Core::LEGACY_BLOCK_BYTE_SIZE); 
  114. if ($iv === false) { 
  115. throw new Ex\EnvironmentIsBrokenException(); 
  116. $ciphertext = Core::ourSubstr($ciphertext, Core::LEGACY_BLOCK_BYTE_SIZE); 
  117. if ($ciphertext === false) { 
  118. throw new Ex\EnvironmentIsBrokenException(); 
  119.  
  120. // Do the decryption. 
  121. $plaintext = self::plainDecrypt($ciphertext, $ekey, $iv, Core::LEGACY_CIPHER_METHOD); 
  122. return $plaintext; 
  123. } else { 
  124. throw new Ex\WrongKeyOrModifiedCiphertextException( 
  125. 'Integrity check failed.' 
  126. ); 
  127.  
  128. /** 
  129. * Encrypts a string with either a key or a password. 
  130. * @param string $plaintext 
  131. * @param KeyOrPassword $secret 
  132. * @param bool $raw_binary 
  133. * @return string 
  134. */ 
  135. private static function encryptInternal($plaintext, KeyOrPassword $secret, $raw_binary) 
  136. RuntimeTests::runtimeTest(); 
  137.  
  138. $salt = Core::secureRandom(Core::SALT_BYTE_SIZE); 
  139. $keys = $secret->deriveKeys($salt); 
  140. $ekey = $keys->getEncryptionKey(); 
  141. $akey = $keys->getAuthenticationKey(); 
  142. $iv = Core::secureRandom(Core::BLOCK_BYTE_SIZE); 
  143.  
  144. $ciphertext = Core::CURRENT_VERSION . $salt . $iv . self::plainEncrypt($plaintext, $ekey, $iv); 
  145. $auth = \hash_hmac(Core::HASH_FUNCTION_NAME, $ciphertext, $akey, true); 
  146. $ciphertext = $ciphertext . $auth; 
  147.  
  148. if ($raw_binary) { 
  149. return $ciphertext; 
  150. return Encoding::binToHex($ciphertext); 
  151.  
  152. /** 
  153. * Decrypts a ciphertext to a string with either a key or a password. 
  154. * @param string $ciphertext 
  155. * @param KeyOrPassword $secret 
  156. * @param bool $raw_binary 
  157. * @throws Defuse\Crypto\Exception\EnvironmentIsBrokenException 
  158. * @throws Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException 
  159. * @return string 
  160. */ 
  161. private static function decryptInternal($ciphertext, KeyOrPassword $secret, $raw_binary) 
  162. RuntimeTests::runtimeTest(); 
  163.  
  164. if (! $raw_binary) { 
  165. try { 
  166. $ciphertext = Encoding::hexToBin($ciphertext); 
  167. } catch (Ex\BadFormatException $ex) { 
  168. throw new Ex\WrongKeyOrModifiedCiphertextException( 
  169. 'Ciphertext has invalid hex encoding.' 
  170. ); 
  171.  
  172. if (Core::ourStrlen($ciphertext) < Core::MINIMUM_CIPHERTEXT_SIZE) { 
  173. throw new Ex\WrongKeyOrModifiedCiphertextException( 
  174. 'Ciphertext is too short.' 
  175. ); 
  176.  
  177. // Get and check the version header. 
  178. $header = Core::ourSubstr($ciphertext, 0, Core::HEADER_VERSION_SIZE); 
  179. if ($header !== Core::CURRENT_VERSION) { 
  180. throw new Ex\WrongKeyOrModifiedCiphertextException( 
  181. 'Bad version header.' 
  182. ); 
  183.  
  184. // Get the salt. 
  185. $salt = Core::ourSubstr( 
  186. $ciphertext,  
  187. Core::HEADER_VERSION_SIZE,  
  188. Core::SALT_BYTE_SIZE 
  189. ); 
  190. if ($salt === false) { 
  191. throw new Ex\EnvironmentIsBrokenException(); 
  192.  
  193. // Get the IV. 
  194. $iv = Core::ourSubstr( 
  195. $ciphertext,  
  196. Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE,  
  197. Core::BLOCK_BYTE_SIZE 
  198. ); 
  199. if ($iv === false) { 
  200. throw new Ex\EnvironmentIsBrokenException(); 
  201.  
  202. // Get the HMAC. 
  203. $hmac = Core::ourSubstr( 
  204. $ciphertext,  
  205. Core::ourStrlen($ciphertext) - Core::MAC_BYTE_SIZE,  
  206. Core::MAC_BYTE_SIZE 
  207. ); 
  208. if ($hmac === false) { 
  209. throw new Ex\EnvironmentIsBrokenException(); 
  210.  
  211. // Get the actual encrypted ciphertext. 
  212. $encrypted = Core::ourSubstr( 
  213. $ciphertext,  
  214. Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + 
  215. Core::BLOCK_BYTE_SIZE,  
  216. Core::ourStrlen($ciphertext) - Core::MAC_BYTE_SIZE - Core::SALT_BYTE_SIZE - 
  217. Core::BLOCK_BYTE_SIZE - Core::HEADER_VERSION_SIZE 
  218. ); 
  219. if ($encrypted === false) { 
  220. throw new Ex\EnvironmentIsBrokenException(); 
  221.  
  222. // Derive the separate encryption and authentication keys from the key 
  223. // or password, whichever it is. 
  224. $keys = $secret->deriveKeys($salt); 
  225.  
  226. if (self::verifyHMAC($hmac, $header . $salt . $iv . $encrypted, $keys->getAuthenticationKey())) { 
  227. $plaintext = self::plainDecrypt($encrypted, $keys->getEncryptionKey(), $iv, Core::CIPHER_METHOD); 
  228. return $plaintext; 
  229. } else { 
  230. throw new Ex\WrongKeyOrModifiedCiphertextException( 
  231. 'Integrity check failed.' 
  232. ); 
  233.  
  234. /** 
  235. * Raw unauthenticated encryption (insecure on its own). 
  236. * @param string $plaintext 
  237. * @param string $key 
  238. * @param string $iv 
  239. * @throws Ex\EnvironmentIsBrokenException 
  240. * @return string 
  241. */ 
  242. protected static function plainEncrypt($plaintext, $key, $iv) 
  243. Core::ensureConstantExists('OPENSSL_RAW_DATA'); 
  244. Core::ensureFunctionExists('openssl_encrypt'); 
  245. $ciphertext = \openssl_encrypt( 
  246. $plaintext,  
  247. Core::CIPHER_METHOD,  
  248. $key,  
  249. OPENSSL_RAW_DATA,  
  250. $iv 
  251. ); 
  252.  
  253. if ($ciphertext === false) { 
  254. throw new Ex\EnvironmentIsBrokenException( 
  255. 'openssl_encrypt() failed.' 
  256. ); 
  257.  
  258. return $ciphertext; 
  259.  
  260. /** 
  261. * Raw unauthenticated decryption (insecure on its own). 
  262. * @param string $ciphertext 
  263. * @param string $key 
  264. * @param string $iv 
  265. * @param string $cipherMethod 
  266. * @throws Ex\EnvironmentIsBrokenException 
  267. * @return string 
  268. */ 
  269. protected static function plainDecrypt($ciphertext, $key, $iv, $cipherMethod) 
  270. Core::ensureConstantExists('OPENSSL_RAW_DATA'); 
  271. Core::ensureFunctionExists('openssl_decrypt'); 
  272. $plaintext = \openssl_decrypt( 
  273. $ciphertext,  
  274. $cipherMethod,  
  275. $key,  
  276. OPENSSL_RAW_DATA,  
  277. $iv 
  278. ); 
  279. if ($plaintext === false) { 
  280. throw new Ex\EnvironmentIsBrokenException( 
  281. 'openssl_decrypt() failed.' 
  282. ); 
  283.  
  284. return $plaintext; 
  285.  
  286. /** 
  287. * Verifies an HMAC without leaking information through side-channels. 
  288. * @param string $correct_hmac 
  289. * @param string $message 
  290. * @param string $key 
  291. * @throws Ex\EnvironmentIsBrokenException 
  292. * @return bool 
  293. */ 
  294. protected static function verifyHMAC($correct_hmac, $message, $key) 
  295. $message_hmac = \hash_hmac(Core::HASH_FUNCTION_NAME, $message, $key, true); 
  296. return Core::hashEquals($correct_hmac, $message_hmac);