Passed
Push — php72 ( ef4f38...0629fc )
by Joni
01:46
created
lib/AESKW/AESKeyWrapAlgorithm.php 1 patch
Indentation   +64 added lines, -64 removed lines patch added patch discarded remove patch
@@ -13,71 +13,71 @@
 block discarded – undo
13 13
  */
14 14
 interface AESKeyWrapAlgorithm
15 15
 {
16
-    /**
17
-     * Wrap a key using given key encryption key.
18
-     *
19
-     * Key length must be at least 64 bits (8 octets) and a multiple
20
-     * of 64 bits (8 octets). Use `wrapPad()` to wrap a key of arbitrary length.
21
-     *
22
-     * Key encryption key must have a size of underlying AES algorithm,
23
-     * ie. 128, 196 or 256 bits.
24
-     *
25
-     * @see https://tools.ietf.org/html/rfc3394#section-2.2.1
26
-     *
27
-     * @param string $key Key to wrap
28
-     * @param string $kek Key encryption key
29
-     *
30
-     * @throws \RuntimeException For invalid inputs
31
-     *
32
-     * @return string Ciphertext
33
-     */
34
-    public function wrap(string $key, string $kek): string;
16
+	/**
17
+	 * Wrap a key using given key encryption key.
18
+	 *
19
+	 * Key length must be at least 64 bits (8 octets) and a multiple
20
+	 * of 64 bits (8 octets). Use `wrapPad()` to wrap a key of arbitrary length.
21
+	 *
22
+	 * Key encryption key must have a size of underlying AES algorithm,
23
+	 * ie. 128, 196 or 256 bits.
24
+	 *
25
+	 * @see https://tools.ietf.org/html/rfc3394#section-2.2.1
26
+	 *
27
+	 * @param string $key Key to wrap
28
+	 * @param string $kek Key encryption key
29
+	 *
30
+	 * @throws \RuntimeException For invalid inputs
31
+	 *
32
+	 * @return string Ciphertext
33
+	 */
34
+	public function wrap(string $key, string $kek): string;
35 35
 
36
-    /**
37
-     * Unwrap a key from a ciphertext using given key encryption key.
38
-     *
39
-     * @see https://tools.ietf.org/html/rfc3394#section-2.2.2
40
-     *
41
-     * @param string $ciphertext Ciphertext of the wrapped key
42
-     * @param string $kek        Key encryption key
43
-     *
44
-     * @throws \RuntimeException For invalid inputs
45
-     *
46
-     * @return string Unwrapped key
47
-     */
48
-    public function unwrap(string $ciphertext, string $kek): string;
36
+	/**
37
+	 * Unwrap a key from a ciphertext using given key encryption key.
38
+	 *
39
+	 * @see https://tools.ietf.org/html/rfc3394#section-2.2.2
40
+	 *
41
+	 * @param string $ciphertext Ciphertext of the wrapped key
42
+	 * @param string $kek        Key encryption key
43
+	 *
44
+	 * @throws \RuntimeException For invalid inputs
45
+	 *
46
+	 * @return string Unwrapped key
47
+	 */
48
+	public function unwrap(string $ciphertext, string $kek): string;
49 49
 
50
-    /**
51
-     * Wrap a key of arbitrary length using given key encryption key.
52
-     *
53
-     * This variant of wrapping does not place any restriction on key size.
54
-     *
55
-     * Key encryption key has the same restrictions as with `wrap()` method.
56
-     *
57
-     * @see https://tools.ietf.org/html/rfc5649#section-4.1
58
-     *
59
-     * @param string $key Key to wrap
60
-     * @param string $kek Key encryption key
61
-     *
62
-     * @throws \RuntimeException For invalid inputs
63
-     *
64
-     * @return string Ciphertext
65
-     */
66
-    public function wrapPad(string $key, string $kek): string;
50
+	/**
51
+	 * Wrap a key of arbitrary length using given key encryption key.
52
+	 *
53
+	 * This variant of wrapping does not place any restriction on key size.
54
+	 *
55
+	 * Key encryption key has the same restrictions as with `wrap()` method.
56
+	 *
57
+	 * @see https://tools.ietf.org/html/rfc5649#section-4.1
58
+	 *
59
+	 * @param string $key Key to wrap
60
+	 * @param string $kek Key encryption key
61
+	 *
62
+	 * @throws \RuntimeException For invalid inputs
63
+	 *
64
+	 * @return string Ciphertext
65
+	 */
66
+	public function wrapPad(string $key, string $kek): string;
67 67
 
68
-    /**
69
-     * Unwrap a key from a padded ciphertext using given key encryption key.
70
-     *
71
-     * This variant of unwrapping must be used if the key was wrapped using `wrapPad()`.
72
-     *
73
-     * @see https://tools.ietf.org/html/rfc5649#section-4.2
74
-     *
75
-     * @param string $ciphertext Ciphertext of the wrapped and padded key
76
-     * @param string $kek        Key encryption key
77
-     *
78
-     * @throws \RuntimeException For invalid inputs
79
-     *
80
-     * @return string Unwrapped key
81
-     */
82
-    public function unwrapPad(string $ciphertext, string $kek): string;
68
+	/**
69
+	 * Unwrap a key from a padded ciphertext using given key encryption key.
70
+	 *
71
+	 * This variant of unwrapping must be used if the key was wrapped using `wrapPad()`.
72
+	 *
73
+	 * @see https://tools.ietf.org/html/rfc5649#section-4.2
74
+	 *
75
+	 * @param string $ciphertext Ciphertext of the wrapped and padded key
76
+	 * @param string $kek        Key encryption key
77
+	 *
78
+	 * @throws \RuntimeException For invalid inputs
79
+	 *
80
+	 * @return string Unwrapped key
81
+	 */
82
+	public function unwrapPad(string $ciphertext, string $kek): string;
83 83
 }
