SecretKey::getPublicKey()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
/**
4
 * Copyright (c) 2020 UMI
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in all
14
 * copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
 * SOFTWARE.
23
 */
24
25
declare(strict_types=1);
26
27
namespace UmiTop\UmiCore\Key\Ed25519;
28
29
use Exception;
30
use UmiTop\UmiCore\Key\PublicKeyInterface;
31
use UmiTop\UmiCore\Key\SecretKeyInterface;
32
use UmiTop\UmiCore\Util\Ed25519\Ed25519;
33
34
/**
35
 * Класс для работы с приватными ключами.
36
 * @package UmiTop\UmiCore\Key\Ed25519
37
 */
38
class SecretKey implements SecretKeyInterface
39
{
40
    /** @var int Длина приватного ключа в байтах. */
41
    public const LENGTH = 64;
42
43
    /** @var string Приватный ключ в бинарном виде. */
44
    private $bytes;
45
46
    /**
47
     * SecretKey constructor.
48
     * @param string $bytes Приватный ключ в бинарном виде. В формате libsodium, 64 байта.
49
     * @throws Exception
50
     */
51 8
    public function __construct(string $bytes)
52
    {
53 8
        if (strlen($bytes) !== self::LENGTH) {
54 1
            throw new Exception('secret key size should be 64 bytes');
55
        }
56
57 7
        $this->bytes = $bytes;
58 7
    }
59
60
    /**
61
     * Статический метод, создающий приватный ключ из seed.
62
     * Libsodium принимает seed длиной 32 байта, поэтому если длина отличается, то берется sha256 хэш.
63
     * @param string $seed Бинарная строка любой длины.
64
     * @return SecretKeyInterface
65
     * @codeCoverageIgnore
66
     */
67
    public static function fromSeed(string $seed): SecretKeyInterface
68
    {
69
        if (strlen($seed) !== Ed25519::SEED_BYTES) {
70
            $seed = hash('sha256', $seed, true);
71
        }
72
73
        if (function_exists('sodium_crypto_sign_seed_keypair') === true) {
74
            $bytes = sodium_crypto_sign_secretkey(
75
                sodium_crypto_sign_seed_keypair($seed)
76
            );
77
78
            return new SecretKey($bytes);
79
        }
80
81
        $ed25519 = new Ed25519();
82
        $bytes = $ed25519->secretKeyFromSeed($seed);
83
84
        return new SecretKey($bytes);
85
    }
86
87
    /**
88
     * Приватный ключ в бинарном виде. В формате libsodium, 64 байта.
89
     * @return string
90
     */
91 1
    public function getBytes(): string
92
    {
93 1
        return $this->bytes;
94
    }
95
96
    /**
97
     * Публичный ключ, соответствующий приватному ключу.
98
     * @return PublicKeyInterface
99
     */
100 5
    public function getPublicKey(): PublicKeyInterface
101
    {
102 5
        return new PublicKey(substr($this->bytes, 32, 32));
103
    }
104
105
    /**
106
     * Создает цифровую подпись сообщения.
107
     * @param string $message Сообщение в бинарном виде.
108
     * @return string
109
     * @codeCoverageIgnore
110
     */
111
    public function sign(string $message): string
112
    {
113
        if (function_exists('sodium_crypto_sign_detached') === true) {
114
            return sodium_crypto_sign_detached($message, $this->bytes);
115
        }
116
117
        $ed25519 = new Ed25519();
118
119
        return $ed25519->sign($message, $this->bytes);
120
    }
121
}
122