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

PhPsst::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 9
ccs 7
cts 7
cp 1
rs 9.6666
cc 2
eloc 6
nc 2
nop 2
crap 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