Completed
Push — master ( 6e4edc...cbed4d )
by Felix
02:48
created

PhPsst::generateKey()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 16
ccs 0
cts 13
cp 0
rs 9.4285
cc 3
eloc 12
nc 3
nop 0
crap 12
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\Storage;
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 Storage
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 Storage $storage
39
     * @param string $cipher
40
     */
41 5
    public function __construct(Storage $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 = $this->generateKey();
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 5
        $id = preg_replace("/[^a-zA-Z\d]/", '', $id);
93
94 5
        if (!($password = $this->storage->get($id))) {
95 3
            throw new PhPsstException('No password with that ID found', PhPsstException::NO_PASSWORD_WITH_ID_FOUND);
96
        }
97 4
        $encrypter = new Encrypter($key, $this->cipher);
98
99 4
        $password->decreaseViews();
100 4
        if ($password->getViews() > 0) {
101 2
            $this->storage->store($password, true);
102 2
        } else {
103 2
            $this->storage->delete($password);
104
        }
105
106 4
        return $encrypter->decrypt($password->getPassword());
107
    }
108
109
    /**
110
     * @return string
111
     */
112
    protected function generateKey()
113
    {
114
        $key = null;
0 ignored issues
show
Unused Code introduced by
$key is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
115
        switch ($this->cipher) {
116
            case 'AES-128-CBC':
117
                $key = bin2hex(random_bytes(8));
118
                break;
119
            case 'AES-256-CBC':
120
                $key = bin2hex(random_bytes(16));
121
                break;
122
            default:
123
                throw new \RuntimeException('Only supported ciphers are AES-128-CBC and AES-256-CBC');
124
        }
125
126
        return $key;
127
    }
128
}
129