Failed Conditions
Push — v7 ( a687dc...e264c8 )
by Florent
02:28
created

CurveFp   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 201
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 6
dl 0
loc 201
rs 10
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getModAdapter() 0 4 1
A getPoint() 0 4 1
A getInfinity() 0 4 1
A getGenerator() 0 4 1
A recoverYfromX() 0 22 2
A contains() 0 20 1
A getA() 0 4 1
A getB() 0 4 1
A getPrime() 0 4 1
A getSize() 0 4 1
A cmp() 0 10 2
A equals() 0 4 1
A __toString() 0 4 1
A __debugInfo() 0 8 1
1
<?php
2
3
/***********************************************************************
4
Copyright (C) 2012 Matyas Danter
5
6
Permission is hereby granted, free of charge, to any person obtaining
7
a copy of this software and associated documentation files (the "Software"),
8
to deal in the Software without restriction, including without limitation
9
the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
and/or sell copies of the Software, and to permit persons to whom the
11
Software is furnished to do so, subject to the following conditions:
12
13
The above copyright notice and this permission notice shall be included
14
in all copies or substantial portions of the Software.
15
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
20
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
OTHER DEALINGS IN THE SOFTWARE.
23
 *************************************************************************/
24
namespace Jose\Component\Core\Util\Ecc\Primitives;
25
26
use Jose\Component\Core\Util\Ecc\Math\GmpMath;
27
use Jose\Component\Core\Util\Ecc\Math\ModularArithmetic;
28
use Jose\Component\Core\Util\Ecc\Random\RandomNumberGenerator;
29
30
/**
31
 * This class is a representation of an EC over a field modulo a prime number
32
 *
33
 * Important objectives for this class are:
34
 * - Does the curve contain a point?
35
 * - Comparison of two curves.
36
 */
