Completed
Push — master ( d0dfb4...2f1abc )
by Felix
02:52
created

PhPsst   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 89
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 100%

Importance

Changes 6
Bugs 0 Features 2
Metric Value
wmc 11
c 6
b 0
f 2
lcom 1
cbo 4
dl 0
loc 89
ccs 34
cts 34
cp 1
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
B store() 0 24 4
B retrieve() 0 21 5
A __construct() 0 9 2
1
<?php
2
/**
3
 * PhPsst.
4
 *
5
 * @copyright Copyright (c) 2016 Felix Sandström
6
 * @license   MIT
7
 */
8
9
namespace PhPsst;
10
11
use Illuminate\Encryption\Encrypter;
12
use PhPsst\Storage\StorageInterface;
13
14
/**
15
 * A PHP library for distributing (one time) passwords/secrets in a more secure way.
16
 *
17
 * @author Felix Sandström <http://github.com/felixsand>
18
 */
19
class PhPsst
20
{
21
    /**
22
     * @var StorageInterface
23
     */
24
    protected $storage;
25
26
    /**
27
     * @var string
28
     */
29
    protected $cipher;
30
31
    /**
32
     * @const string
33
     */
34
    const CIPHER_DEFAULT = 'AES-256-CBC';
35
36
    /**
37
     * PhPsst constructor.
38
     * @param StorageInterface $storage
39
     * @param string $cipher
40
     */
41 5
    public function __construct(StorageInterface $storage, $cipher = null)
42
    {
43 5
        $this->storage = $storage;
44 5
        if ($cipher !== null) {
45 1
            $this->cipher = $cipher;
46 1
        } else {
47 5
            $this->cipher = self::CIPHER_DEFAULT;
48
        }
49 5
    }
50
51
    /**
52
     * @param string $password
53
     * @param int $ttl
54
     * @param int $views
55
     * @return string
56
     */
57 7
    public function store($password, $ttl = 3600, $views = 1)
58
    {
59 7
        if (empty($password)) {
60 1
            throw new \InvalidArgumentException('The password has to be set');
61
        }
62
63 6
        $ttl = (int) $ttl;
64 6
        if ($ttl < 1) {
65 1
            throw new \InvalidArgumentException('TTL has to be higher than 0');
66
        }
67
68 5
        $views = (int) $views;
69 5
        if ($views < 1) {
70 1
            throw new \InvalidArgumentException('Views has to be highter han 0');
71
        }
72
73 4
        $id = uniqid();
74 4
        $key = bin2hex(random_bytes(16));
75 4
        $encrypter = new Encrypter($key, $this->cipher);
76
77 4
        $this->storage->store(new Password($id, $encrypter->encrypt($password), $ttl, $views));
78
79 4
        return $id . ';' . $key;
80
    }
81
82
    /**
83
     * @param $secret
84
     * @return string
85
     */
86 6
    public function retrieve($secret)
87
    {
88 6
        if (!($idKeyArray = explode(';', $secret)) || count($idKeyArray) != 2) {
89 1
            throw new \InvalidArgumentException('Invalid secret');
90
        }
91 5
        list($id, $key) = $idKeyArray;
92
93 5
        if (!($password = $this->storage->get($id))) {
94 1
            throw new PhPsstException('No password with that ID found', PhPsstException::NO_PASSWORD_WITH_ID_FOUND);
95
        }
96 4
        $encrypter = new Encrypter($key, $this->cipher);
97
98 4
        $password->decreaseViews();
99 4
        if ($password->getViews() > 0) {
100 2
            $this->storage->store($password, true);
101 2
        } else {
102 2
            $this->storage->delete($password);
103
        }
104
105 4
        return $encrypter->decrypt($password->getPassword());
106
    }
107
}
108