From 8532b2789d077ff0cc4144dad6844bbe9541c9e9 Mon Sep 17 00:00:00 2001
From: Krzysztof Galanty <krzysztof.ga@modulesgarden.com>
Date: Wed, 20 Sep 2017 15:18:29 +0200
Subject: [PATCH] - Added encrypt & decrypt functions to OpenSSL - Fixed PHP7
 incompatibilities regarding ambiguous hex-as-strings

---
 src/Bitpay/Crypto/OpenSSLExtension.php | 82 ++++++++++++++++++++++++++
 src/Bitpay/PrivateKey.php              |  4 +-
 src/Bitpay/PublicKey.php               |  2 +-
 3 files changed, 85 insertions(+), 3 deletions(-)

diff --git a/src/Bitpay/Crypto/OpenSSLExtension.php b/src/Bitpay/Crypto/OpenSSLExtension.php
index bcde0dc5..fcc21b65 100644
--- a/src/Bitpay/Crypto/OpenSSLExtension.php
+++ b/src/Bitpay/Crypto/OpenSSLExtension.php
@@ -26,6 +26,7 @@ public static function hasSupport()
      */
     public function getAlgos()
     {
+        return openssl_get_cipher_methods();
     }
 
     /**
@@ -177,4 +178,85 @@ final public function saveCSRtoString($csr, $out, $notext = true)
 
         return openssl_csr_export($csr, $out, $notext);
     }
+     /**
+     *
+     * Encrypts $text based on your $key and $iv.  The returned text is
+     * base-64 encoded to make it easier to work with in various scenarios.
+     * Default cipher is AES-256-CBC but you can substitute depending
+     * on your specific encryption needs.
+     *
+     * @param  string    $text
+     * @param  string    $key
+     * @param  string    $iv
+     * @param  int       $bit_check
+     * @param  string    $cipher_type
+     * @return string    $text
+     * @throws Exception $e
+     *
+     */
+    public function encrypt($text, $key = '', $iv = '', $bit_check = 8, $cipher_type = 'AES-256-CBC') {
+        try {
+            if (function_exists('openssl_pkey_new')) {
+                /* Ensure the key & IV is the same for both encrypt & decrypt. */
+                if (!empty($text) && is_string($text)) {
+                    $text_num = str_split($text, $bit_check);
+                    $text_num = $bit_check - strlen($text_num[count($text_num) - 1]);
+
+                    for ($i = 0; $i < $text_num; $i++) {
+                        $text = $text . chr($text_num);
+                    }
+                    $encrypted = openssl_encrypt($text, $cipher_type, $key, 0, $iv);
+                    return base64_encode($encrypted);
+                } else {
+                    return $text;
+                }
+            } else {
+                throw new \Exception('Error in OpenSSL encrypt: OpenSSL PHP extension missing. openssl_encrypt function not found.');
+
+                return false;
+            }
+        } catch (\Exception $e) {
+            throw $e;
+        }
+    }
+
+    /**
+     *
+     * Decrypts $text based on your $key and $iv.  Make sure you use the same key
+     * and initialization vector that you used when encrypting the $text. Default
+     * cipher is AES-256-CBC but you can substitute depending on the cipher
+     * used for encrypting the text - very important.
+     *
+     * @param  string    $encrypted_text
+     * @param  string    $key
+     * @param  string    $iv
+     * @param  int       $bit_check
+     * @param  string    $cipher_type
+     * @return string    $text
+     * @throws Exception $e
+     *
+     */
+    public function decrypt($encrypted_text, $key = '', $iv = '', $bit_check = 8, $cipher_type = 'AES-256-CBC') {
+        try {
+            /* Ensure the key & IV is the same for both encrypt & decrypt. */
+            if (!empty($encrypted_text)) {
+
+                $decrypted = openssl_decrypt(base64_decode($encrypted_text), $cipher_type, $key, 0, $iv);
+                $last_char = substr($decrypted, -1);
+
+                for ($i = 0; $i < $bit_check; $i++) {
+                    if (chr($i) == $last_char) {
+                        $decrypted = substr($decrypted, 0, strlen($decrypted) - $i);
+                        break;
+                    }
+                }
+                return $decrypted;
+            } else {
+                return $encrypted_text;
+            }
+        } catch (\Exception $e) {
+            throw $e;
+        }
+    }
+
 }
diff --git a/src/Bitpay/PrivateKey.php b/src/Bitpay/PrivateKey.php
index aa35b4ce..4f706367 100644
--- a/src/Bitpay/PrivateKey.php
+++ b/src/Bitpay/PrivateKey.php
@@ -220,7 +220,7 @@ public static function serializeSig($r, $s)
         $byte = strrev($byte);
 
         // msb check
-        if (Math::cmp('0x'.bin2hex($byte[0]), '0x80') >= 0) {
+        if (Math::cmp('0x'.bin2hex($byte[0]), '0'.'x80') >= 0) {
             $byte = chr(0x00).$byte;
         }
 
@@ -240,7 +240,7 @@ public static function serializeSig($r, $s)
         $byte = strrev($byte);
 
         // msb check
-        if (Math::cmp('0x'.bin2hex($byte[0]), '0x80') >= 0) {
+        if (Math::cmp('0x'.bin2hex($byte[0]), '0'.'x80') >= 0) {
             $byte = chr(0x00).$byte;
         }
 
diff --git a/src/Bitpay/PublicKey.php b/src/Bitpay/PublicKey.php
index 50bb9dd5..8d58416d 100644
--- a/src/Bitpay/PublicKey.php
+++ b/src/Bitpay/PublicKey.php
@@ -36,7 +36,7 @@ public function __toString()
             return '';
         }
 
-        if (Math::mod('0x'.$this->y, '0x02') == '1') {
+        if (Math::mod('0x'.$this->y, '0'.'x02') == '1') {
             return sprintf('03%s', $this->x);
         } else {
             return sprintf('02%s', $this->x);