37
final class CurveFp
38
{
39
40
    /**
41
     * @var CurveParameters
42
     */
43
    protected $parameters;
44
45
    /**
46
     *
47
     * @var GmpMath
48
     */
49
    protected $adapter = null;
50
51
    /**
52
     *
53
     * @var ModularArithmetic
54
     */
55
    protected $modAdapter = null;
56
57
    /**
58
     * Constructor that sets up the instance variables.
59
     *
60
     * @param CurveParameters $parameters
61
     * @param GmpMath $adapter
62
     */
63
    public function __construct(CurveParameters $parameters, GmpMath $adapter)
64
    {
65
        $this->parameters = $parameters;
66
        $this->adapter = $adapter;
67
        $this->modAdapter = new ModularArithmetic($this->adapter, $this->parameters->getPrime());
68
    }
69
70
    /**
71
     * {@inheritDoc}
72
     * @see \Jose\Component\Core\Util\Ecc\CurveFp::getModAdapter()
73
     */
74
    public function getModAdapter()
75
    {
76
        return $this->modAdapter;
77
    }
78
79
    /**
80
     * {@inheritDoc}
81
     * @see \Jose\Component\Core\Util\Ecc\CurveFp::getPoint()
82
     */
83
    public function getPoint(\GMP $x, \GMP $y, \GMP $order = null)
84
    {
85
        return new Point($this->adapter, $this, $x, $y, $order);
86
    }
87
    
88
    /**
89
     * {@inheritDoc}
90
     * @see \Jose\Component\Core\Util\Ecc\CurveFp::getInfinity()
91
     */
92
    public function getInfinity()
93
    {
94
        return new Point($this->adapter, $this, gmp_init(0, 10), gmp_init(0, 10), null, true);
95
    }
96
97
    /**
98
     * {@inheritDoc}
99
     * @see \Jose\Component\Core\Util\Ecc\CurveFp::getGenerator()
100
     */
101
    public function getGenerator(\GMP $x, \GMP $y, \GMP $order, RandomNumberGenerator $randomGenerator = null)
102
    {
103
        return new GeneratorPoint($this->adapter, $this, $x, $y, $order, $randomGenerator);
104
    }
105
106
    /**
107
     * @param bool $wasOdd
108
     * @param \GMP $xCoord
109
     * @return \GMP
110
     */
111
    public function recoverYfromX($wasOdd, \GMP $xCoord)
112
    {
113
        $math = $this->adapter;
114
        $prime = $this->getPrime();
115
116
        $root = $this->adapter->getNumberTheory()->squareRootModP(
117
            $math->add(
118
                $math->add(
119
                    $this->modAdapter->pow($xCoord, gmp_init(3, 10)),
120
                    $math->mul($this->getA(), $xCoord)
121
                ),
122
                $this->getB()
123
            ),
124
            $prime
125
        );
126
127
        if ($math->equals($math->mod($root, gmp_init(2, 10)), gmp_init(1)) === $wasOdd) {
128
            return $root;
129
        } else {
130
            return $math->sub($prime, $root);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $math->sub($prime, $root); (resource) is incompatible with the return type documented by Jose\Component\Core\Util...\CurveFp::recoverYfromX of type GMP.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
131
        }
132
    }
133
    /**
134
     * {@inheritDoc}
135
     * @see \Jose\Component\Core\Util\Ecc\CurveFp::contains()
136
     */
137
    public function contains(\GMP $x, \GMP $y)
138
    {
139
        $math = $this->adapter;
140
141
        $eq_zero = $math->equals(
142
            $this->modAdapter->sub(
143
                $math->pow($y, 2),
144
                $math->add(
145
                    $math->add(
146
                        $math->pow($x, 3),
147
                        $math->mul($this->getA(), $x)
148
                    ),
149
                    $this->getB()
150
                )
151
            ),
152
            gmp_init(0, 10)
153
        );
154
155
        return $eq_zero;
156
    }
157
158
    /**
159
     * {@inheritDoc}
160
     * @see \Jose\Component\Core\Util\Ecc\CurveFp::getA()
161
     */
162
    public function getA()
163
    {
164
        return $this->parameters->getA();
165
    }
166
167
    /**
168
     * {@inheritDoc}
169
     * @see \Jose\Component\Core\Util\Ecc\CurveFp::getB()
170
     */
171
    public function getB()
172
    {
173
        return $this->parameters->getB();
174
    }
175
176
    /**
177
     * {@inheritDoc}
178
     * @see \Jose\Component\Core\Util\Ecc\CurveFp::getPrime()
179
     */
180
    public function getPrime()
181
    {
182
        return $this->parameters->getPrime();
183
    }
184
185
    /**
186
     * @return int
187
     */
188
    public function getSize()
189
    {
190
        return $this->parameters->getSize();
191
    }
192
193
    /**
194
     * {@inheritDoc}
195
     * @see \Jose\Component\Core\Util\Ecc\CurveFp::cmp()
196
     */
197
    public function cmp(CurveFp $other)
198
    {
199
        $math = $this->adapter;
200
201
        $equal  = $math->equals($this->getA(), $other->getA());
202
        $equal &= $math->equals($this->getB(), $other->getB());
203
        $equal &= $math->equals($this->getPrime(), $other->getPrime());
204
205
        return ($equal) ? 0 : 1;
206
    }
207
208
    /**
209
     * {@inheritDoc}
210
     * @see \Jose\Component\Core\Util\Ecc\CurveFp::equals()
211
     */
212
    public function equals(CurveFp $other)
213
    {
214
        return $this->cmp($other) == 0;
215
    }
216
217
    /**
218
     * {@inheritDoc}
219
     * @see \Jose\Component\Core\Util\Ecc\CurveFp::__toString()
220
     */
221
    public function __toString()
222
    {
223
        return 'curve(' . $this->adapter->toString($this->getA()) . ', ' . $this->adapter->toString($this->getB()) . ', ' . $this->adapter->toString($this->getPrime()) . ')';
224
    }
225
226
    /**
227
     * @return array
228
     */
229
    public function __debugInfo()
230
    {
231
        return [
232
            'a' => $this->adapter->toString($this->getA()),
233
            'b' => $this->adapter->toString($this->getB()),
234
            'prime' => $this->adapter->toString($this->getPrime())
235
        ];
236
    }
237
}
238