EcDH   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 30
c 1
b 0
f 0
dl 0
loc 124
rs 10
wmc 13

7 Methods

Rating   Name   Duplication   Size   Complexity  
A setSenderKey() 0 4 1
A calculateSharedKey() 0 5 1
A calculateKey() 0 14 3
A __construct() 0 3 1
A checkExchangeState() 0 18 5
A createMultiPartyKey() 0 5 1
A setRecipientKey() 0 4 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Mdanter\Ecc\Crypto\EcDH;
5
6
/**
7
 * *********************************************************************
8
 * Copyright (C) 2012 Matyas Danter
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining
11
 * a copy of this software and associated documentation files (the "Software"),
12
 * to deal in the Software without restriction, including without limitation
13
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14
 * and/or sell copies of the Software, and to permit persons to whom the
15
 * Software is furnished to do so, subject to the following conditions:
16
 *
17
 * The above copyright notice and this permission notice shall be included
18
 * in all copies or substantial portions of the Software.
19
 *
20
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
24
 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26
 * OTHER DEALINGS IN THE SOFTWARE.
27
 * ***********************************************************************
28
 */
29
30
use Mdanter\Ecc\Crypto\Key\PrivateKeyInterface;
31
use Mdanter\Ecc\Crypto\Key\PublicKeyInterface;
32
use Mdanter\Ecc\Exception\ExchangeException;
33
use Mdanter\Ecc\Math\GmpMathInterface;
34
35
/**
36
 * This class is the implementation of ECDH.
37
 * EcDH is safe key exchange and achieves
38
 * that a key is transported securely between two parties.
39
 * The key then can be hashed and used as a basis in
40
 * a dual encryption scheme, along with AES for faster
41
 * two- way encryption.
42
 */
43
class EcDH implements EcDHInterface
44
{
45
    /**
46
     * Adapter used for math calculations
47
     *
48
     * @var GmpMathInterface
49
     */
50
    private $adapter;
51
52
    /**
53
     * Secret key between the two parties
54
     *
55
     * @var PublicKeyInterface
56
     */
57
    private $secretKey = null;
58
59
    /**
60
     *
61
     * @var PublicKeyInterface
62
     */
63
    private $recipientKey;
64
65
    /**
66
     *
67
     * @var PrivateKeyInterface
68
     */
69
    private $senderKey;
70
71
    /**
72
     * Initialize a new exchange from a generator point.
73
     *
74
     * @param GmpMathInterface $adapter A math adapter instance.
75
     */
76
    public function __construct(GmpMathInterface $adapter)
77
    {
78
        $this->adapter = $adapter;
79
    }
80
81
    /**
82
     * {@inheritDoc}
83
     * @see \Mdanter\Ecc\Crypto\EcDH\EcDHInterface::calculateSharedKey()
84
     */
85
    public function calculateSharedKey(): \GMP
86
    {
87
        $this->calculateKey();
88
89
        return $this->secretKey->getPoint()->getX();
90
    }
91
92
    /**
93
     * {@inheritDoc}
94
     * @see \Mdanter\Ecc\Crypto\EcDH\EcDHInterface::createMultiPartyKey()
95
     */
96
    public function createMultiPartyKey(): PublicKeyInterface
97
    {
98
        $this->calculateKey();
99
100
        return $this->secretKey;
101
    }
102
103
    /**
104
     * {@inheritDoc}
105
     * @see \Mdanter\Ecc\Crypto\EcDH\EcDHInterface::setRecipientKey()
106
     */
107
    public function setRecipientKey(PublicKeyInterface $key = null)
108
    {
109
        $this->recipientKey = $key;
110
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Mdanter\Ecc\Crypto\EcDH\EcDH which is incompatible with the return type mandated by Mdanter\Ecc\Crypto\EcDH\...face::setRecipientKey() of void.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
111
    }
112
113
    /**
114
     * {@inheritDoc}
115
     * @see \Mdanter\Ecc\Crypto\EcDH\EcDHInterface::setSenderKey()
116
     */
117
    public function setSenderKey(PrivateKeyInterface $key)
118
    {
119
        $this->senderKey = $key;
120
        return $this;
121
    }
122
123
    /**
124
     *
125
     */
126
    private function calculateKey()
127
    {
128
        $this->checkExchangeState();
129
130
        if ($this->secretKey === null) {
131
            try {
132
                // Multiply our secret with recipients public key
133
                $point = $this->recipientKey->getPoint()->mul($this->senderKey->getSecret());
134
135
                // Ensure we completed a valid exchange, ensure we can create a
136
                // public key instance for the shared secret using our generator.
137
                $this->secretKey = $this->senderKey->getPoint()->getPublicKeyFrom($point->getX(), $point->getY());
138
            } catch (\Exception $e) {
139
                throw new ExchangeException("Invalid ECDH exchange", 0, $e);
140
            }
141
        }
142
    }
143
144
    /**
145
     * Verifies that the shared secret is known, or that the required keys are available
146
     * to calculate the shared secret.
147
     * @throws \RuntimeException when the exchange has not been made.
148
     */
149
    private function checkExchangeState()
150
    {
151
        if ($this->secretKey !== null) {
152
            return;
153
        }
154
155
        if ($this->senderKey === null) {
156
            throw new ExchangeException('Sender key not set.');
157
        }
158
159
        if ($this->recipientKey === null) {
160
            throw new ExchangeException('Recipient key not set.');
161
        }
162
163
        // Check the point exists on our curve.
164
        $point = $this->recipientKey->getPoint();
165
        if (!$this->senderKey->getPoint()->getCurve()->contains($point->getX(), $point->getY())) {
166
            throw new ExchangeException("Invalid ECDH exchange - Point does not exist on our curve");
167
        }
168
    }
169
}
170