Passed
Pull Request — master (#43)
by Tim
02:10
created

SymmetricKey::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\XMLSecurity\Key;
6
7
use SimpleSAML\XMLSecurity\Utils\Random;
8
9
use function chr;
10
use function ord;
11
use function strlen;
12
13
/**
14
 * A class to model symmetric key secrets.
15
 *
16
 * New SymmetricKey objects can be created passing a given secret to the constructor, or using the static method
17
 * generate(), which will return a SymmetricKey object with a random secret material.
18
 *
19
 * Note that random secrets generated by this class will be cryptographically secure.
20
 *
21
 * @package simplesamlphp/xml-security
22
 */
23
class SymmetricKey implements KeyInterface
24
{
25
    /** @var string */
26
    protected string $material;
27
28
29
    /**
30
     * Build a new key with $key as its material.
31
     *
32
     * @param string $key The associated key material.
33
     */
34
    public function __construct(string $key)
35
    {
36
        $this->material = $key;
37
    }
38
39
40
    /**
41
     * Return the key material associated with this key.
42
     *
43
     * @return string The key material.
44
     */
45
    public function getMaterial(): string
46
    {
47
        return $this->material;
48
    }
49
50
51
    /**
52
     * Generate a random, binary secret key of a given length.
53
     *
54
     * If the key is intended to be used with 3DES in CBC mode, pass true in $parityBits.
55
     *
56
     * @param positive-int $length The length of the secret we want, in bytes.
1 ignored issue
show
Documentation Bug introduced by
The doc comment positive-int at position 0 could not be parsed: Unknown type name 'positive-int' at position 0 in positive-int.
Loading history...
57
     * @param bool $parityBits Whether the key should be suitable for its use in 3DES in CBC mode or not.
58
     *
59
     * @return \SimpleSAML\XMLSecurity\Key\SymmetricKey A cryptographically-secure random symmetric key.
60
     *
61
     * @throws \SimpleSAML\XMLSecurity\Exception\RuntimeException If no appropriate sources of cryptographically-secure
62
     *   random material are available.
63
     */
64
    public static function generate(int $length, bool $parityBits = false): SymmetricKey
65
    {
66
        $key = Random::generateRandomBytes($length);
67
68
        if ($parityBits) {
69
            /*
70
             * Make sure that the generated key has the proper parity bits set.
71
             * Mcrypt doesn't care about the parity bits, but others may care.
72
             */
73
            for ($i = 0; $i < strlen($key); $i++) {
74
                $byte = ord($key[$i]) & 0xfe;
75
                $parity = 1;
76
                for ($j = 1; $j < 8; $j++) {
77
                    $parity ^= ($byte >> $j) & 1;
78
                }
79
                $byte |= $parity;
80
                $key[$i] = chr($byte);
81
            }
82
        }
83
84
        return new self($key);
85
    }
86
87
88
    /**
89
     * Get the length of this symmetric key, in bytes.
90
     *
91
     * @return int The length of the key.
92
     */
93
    public function getLength(): int
94
    {
95
        return strlen($this->getMaterial());
96
    }
97
}
98