├── .styleci.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── composer.json └── src ├── Caster.php ├── Encrypted.php └── Password.php /.styleci.yml: -------------------------------------------------------------------------------- 1 | risky: true 2 | version: 7 3 | 4 | tab-width: 4 5 | use-tabs: true 6 | 7 | preset: symfony 8 | 9 | enabled: 10 | - ternary_to_null_coalescing 11 | 12 | disabled: 13 | - phpdoc_align 14 | - symfony_braces 15 | - new_with_braces 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 1.5.0 4 | 5 | ### Updated 6 | - Laravel 10. 7 | 8 | ## 1.4.0 9 | 10 | ### Updated 11 | - Laravel 9. 12 | 13 | ## 1.3.0 14 | 15 | ### Updated 16 | - Laravel 8. 17 | 18 | ## 1.2.1 19 | 20 | ### Fixed 21 | - Casting to datetime. 22 | 23 | ## 1.2.0 24 | 25 | ### Fixed 26 | - Null handling (null will now decrypt to null, and null already encrypted to null). 27 | 28 | ### Changed 29 | - Uses `Hash::make()` instead of `bcrypt`. 30 | 31 | ## 1.1.0 32 | 33 | ### Added 34 | - Hashing. 35 | 36 | ### Updated 37 | - Readme. 38 | 39 | ## 1.0.0. Initial release 40 | 41 | ### Added 42 | - This package. 43 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## TODO 2 | 3 | - Upgrade to Laravel 8 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Glaive.pro 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Encrypted 2 | 3 | [![Build Status](https://img.shields.io/travis/crudly/Encrypted/master?style=flat-square)](https://travis-ci.org/crudly/encrypted) 4 | [![Release](https://img.shields.io/github/v/release/crudly/Encrypted?style=flat-square)](https://github.com/crudly/Encrypted/releases/latest) 5 | [![License](https://img.shields.io/packagist/l/crudly/encrypted?style=flat-square)](LICENSE) 6 | 7 | > **Note** This package is no longer needed for new projects as [hashing is now](https://github.com/laravel/framework/pull/46947) 8 | > among the native casts and encryption was there for a while already. 9 | > We will probably keep it up to date for a few more years because it usually only takes bumping a version tag. 10 | 11 | A custom cast class for Laravel Eloquent that encrypts or hashes your values. Package is small and provides just a few, simple, well tested features. 12 | 13 | ```php 14 | protected $casts = [ 15 | // hashes the value when assigning to $model->password 16 | 'password' => Password::class, 17 | 18 | // encrypts on write, decrypts on read 19 | 'classified' => Encrypted::class, 20 | 21 | // encrypts on write, decrypts & typecasts on read 22 | 'secret' => Encrypted::class.':integer', 23 | ]; 24 | ``` 25 | 26 | ## Installation 27 | 28 | Use composer. 29 | 30 | ```bash 31 | $ composer require crudly/encrypted 32 | ``` 33 | 34 | ## Usage 35 | 36 | Mark any column in your model as encrypted. 37 | 38 | ```php 39 | Encrypted::class, 50 | ]; 51 | } 52 | ``` 53 | 54 | You can work with the attribute as you normally would, but it will be encrypted on the database. 55 | 56 | ```php 57 | $mm = new MyModel; 58 | 59 | $mm->someting_secret = 'classified_info'; 60 | $mm->save(); 61 | ``` 62 | 63 | ### Type casting 64 | 65 | Encryption serializes the variable and decryption unserializes it, so you get out exactly what you put in. This usually means that no type casting is needed. 66 | 67 | But sometimes you want everything casted to some type even if you put something else in. In those cases you can specify types (all of Eloquent's default casts are supported): 68 | 69 | ```php 70 | Encrypted::class, 81 | 'an_integer' => Encrypted::class.':integer', 82 | 'a_string' => Encrypted::class.':string', 83 | 'decimal_with_two_places' => Encrypted::class.':decimal:2', 84 | ]; 85 | } 86 | ``` 87 | 88 | ### Password hashing 89 | 90 | This can also be used to hash a password upon write. 91 | 92 | ```php 93 | Password::class, 104 | ]; 105 | } 106 | ``` 107 | 108 | This hashes the password using `bcrypt`. You can check a string against the hashed password using `Hash` facade. 109 | 110 | ```php 111 | $mu = new MyUser; 112 | $mu->password = 'secret'; 113 | 114 | $mu->password; // returns a hash 115 | 116 | Hash::check('secret', $mu->password); //returns true 117 | Hash::check('hunter2', $mu->password); //returns false 118 | ``` 119 | 120 | # TODO 121 | 122 | Maybe add key and cipher customization via options, i.e. `Encrypted::class.':string,AckfSECXIvnK5r28GVIWUAxmbBSjTsmF'` and `Encrypted::class.':string,AckfSECXIvnK5r28GVIWUAxmbBSjTsmF,AES-128-CBC'`. And password hashing options. 123 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crudly/encrypted", 3 | "description": "Encryption and hashing casts for Eloquent", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "Larzs", 8 | "email": "wester@inbox.lv", 9 | "homepage": "https://github.com/orgs/crudly/people/Larzs" 10 | }, 11 | { 12 | "name": "Juris Evertovskis", 13 | "email": "juris@glaive.pro", 14 | "homepage": "https://github.com/tontonsb" 15 | } 16 | ], 17 | "homepage": "https://github.com/crudly/encrypted", 18 | "keywords": ["Laravel", "Eloquent", "Encryption", "Hashing"], 19 | "require": { 20 | "laravel/framework": "^9.0|^10.0|^11.0" 21 | }, 22 | "require-dev": { 23 | "phpunit/phpunit": "^9.0|^10.0", 24 | "orchestra/testbench": "^7.0|^8.0" 25 | }, 26 | "autoload": { 27 | "psr-4": { 28 | "Crudly\\Encrypted\\": "src" 29 | } 30 | }, 31 | "autoload-dev": { 32 | "psr-4": { 33 | "Crudly\\Encrypted\\Tests\\": "tests" 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Caster.php: -------------------------------------------------------------------------------- 1 | castType = $castType; 29 | } 30 | 31 | /** 32 | * Coerce value to type. 33 | */ 34 | public function coerce($value) 35 | { 36 | if (!\is_string($value)) 37 | { 38 | if (\in_array($this->castType, ['array', 'json'])) 39 | return (array) $value; 40 | 41 | if ('collection' == $this->castType) 42 | return $value instanceof Collection ? $value : collect($value); 43 | 44 | if ('object' == $this->castType) 45 | return (object) $value; 46 | 47 | if (\in_array($this->castType, ['date', 'datetime']) && \is_object($value)) 48 | return (object) $value; 49 | } 50 | 51 | // Don't specify key, we override getCastType to provide correct type. 52 | return $this->castAttribute(null, $value); 53 | } 54 | 55 | /** 56 | * Get the type of cast. Used by HasAttributes::castAttribute. 57 | */ 58 | protected function getCastType(): string 59 | { 60 | if ($this->isCustomDateTimeCast($this->castType)) 61 | return 'custom_datetime'; 62 | 63 | if ($this->isDecimalCast($this->castType)) 64 | return 'decimal'; 65 | 66 | return trim(strtolower($this->castType)); 67 | } 68 | 69 | /** 70 | * Tell HasAttributes::castAttribute that we don't use further casting classes. 71 | * Might allow in the future if there are some use cases. 72 | */ 73 | protected function isClassCastable(): bool 74 | { 75 | return false; 76 | } 77 | 78 | /** 79 | * Scam the casts array for HasAttributes::castAttribute. 80 | */ 81 | public function getCasts(): array 82 | { 83 | return [null => $this->castType]; 84 | } 85 | 86 | /** 87 | * Set the model property. 88 | */ 89 | public function setModel(Model $model): void 90 | { 91 | $this->model = $model; 92 | } 93 | 94 | /** 95 | * Get the format for dates from the model. 96 | */ 97 | public function getDateFormat(): string 98 | { 99 | return $this->model->getDateFormat(); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/Encrypted.php: -------------------------------------------------------------------------------- 1 | castType = 'null' === $castType ? null : $castType; 25 | 26 | if ($this->castType) 27 | $this->caster = new Caster($castType); 28 | } 29 | 30 | /** 31 | * Cast the given value. 32 | * 33 | * @param \Illuminate\Database\Eloquent\Model $model 34 | * @param mixed $value 35 | * 36 | * @return mixed 37 | */ 38 | public function get($model, string $key, $value, array $attributes) 39 | { 40 | if (null !== $value) 41 | $value = decrypt($value); 42 | 43 | if (!$this->castType) 44 | return $value; 45 | 46 | $this->caster->setModel($model); 47 | 48 | return $this->caster->coerce($value); 49 | } 50 | 51 | /** 52 | * Prepare the given value for storage. 53 | * 54 | * @param \Illuminate\Database\Eloquent\Model $model 55 | * @param mixed $value 56 | * 57 | * @return string 58 | */ 59 | public function set($model, string $key, $value, array $attributes) 60 | { 61 | return encrypt($value); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Password.php: -------------------------------------------------------------------------------- 1 |