SignHasher::getAlgorithm()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

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
rs 10
1
<?php
2
3
namespace Mdanter\Ecc\Crypto\Signature;
4
5
use Mdanter\Ecc\EccFactory;
6
use Mdanter\Ecc\Math\GmpMathInterface;
7
use Mdanter\Ecc\Primitives\GeneratorPoint;
8
use Mdanter\Ecc\Util\BinaryString;
9
use Mdanter\Ecc\Util\NumberSize;
10
11
class SignHasher implements HasherInterface
12
{
13
    /**
14
     * @var int[]
15
     */
16
    protected static $sizeMap = [
17
        'sha1' => 20,
18
        'sha224' => 28,
19
        'sha256' => 32,
20
        'sha384' => 48,
21
        'sha512' => 64,
22
    ];
23
24
    /**
25
     * @var GmpMathInterface
26
     */
27
    private $adapter;
28
29
    /**
30
     * @var string
31
     */
32
    private $algorithm;
33
34
    /**
35
     * SignHasher constructor.
36
     * @param string $algorithm
37
     * @param GmpMathInterface|null $math
38
     */
39
    public function __construct(string $algorithm, GmpMathInterface $math = null)
40
    {
41
        if (!array_key_exists($algorithm, self::$sizeMap)) {
42
            throw new \InvalidArgumentException("Unsupported hashing algorithm");
43
        }
44
45
        $this->algorithm = $algorithm;
46
        $this->adapter = $math ?: EccFactory::getAdapter();
47
    }
48
49
    /**
50
     * @return string
51
     */
52
    public function getAlgorithm(): string
53
    {
54
        return $this->algorithm;
55
    }
56
57
    /**
58
     * @return int
59
     */
60
    public function getLengthInBytes(): int
61
    {
62
        return self::$sizeMap[$this->algorithm];
63
    }
64
65
    /**
66
     * @param string $data
67
     * @return string
68
     */
69
    public function makeRawHash(string $data): string
70
    {
71
        return hash($this->algorithm, $data, false);
72
    }
73
74
    /**
75
     * @param \GMP $hash
76
     * @param GeneratorPoint $G
77
     * @return \GMP
78
     */
79
    public function truncateForECDSA(\GMP $hash, GeneratorPoint $G)
80
    {
81
        $hashBits = gmp_strval($hash, 2);
82
        if (BinaryString::length($hashBits) < self::$sizeMap[$this->algorithm] * 8) {
83
            $hashBits = str_pad($hashBits, self::$sizeMap[$this->algorithm] * 8, '0', STR_PAD_LEFT);
84
        }
85
86
        return gmp_init(BinaryString::substring($hashBits, 0, NumberSize::bnNumBits($this->adapter, $G->getOrder())), 2);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_init(Mdanter\...r, $G->getOrder())), 2) also could return the type resource which is incompatible with the documented return type GMP.
Loading history...
87
    }
88
89
    /**
90
     * @param string $data
91
     * @param GeneratorPoint $G
92
     * @return \GMP
93
     */
94
    public function makeHash(string $data, GeneratorPoint $G): \GMP
95
    {
96
        $hash = gmp_init($this->makeRawHash($data), 16);
97
        return $this->truncateForECDSA($hash, $G);
0 ignored issues
show
Bug introduced by
It seems like $hash can also be of type resource; however, parameter $hash of Mdanter\Ecc\Crypto\Signa...her::truncateForECDSA() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

97
        return $this->truncateForECDSA(/** @scrutinizer ignore-type */ $hash, $G);
Loading history...
98
    }
99
}
100