1
0
Quellcode durchsuchen

Break out encryption from SecureString to make working with encryption easier.

Nathaniel van Diepen vor 6 Jahren
Ursprung
Commit
9f9e29dfcf
2 geänderte Dateien mit 60 neuen und 10 gelöschten Zeilen
  1. 47 0
      Data/encryption.class.php
  2. 13 10
      Data/securestring.class.php

+ 47 - 0
Data/encryption.class.php

@@ -0,0 +1,47 @@
+<?php
+	namespace Juju\Data;
+
+	class Encryption {
+		private static $methods = null;
+		private static $instances = [];
+		private $method = null;
+		private function __construct(string $method){
+			$this->method = $method;
+		}
+		public function __get(string $name){
+			switch($name){
+				case 'method':
+					return $this->method;
+				default:
+					throw new \Exception("Property {$name} does not exist");
+			}
+		}
+		public static function methods(){
+			if(is_null(self::$methods)){
+				self::$methods = openssl_get_cipher_methods();
+			}
+			return self::$methods;
+		}
+		public static function from(string $method){
+			if(!in_array($method, self::methods())){
+				throw new Exception("Unsupported OpenSSL method: {$method}");
+			}
+			if(!isset(Encryption::$instances[$method])){
+				Encryption::$instances[$method] = new Encryption($method);
+			}
+			return Encryption::$instances[$method];
+		}
+		public function __toString(){
+			return $this->method.'';
+		}
+		public function iv_len(){
+			return openssl_cipher_iv_length($this->method);
+		}
+		public function encrypt(string $data, string $key, string $iv){
+			return openssl_encrypt($data, $this->method, $key, \OPENSSL_RAW_DATA, $iv);
+		}
+		public function decrypt(string $data, string $key, string $iv){
+			return openssl_decrypt($data, $this->method, $key, \OPENSSL_RAW_DATA, $iv);
+		}
+	}
+?>

+ 13 - 10
Data/securestring.class.php

@@ -1,27 +1,30 @@
 <?php
 	namespace Juju\Data;
+	require_once('encryption.class.php');
 
 	class SecureString implements \JsonSerializable {
 		private $data;
 		private $password;
 		private $iv;
-		private $method;
-		private static $methods = null;
+		private $encryption;
 		private function __construct(string $data){
+			$tries = 0;
+			$methods = Encryption::methods();
 			do{
-				if(is_null(self::$methods)){
-					self::$methods = openssl_get_cipher_methods();
-				}
-				$this->method = self::$methods[random_int(0, count(self::$methods) - 1)];
-				$ivlen = openssl_cipher_iv_length($this->method);
+				$method = $methods[random_int(0, count($methods) - 1)];
+				$this->encryption = Encryption::from($method);
+				$ivlen = $this->encryption->iv_len();
 				$this->password = openssl_random_pseudo_bytes($ivlen);
 				$this->iv = openssl_random_pseudo_bytes($ivlen);
-				$this->data = openssl_encrypt($data, $this->method, $this->password, \OPENSSL_RAW_DATA, $this->iv);
+				$this->data = $this->encryption->encrypt($data, $this->password, $this->iv);
+				if(++$tries == count($methods)){
+					throw new \Exception("Too many failed attempts to encrypt data");
+				}
 			// If for some reason the data we encrypted will not decrypt, try again until it will
 			}while($data != (string)$this);
 		}
 		public function __toString(){
-			return ''.openssl_decrypt($this->data, $this->method, $this->password, \OPENSSL_RAW_DATA, $this->iv);
+			return ''.$this->encryption->decrypt($this->data, $this->password, $this->iv);
 		}
 		public function jsonSerialize(){
 			return "{$this}";
@@ -30,4 +33,4 @@
 			return new self($data);
 		}
 	}
-?>
+?>