Please login to merge, or discard this patch.
lib/AESKW/Algorithm.php 1 patch
Indentation   +461 added lines, -461 removed lines patch added patch discarded remove patch
@@ -11,487 +11,487 @@
 block discarded – undo
11 11
  */
12 12
 abstract class Algorithm implements AESKeyWrapAlgorithm
13 13
 {
14
-    /**
15
-     * Default initial value.
16
-     *
17
-     * @see https://tools.ietf.org/html/rfc3394#section-2.2.3.1
18
-     *
19
-     * @var string
20
-     */
21
-    const DEFAULT_IV = "\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6";
14
+	/**
15
+	 * Default initial value.
16
+	 *
17
+	 * @see https://tools.ietf.org/html/rfc3394#section-2.2.3.1
18
+	 *
19
+	 * @var string
20
+	 */
21
+	const DEFAULT_IV = "\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6";
22 22
 
23
-    /**
24
-     * High order bytes of the alternative initial value for padding.
25
-     *
26
-     * @see https://tools.ietf.org/html/rfc5649#section-3
27
-     *
28
-     * @var string
29
-     */
30
-    const AIV_HI = "\xA6\x59\x59\xA6";
23
+	/**
24
+	 * High order bytes of the alternative initial value for padding.
25
+	 *
26
+	 * @see https://tools.ietf.org/html/rfc5649#section-3
27
+	 *
28
+	 * @var string
29
+	 */
30
+	const AIV_HI = "\xA6\x59\x59\xA6";
31 31
 
32
-    /**
33
-     * Initial value.
34
-     *
35
-     * @var string
36
-     */
37
-    protected $_iv;
32
+	/**
33
+	 * Initial value.
34
+	 *
35
+	 * @var string
36
+	 */
37
+	protected $_iv;
38 38
 
39
-    /**
40
-     * Constructor.
41
-     *
42
-     * @param string $iv Initial value
43
-     */
44
-    public function __construct(string $iv = self::DEFAULT_IV)
45
-    {
46
-        if (8 !== strlen($iv)) {
47
-            throw new \UnexpectedValueException('IV size must be 64 bits.');
48
-        }
49
-        $this->_iv = $iv;
50
-    }
39
+	/**
40
+	 * Constructor.
41
+	 *
42
+	 * @param string $iv Initial value
43
+	 */
44
+	public function __construct(string $iv = self::DEFAULT_IV)
45
+	{
46
+		if (8 !== strlen($iv)) {
47
+			throw new \UnexpectedValueException('IV size must be 64 bits.');
48
+		}
49
+		$this->_iv = $iv;
50
+	}
51 51
 
52
-    /**
53
-     * Wrap a key using given key encryption key.
54
-     *
55
-     * Key length must be at least 64 bits (8 octets) and a multiple
56
-     * of 64 bits (8 octets). Use `wrapPad()` to wrap a key of arbitrary length.
57
-     *
58
-     * Key encryption key must have a size of underlying AES algorithm,
59
-     * ie. 128, 196 or 256 bits.
60
-     *
61
-     * @param string $key Key to wrap
62
-     * @param string $kek Key encryption key
63
-     *
64
-     * @throws \UnexpectedValueException If the key length is invalid
65
-     *
66
-     * @return string Ciphertext
67
-     */
68
-    public function wrap(string $key, string $kek): string
69
-    {
70
-        $key_len = strlen($key);
71
-        // rfc3394 dictates n to be at least 2
72
-        if ($key_len < 16) {
73
-            throw new \UnexpectedValueException(
74
-                'Key length must be at least 16 octets.');
75
-        }
76
-        if (0 !== $key_len % 8) {
77
-            throw new \UnexpectedValueException(
78
-                'Key length must be a multiple of 64 bits.');
79
-        }
80
-        $this->_checkKEKSize($kek);
81
-        // P = plaintext as 64 bit blocks
82
-        $P = [];
83
-        $i = 1;
84
-        foreach (str_split($key, 8) as $val) {
85
-            $P[$i++] = $val;
86
-        }
87
-        $C = $this->_wrapBlocks($P, $kek, $this->_iv);
88
-        return implode('', $C);
89
-    }
52
+	/**
53
+	 * Wrap a key using given key encryption key.
54
+	 *
55
+	 * Key length must be at least 64 bits (8 octets) and a multiple
56
+	 * of 64 bits (8 octets). Use `wrapPad()` to wrap a key of arbitrary length.
57
+	 *
58
+	 * Key encryption key must have a size of underlying AES algorithm,
59
+	 * ie. 128, 196 or 256 bits.
60
+	 *
61
+	 * @param string $key Key to wrap
62
+	 * @param string $kek Key encryption key
63
+	 *
64
+	 * @throws \UnexpectedValueException If the key length is invalid
65
+	 *
66
+	 * @return string Ciphertext
67
+	 */
68
+	public function wrap(string $key, string $kek): string
69
+	{
70
+		$key_len = strlen($key);
71
+		// rfc3394 dictates n to be at least 2
72
+		if ($key_len < 16) {
73
+			throw new \UnexpectedValueException(
74
+				'Key length must be at least 16 octets.');
75
+		}
76
+		if (0 !== $key_len % 8) {
77
+			throw new \UnexpectedValueException(
78
+				'Key length must be a multiple of 64 bits.');
79
+		}
80
+		$this->_checkKEKSize($kek);
81
+		// P = plaintext as 64 bit blocks
82
+		$P = [];
83
+		$i = 1;
84
+		foreach (str_split($key, 8) as $val) {
85
+			$P[$i++] = $val;
86
+		}
87
+		$C = $this->_wrapBlocks($P, $kek, $this->_iv);
88
+		return implode('', $C);
89
+	}
90 90
 
91
-    /**
92
-     * Unwrap a key from a ciphertext using given key encryption key.
93
-     *
94
-     * @param string $ciphertext Ciphertext of the wrapped key
95
-     * @param string $kek        Key encryption key
96
-     *
97
-     * @throws \UnexpectedValueException If the ciphertext is invalid
98
-     *
99
-     * @return string Unwrapped key
100
-     */
101
-    public function unwrap(string $ciphertext, string $kek): string
102
-    {
103
-        if (0 !== strlen($ciphertext) % 8) {
104
-            throw new \UnexpectedValueException(
105
-                'Ciphertext length must be a multiple of 64 bits.');
106
-        }
107
-        $this->_checkKEKSize($kek);
108
-        // C = ciphertext as 64 bit blocks with integrity check value prepended
109
-        $C = str_split($ciphertext, 8);
110
-        [$A, $R] = $this->_unwrapBlocks($C, $kek);
111
-        // check integrity value
112
-        if (!hash_equals($this->_iv, $A)) {
113
-            throw new \UnexpectedValueException('Integrity check failed.');
114
-        }
115
-        // output the plaintext
116
-        $P = array_slice($R, 1, null, true);
117
-        return implode('', $P);
118
-    }
91
+	/**
92
+	 * Unwrap a key from a ciphertext using given key encryption key.
93
+	 *
94
+	 * @param string $ciphertext Ciphertext of the wrapped key
95
+	 * @param string $kek        Key encryption key
96
+	 *
97
+	 * @throws \UnexpectedValueException If the ciphertext is invalid
98
+	 *
99
+	 * @return string Unwrapped key
100
+	 */
101
+	public function unwrap(string $ciphertext, string $kek): string
102
+	{
103
+		if (0 !== strlen($ciphertext) % 8) {
104
+			throw new \UnexpectedValueException(
105
+				'Ciphertext length must be a multiple of 64 bits.');
106
+		}
107
+		$this->_checkKEKSize($kek);
108
+		// C = ciphertext as 64 bit blocks with integrity check value prepended
109
+		$C = str_split($ciphertext, 8);
110
+		[$A, $R] = $this->_unwrapBlocks($C, $kek);
111
+		// check integrity value
112
+		if (!hash_equals($this->_iv, $A)) {
113
+			throw new \UnexpectedValueException('Integrity check failed.');
114
+		}
115
+		// output the plaintext
116
+		$P = array_slice($R, 1, null, true);
117
+		return implode('', $P);
118
+	}
119 119
 
120
-    /**
121
-     * Wrap a key of arbitrary length using given key encryption key.
122
-     *
123
-     * This variant of wrapping does not place any restriction on key size.
124
-     *
125
-     * Key encryption key has the same restrictions as with `wrap()` method.
126
-     *
127
-     * @param string $key Key to wrap
128
-     * @param string $kek Key encryption key
129
-     *
130
-     * @throws \UnexpectedValueException If the key length is invalid
131
-     *
132
-     * @return string Ciphertext
133
-     */
134
-    public function wrapPad(string $key, string $kek): string
135
-    {
136
-        if (!strlen($key)) {
137
-            throw new \UnexpectedValueException(
138
-                'Key must have at least one octet.');
139
-        }
140
-        $this->_checkKEKSize($kek);
141
-        [$key, $aiv] = $this->_padKey($key);
142
-        // If the padded key contains exactly eight octets,
143
-        // let the ciphertext be:
144
-        // C[0] | C[1] = ENC(K, A | P[1]).
145
-        if (8 === strlen($key)) {
146
-            return $this->_encrypt($kek, $aiv . $key);
147
-        }
148
-        // build plaintext blocks and apply normal wrapping with AIV as an
149
-        // initial value
150
-        $P = [];
151
-        $i = 1;
152
-        foreach (str_split($key, 8) as $val) {
153
-            $P[$i++] = $val;
154
-        }
155
-        $C = $this->_wrapBlocks($P, $kek, $aiv);
156
-        return implode('', $C);
157
-    }
120
+	/**
121
+	 * Wrap a key of arbitrary length using given key encryption key.
122
+	 *
123
+	 * This variant of wrapping does not place any restriction on key size.
124
+	 *
125
+	 * Key encryption key has the same restrictions as with `wrap()` method.
126
+	 *
127
+	 * @param string $key Key to wrap
128
+	 * @param string $kek Key encryption key
129
+	 *
130
+	 * @throws \UnexpectedValueException If the key length is invalid
131
+	 *
132
+	 * @return string Ciphertext
133
+	 */
134
+	public function wrapPad(string $key, string $kek): string
135
+	{
136
+		if (!strlen($key)) {
137
+			throw new \UnexpectedValueException(
138
+				'Key must have at least one octet.');
139
+		}
140
+		$this->_checkKEKSize($kek);
141
+		[$key, $aiv] = $this->_padKey($key);
142
+		// If the padded key contains exactly eight octets,
143
+		// let the ciphertext be:
144
+		// C[0] | C[1] = ENC(K, A | P[1]).
145
+		if (8 === strlen($key)) {
146
+			return $this->_encrypt($kek, $aiv . $key);
147
+		}
148
+		// build plaintext blocks and apply normal wrapping with AIV as an
149
+		// initial value
150
+		$P = [];
151
+		$i = 1;
152
+		foreach (str_split($key, 8) as $val) {
153
+			$P[$i++] = $val;
154
+		}
155
+		$C = $this->_wrapBlocks($P, $kek, $aiv);
156
+		return implode('', $C);
157
+	}
158 158
 
159
-    /**
160
-     * Unwrap a key from a padded ciphertext using given key encryption key.
161
-     *
162
-     * This variant of unwrapping must be used if the key was wrapped using `wrapPad()`.
163
-     *
164
-     * @param string $ciphertext Ciphertext of the wrapped and padded key
165
-     * @param string $kek        Key encryption key
166
-     *
167
-     * @throws \UnexpectedValueException If the ciphertext is invalid
168
-     *
169
-     * @return string Unwrapped key
170
-     */
171
-    public function unwrapPad(string $ciphertext, string $kek): string
172
-    {
173
-        if (0 !== strlen($ciphertext) % 8) {
174
-            throw new \UnexpectedValueException(
175
-                'Ciphertext length must be a multiple of 64 bits.');
176
-        }
177
-        $this->_checkKEKSize($kek);
178
-        [$P, $A] = $this->_unwrapPaddedCiphertext($ciphertext, $kek);
179
-        // check message integrity
180
-        $this->_checkPaddedIntegrity($A);
181
-        // verify padding
182
-        $len = $this->_verifyPadding($P, $A);
183
-        // remove padding and return unwrapped key
184
-        return substr(implode('', $P), 0, $len);
185
-    }
159
+	/**
160
+	 * Unwrap a key from a padded ciphertext using given key encryption key.
161
+	 *
162
+	 * This variant of unwrapping must be used if the key was wrapped using `wrapPad()`.
163
+	 *
164
+	 * @param string $ciphertext Ciphertext of the wrapped and padded key
165
+	 * @param string $kek        Key encryption key
166
+	 *
167
+	 * @throws \UnexpectedValueException If the ciphertext is invalid
168
+	 *
169
+	 * @return string Unwrapped key
170
+	 */
171
+	public function unwrapPad(string $ciphertext, string $kek): string
172
+	{
173
+		if (0 !== strlen($ciphertext) % 8) {
174
+			throw new \UnexpectedValueException(
175
+				'Ciphertext length must be a multiple of 64 bits.');
176
+		}
177
+		$this->_checkKEKSize($kek);
178
+		[$P, $A] = $this->_unwrapPaddedCiphertext($ciphertext, $kek);
179
+		// check message integrity
180
+		$this->_checkPaddedIntegrity($A);
181
+		// verify padding
182
+		$len = $this->_verifyPadding($P, $A);
183
+		// remove padding and return unwrapped key
184
+		return substr(implode('', $P), 0, $len);
185
+	}
186 186
 
187
-    /**
188
-     * Get OpenSSL cipher method.
189
-     *
190
-     * @return string
191
-     */
192
-    abstract protected function _cipherMethod(): string;
187
+	/**
188
+	 * Get OpenSSL cipher method.
189
+	 *
190
+	 * @return string
191
+	 */
192
+	abstract protected function _cipherMethod(): string;
193 193
 
194
-    /**
195
-     * Get key encryption key size.
196
-     *
197
-     * @return int
198
-     */
199
-    abstract protected function _keySize(): int;
194
+	/**
195
+	 * Get key encryption key size.
196
+	 *
197
+	 * @return int
198
+	 */
199
+	abstract protected function _keySize(): int;
200 200
 
201
-    /**
202
-     * Check KEK size.
203
-     *
204
-     * @param string $kek
205
-     *
206
-     * @throws \UnexpectedValueException
207
-     *
208
-     * @return self
209
-     */
210
-    protected function _checkKEKSize(string $kek): self
211
-    {
212
-        $len = $this->_keySize();
213
-        if (strlen($kek) !== $len) {
214
-            throw new \UnexpectedValueException("KEK size must be {$len} bytes.");
215
-        }
216
-        return $this;
217
-    }
201
+	/**
202
+	 * Check KEK size.
203
+	 *
204
+	 * @param string $kek
205
+	 *
206
+	 * @throws \UnexpectedValueException
207
+	 *
208
+	 * @return self
209
+	 */
210
+	protected function _checkKEKSize(string $kek): self
211
+	{
212
+		$len = $this->_keySize();
213
+		if (strlen($kek) !== $len) {
214
+			throw new \UnexpectedValueException("KEK size must be {$len} bytes.");
215
+		}
216
+		return $this;
217
+	}
218 218
 
219
-    /**
220
-     * Apply Key Wrap to data blocks.
221
-     *
222
-     * Uses alternative version of the key wrap procedure described in the RFC.
223
-     *
224
-     * @see https://tools.ietf.org/html/rfc3394#section-2.2.1
225
-     *
226
-     * @param string[] $P   Plaintext, n 64-bit values `{P1, P2, ..., Pn}`
227
-     * @param string   $kek Key encryption key
228
-     * @param string   $iv  Initial value
229
-     *
230
-     * @return string[] Ciphertext, (n+1) 64-bit values `{C0, C1, ..., Cn}`
231
-     */
232
-    protected function _wrapBlocks(array $P, string $kek, string $iv): array
233
-    {
234
-        $n = count($P);
235
-        // Set A = IV
236
-        $A = $iv;
237
-        // For i = 1 to n
238
-        //   R[i] = P[i]
239
-        $R = $P;
240
-        // For j = 0 to 5
241
-        for ($j = 0; $j <= 5; ++$j) {
242
-            // For i = 1 to n
243
-            for ($i = 1; $i <= $n; ++$i) {
244
-                // B = AES(K, A | R[i])
245
-                $B = $this->_encrypt($kek, $A . $R[$i]);
246
-                // A = MSB(64, B) ^ t where t = (n*j)+i
247
-                $t = $n * $j + $i;
248
-                $A = $this->_msb64($B) ^ $this->_uint64($t);
249
-                // R[i] = LSB(64, B)
250
-                $R[$i] = $this->_lsb64($B);
251
-            }
252
-        }
253
-        // Set C[0] = A
254
-        $C = [$A];
255
-        // For i = 1 to n
256
-        for ($i = 1; $i <= $n; ++$i) {
257
-            // C[i] = R[i]
258
-            $C[$i] = $R[$i];
259
-        }
260
-        return $C;
261
-    }
219
+	/**
220
+	 * Apply Key Wrap to data blocks.
221
+	 *
222
+	 * Uses alternative version of the key wrap procedure described in the RFC.
223
+	 *
224
+	 * @see https://tools.ietf.org/html/rfc3394#section-2.2.1
225
+	 *
226
+	 * @param string[] $P   Plaintext, n 64-bit values `{P1, P2, ..., Pn}`
227
+	 * @param string   $kek Key encryption key
228
+	 * @param string   $iv  Initial value
229
+	 *
230
+	 * @return string[] Ciphertext, (n+1) 64-bit values `{C0, C1, ..., Cn}`
231
+	 */
232
+	protected function _wrapBlocks(array $P, string $kek, string $iv): array
233
+	{
234
+		$n = count($P);
235
+		// Set A = IV
236
+		$A = $iv;
237
+		// For i = 1 to n
238
+		//   R[i] = P[i]
239
+		$R = $P;
240
+		// For j = 0 to 5
241
+		for ($j = 0; $j <= 5; ++$j) {
242
+			// For i = 1 to n
243
+			for ($i = 1; $i <= $n; ++$i) {
244
+				// B = AES(K, A | R[i])
245
+				$B = $this->_encrypt($kek, $A . $R[$i]);
246
+				// A = MSB(64, B) ^ t where t = (n*j)+i
247
+				$t = $n * $j + $i;
248
+				$A = $this->_msb64($B) ^ $this->_uint64($t);
249
+				// R[i] = LSB(64, B)
250
+				$R[$i] = $this->_lsb64($B);
251
+			}
252
+		}
253
+		// Set C[0] = A
254
+		$C = [$A];
255
+		// For i = 1 to n
256
+		for ($i = 1; $i <= $n; ++$i) {
257
+			// C[i] = R[i]
258
+			$C[$i] = $R[$i];
259
+		}
260
+		return $C;
261
+	}
262 262
 
263
-    /**
264
-     * Unwrap the padded ciphertext producing plaintext and integrity value.
265
-     *
266
-     * @param string $ciphertext Ciphertext
267
-     * @param string $kek        Encryption key
268
-     *
269
-     * @return array Tuple of plaintext `{P1, P2, ..., Pn}` and integrity value `A`
270
-     */
271
-    protected function _unwrapPaddedCiphertext(string $ciphertext, string $kek): array
272
-    {
273
-        // split to blocks
274
-        $C = str_split($ciphertext, 8);
275
-        $n = count($C) - 1;
276
-        // if key consists of only one block, recover AIV and padded key as:
277
-        // A | P[1] = DEC(K, C[0] | C[1])
278
-        if (1 === $n) {
279
-            $P = str_split($this->_decrypt($kek, $C[0] . $C[1]), 8);
280
-            $A = $P[0];
281
-            unset($P[0]);
282
-        } else {
283
-            // apply normal unwrapping
284
-            [$A, $R] = $this->_unwrapBlocks($C, $kek);
285
-            $P = array_slice($R, 1, null, true);
286
-        }
287
-        return [$P, $A];
288
-    }
263
+	/**
264
+	 * Unwrap the padded ciphertext producing plaintext and integrity value.
265
+	 *
266
+	 * @param string $ciphertext Ciphertext
267
+	 * @param string $kek        Encryption key
268
+	 *
269
+	 * @return array Tuple of plaintext `{P1, P2, ..., Pn}` and integrity value `A`
270
+	 */
271
+	protected function _unwrapPaddedCiphertext(string $ciphertext, string $kek): array
272
+	{
273
+		// split to blocks
274
+		$C = str_split($ciphertext, 8);
275
+		$n = count($C) - 1;
276
+		// if key consists of only one block, recover AIV and padded key as:
277
+		// A | P[1] = DEC(K, C[0] | C[1])
278
+		if (1 === $n) {
279
+			$P = str_split($this->_decrypt($kek, $C[0] . $C[1]), 8);
280
+			$A = $P[0];
281
+			unset($P[0]);
282
+		} else {
283
+			// apply normal unwrapping
284
+			[$A, $R] = $this->_unwrapBlocks($C, $kek);
285
+			$P = array_slice($R, 1, null, true);
286
+		}
287
+		return [$P, $A];
288
+	}
289 289
 
290
-    /**
291
-     * Apply Key Unwrap to data blocks.
292
-     *
293
-     * Uses the index based version of key unwrap procedure described in the RFC.
294
-     *
295
-     * Does not compute step 3.
296
-     *
297
-     * @see https://tools.ietf.org/html/rfc3394#section-2.2.2
298
-     *
299
-     * @param string[] $C   Ciphertext, (n+1) 64-bit values `{C0, C1, ..., Cn}`
300
-     * @param string   $kek Key encryption key
301
-     *
302
-     * @throws \UnexpectedValueException
303
-     *
304
-     * @return array Tuple of integrity value `A` and register `R`
305
-     */
306
-    protected function _unwrapBlocks(array $C, string $kek): array
307
-    {
308
-        $n = count($C) - 1;
309
-        if (!$n) {
310
-            throw new \UnexpectedValueException('No blocks.');
311
-        }
312
-        // Set A = C[0]
313
-        $A = $C[0];
314
-        // For i = 1 to n
315
-        //   R[i] = C[i]
316
-        $R = $C;
317
-        // For j = 5 to 0
318
-        for ($j = 5; $j >= 0; --$j) {
319
-            // For i = n to 1
320
-            for ($i = $n; $i >= 1; --$i) {
321
-                // B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
322
-                $t = $n * $j + $i;
323
-                $B = $this->_decrypt($kek, ($A ^ $this->_uint64($t)) . $R[$i]);
324
-                // A = MSB(64, B)
325
-                $A = $this->_msb64($B);
326
-                // R[i] = LSB(64, B)
327
-                $R[$i] = $this->_lsb64($B);
328
-            }
329
-        }
330
-        return [$A, $R];
331
-    }
290
+	/**
291
+	 * Apply Key Unwrap to data blocks.
292
+	 *
293
+	 * Uses the index based version of key unwrap procedure described in the RFC.
294
+	 *
295
+	 * Does not compute step 3.
296
+	 *
297
+	 * @see https://tools.ietf.org/html/rfc3394#section-2.2.2
298
+	 *
299
+	 * @param string[] $C   Ciphertext, (n+1) 64-bit values `{C0, C1, ..., Cn}`
300
+	 * @param string   $kek Key encryption key
301
+	 *
302
+	 * @throws \UnexpectedValueException
303
+	 *
304
+	 * @return array Tuple of integrity value `A` and register `R`
305
+	 */
306
+	protected function _unwrapBlocks(array $C, string $kek): array
307
+	{
308
+		$n = count($C) - 1;
309
+		if (!$n) {
310
+			throw new \UnexpectedValueException('No blocks.');
311
+		}
312
+		// Set A = C[0]
313
+		$A = $C[0];
314
+		// For i = 1 to n
315
+		//   R[i] = C[i]
316
+		$R = $C;
317
+		// For j = 5 to 0
318
+		for ($j = 5; $j >= 0; --$j) {
319
+			// For i = n to 1
320
+			for ($i = $n; $i >= 1; --$i) {
321
+				// B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
322
+				$t = $n * $j + $i;
323
+				$B = $this->_decrypt($kek, ($A ^ $this->_uint64($t)) . $R[$i]);
324
+				// A = MSB(64, B)
325
+				$A = $this->_msb64($B);
326
+				// R[i] = LSB(64, B)
327
+				$R[$i] = $this->_lsb64($B);
328
+			}
329
+		}
330
+		return [$A, $R];
331
+	}
332 332
 
333
-    /**
334
-     * Pad a key with zeroes and compute alternative initial value.
335
-     *
336
-     * @param string $key Key
337
-     *
338
-     * @return array Tuple of padded key and AIV
339
-     */
340
-    protected function _padKey(string $key): array
341
-    {
342
-        $len = strlen($key);
343
-        // append padding
344
-        if (0 !== $len % 8) {
345
-            $key .= str_repeat("\0", 8 - $len % 8);
346
-        }
347
-        // compute AIV
348
-        $mli = pack('N', $len);
349
-        $aiv = self::AIV_HI . $mli;
350
-        return [$key, $aiv];
351
-    }
333
+	/**
334
+	 * Pad a key with zeroes and compute alternative initial value.
335
+	 *
336
+	 * @param string $key Key
337
+	 *
338
+	 * @return array Tuple of padded key and AIV
339
+	 */
340
+	protected function _padKey(string $key): array
341
+	{
342
+		$len = strlen($key);
343
+		// append padding
344
+		if (0 !== $len % 8) {
345
+			$key .= str_repeat("\0", 8 - $len % 8);
346
+		}
347
+		// compute AIV
348
+		$mli = pack('N', $len);
349
+		$aiv = self::AIV_HI . $mli;
350
+		return [$key, $aiv];
351
+	}
352 352
 
353
-    /**
354
-     * Check that the integrity check value of the padded key is correct.
355
-     *
356
-     * @param string $A
357
-     *
358
-     * @throws \UnexpectedValueException
359
-     */
360
-    protected function _checkPaddedIntegrity(string $A): void
361
-    {
362
-        // check that MSB(32,A) = A65959A6
363
-        if (!hash_equals(self::AIV_HI, substr($A, 0, 4))) {
364
-            throw new \UnexpectedValueException('Integrity check failed.');
365
-        }
366
-    }
353
+	/**
354
+	 * Check that the integrity check value of the padded key is correct.
355
+	 *
356
+	 * @param string $A
357
+	 *
358
+	 * @throws \UnexpectedValueException
359
+	 */
360
+	protected function _checkPaddedIntegrity(string $A): void
361
+	{
362
+		// check that MSB(32,A) = A65959A6
363
+		if (!hash_equals(self::AIV_HI, substr($A, 0, 4))) {
364
+			throw new \UnexpectedValueException('Integrity check failed.');
365
+		}
366
+	}
367 367
 
368
-    /**
369
-     * Verify that the padding of the plaintext is valid.
370
-     *
371
-     * @param array  $P Plaintext, n 64-bit values `{P1, P2, ..., Pn}`
372
-     * @param string $A Integrity check value
373
-     *
374
-     * @throws \UnexpectedValueException
375
-     *
376
-     * @return int Message length without padding
377
-     */
378
-    protected function _verifyPadding(array $P, string $A): int
379
-    {
380
-        // extract mli
381
-        $mli = substr($A, -4);
382
-        $len = unpack('N1', $mli)[1];
383
-        // check under and overflow
384
-        $n = count($P);
385
-        if (8 * ($n - 1) >= $len || $len > 8 * $n) {
386
-            throw new \UnexpectedValueException('Invalid message length.');
387
-        }
388
-        // if key is padded
389
-        $b = 8 - ($len % 8);
390
-        if ($b < 8) {
391
-            // last block (note that the first index in P is 1)
392
-            $Pn = $P[$n];
393
-            // check that padding consists of zeroes
394
-            if (substr($Pn, -$b) !== str_repeat("\0", $b)) {
395
-                throw new \UnexpectedValueException('Invalid padding.');
396
-            }
397
-        }
398
-        return $len;
399
-    }
368
+	/**
369
+	 * Verify that the padding of the plaintext is valid.
370
+	 *
371
+	 * @param array  $P Plaintext, n 64-bit values `{P1, P2, ..., Pn}`
372
+	 * @param string $A Integrity check value
373
+	 *
374
+	 * @throws \UnexpectedValueException
375
+	 *
376
+	 * @return int Message length without padding
377
+	 */
378
+	protected function _verifyPadding(array $P, string $A): int
379
+	{
380
+		// extract mli
381
+		$mli = substr($A, -4);
382
+		$len = unpack('N1', $mli)[1];
383
+		// check under and overflow
384
+		$n = count($P);
385
+		if (8 * ($n - 1) >= $len || $len > 8 * $n) {
386
+			throw new \UnexpectedValueException('Invalid message length.');
387
+		}
388
+		// if key is padded
389
+		$b = 8 - ($len % 8);
390
+		if ($b < 8) {
391
+			// last block (note that the first index in P is 1)
392
+			$Pn = $P[$n];
393
+			// check that padding consists of zeroes
394
+			if (substr($Pn, -$b) !== str_repeat("\0", $b)) {
395
+				throw new \UnexpectedValueException('Invalid padding.');
396
+			}
397
+		}
398
+		return $len;
399
+	}
400 400
 
401
-    /**
402
-     * Apply AES(K, W) operation (encrypt) to 64 bit block.
403
-     *
404
-     * @param string $kek
405
-     * @param string $block
406
-     *
407
-     * @throws \RuntimeException If encrypt fails
408
-     *
409
-     * @return string
410
-     */
411
-    protected function _encrypt(string $kek, string $block): string
412
-    {
413
-        $str = openssl_encrypt($block, $this->_cipherMethod(), $kek,
414
-            OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
415
-        if (false === $str) {
416
-            throw new \RuntimeException(
417
-                'openssl_encrypt() failed: ' . $this->_getLastOpenSSLError());
418
-        }
419
-        return $str;
420
-    }
401
+	/**
402
+	 * Apply AES(K, W) operation (encrypt) to 64 bit block.
403
+	 *
404
+	 * @param string $kek
405
+	 * @param string $block
406
+	 *
407
+	 * @throws \RuntimeException If encrypt fails
408
+	 *
409
+	 * @return string
410
+	 */
411
+	protected function _encrypt(string $kek, string $block): string
412
+	{
413
+		$str = openssl_encrypt($block, $this->_cipherMethod(), $kek,
414
+			OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
415
+		if (false === $str) {
416
+			throw new \RuntimeException(
417
+				'openssl_encrypt() failed: ' . $this->_getLastOpenSSLError());
418
+		}
419
+		return $str;
420
+	}
421 421
 
422
-    /**
423
-     * Apply AES-1(K, W) operation (decrypt) to 64 bit block.
424
-     *
425
-     * @param string $kek
426
-     * @param string $block
427
-     *
428
-     * @throws \RuntimeException If decrypt fails
429
-     *
430
-     * @return string
431
-     */
432
-    protected function _decrypt(string $kek, string $block): string
433
-    {
434
-        $str = openssl_decrypt($block, $this->_cipherMethod(), $kek,
435
-            OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
436
-        if (false === $str) {
437
-            throw new \RuntimeException(
438
-                'openssl_decrypt() failed: ' . $this->_getLastOpenSSLError());
439
-        }
440
-        return $str;
441
-    }
422
+	/**
423
+	 * Apply AES-1(K, W) operation (decrypt) to 64 bit block.
424
+	 *
425
+	 * @param string $kek
426
+	 * @param string $block
427
+	 *
428
+	 * @throws \RuntimeException If decrypt fails
429
+	 *
430
+	 * @return string
431
+	 */
432
+	protected function _decrypt(string $kek, string $block): string
433
+	{
434
+		$str = openssl_decrypt($block, $this->_cipherMethod(), $kek,
435
+			OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
436
+		if (false === $str) {
437
+			throw new \RuntimeException(
438
+				'openssl_decrypt() failed: ' . $this->_getLastOpenSSLError());
439
+		}
440
+		return $str;
441
+	}
442 442
 
443
-    /**
444
-     * Get the latest OpenSSL error message.
445
-     *
446
-     * @return string
447
-     */
448
-    protected function _getLastOpenSSLError(): string
449
-    {
450
-        $msg = '';
451
-        while (false !== ($err = openssl_error_string())) {
452
-            $msg = $err;
453
-        }
454
-        return $msg;
455
-    }
443
+	/**
444
+	 * Get the latest OpenSSL error message.
445
+	 *
446
+	 * @return string
447
+	 */
448
+	protected function _getLastOpenSSLError(): string
449
+	{
450
+		$msg = '';
451
+		while (false !== ($err = openssl_error_string())) {
452
+			$msg = $err;
453
+		}
454
+		return $msg;
455
+	}
456 456
 
457
-    /**
458
-     * Take 64 most significant bits from value.
459
-     *
460
-     * @param string $val
461
-     *
462
-     * @return string
463
-     */
464
-    protected function _msb64(string $val): string
465
-    {
466
-        return substr($val, 0, 8);
467
-    }
457
+	/**
458
+	 * Take 64 most significant bits from value.
459
+	 *
460
+	 * @param string $val
461
+	 *
462
+	 * @return string
463
+	 */
464
+	protected function _msb64(string $val): string
465
+	{
466
+		return substr($val, 0, 8);
467
+	}
468 468
 
469
-    /**
470
-     * Take 64 least significant bits from value.
471
-     *
472
-     * @param string $val
473
-     *
474
-     * @return string
475
-     */
476
-    protected function _lsb64(string $val): string
477
-    {
478
-        return substr($val, -8);
479
-    }
469
+	/**
470
+	 * Take 64 least significant bits from value.
471
+	 *
472
+	 * @param string $val
473
+	 *
474
+	 * @return string
475
+	 */
476
+	protected function _lsb64(string $val): string
477
+	{
478
+		return substr($val, -8);
479
+	}
480 480
 
481
-    /**
482
-     * Convert number to 64 bit unsigned integer octet string with
483
-     * most significant bit first.
484
-     *
485
-     * @param int $num
486
-     *
487
-     * @return string
488
-     */
489
-    protected function _uint64(int $num): string
490
-    {
491
-        // truncate on 32 bit hosts
492
-        if (PHP_INT_SIZE < 8) {
493
-            return "\0\0\0\0" . pack('N', $num);
494
-        }
495
-        return pack('J', $num);
496
-    }
481
+	/**
482
+	 * Convert number to 64 bit unsigned integer octet string with
483
+	 * most significant bit first.
484
+	 *
485
+	 * @param int $num
486
+	 *
487
+	 * @return string
488
+	 */
489
+	protected function _uint64(int $num): string
490
+	{
491
+		// truncate on 32 bit hosts
492
+		if (PHP_INT_SIZE < 8) {
493
+			return "\0\0\0\0" . pack('N', $num);
494
+		}
495
+		return pack('J', $num);
496
+	}
497 497
 }
Please login to merge, or discard this patch.