Skip to content

Commit 7a9f9d7

Browse files
committed
MAGETWO-64613: Implement service to enrypt collected data
1 parent a35599d commit 7a9f9d7

File tree

12 files changed

+1023
-86
lines changed

12 files changed

+1023
-86
lines changed

app/code/Magento/Analytics/Controller/Adminhtml/Export/Example.php

Lines changed: 0 additions & 57 deletions
This file was deleted.

app/code/Magento/Analytics/Model/Cryptographer.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ public function encode($source)
5858
} catch (\Exception $e) {
5959
throw new LocalizedException(__('Input data must be string or convertible into string.'));
6060
}
61+
} elseif (!$source) {
62+
throw new LocalizedException(__('Input data must be non-empty string.'));
6163
}
6264
if (!$this->validateCipherMethod($this->cipherMethod)) {
6365
throw new LocalizedException(__('Not valid cipher method.'));
@@ -81,11 +83,13 @@ public function encode($source)
8183
/**
8284
* Return key for encryption.
8385
*
86+
* Random initial value for key used in case of empty token value to prevent a vulnerability with a predicted key.
87+
*
8488
* @return string
8589
*/
8690
private function getKey()
8791
{
88-
return hash('sha256', $this->analyticsToken->getToken());
92+
return hash('sha256', $this->analyticsToken->getToken() ?: openssl_random_pseudo_bytes(256));
8993
}
9094

9195
/**

app/code/Magento/Analytics/Model/ExportDataHandler.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public function prepareExportData()
120120
*
121121
* @return string
122122
*/
123-
public function getTmpFilesDirRelativePath()
123+
private function getTmpFilesDirRelativePath()
124124
{
125125
return $this->subdirectoryPath . 'tmp/';
126126
}
@@ -130,7 +130,7 @@ public function getTmpFilesDirRelativePath()
130130
*
131131
* @return string
132132
*/
133-
public function getArchiveRelativePath()
133+
private function getArchiveRelativePath()
134134
{
135135
return $this->subdirectoryPath . $this->archiveName;
136136
}

app/code/Magento/Analytics/Model/FileInfo.php

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,31 +42,11 @@ public function getPath()
4242
return $this->path;
4343
}
4444

45-
/**
46-
* @param string $path
47-
* @return $this
48-
*/
49-
public function setPath($path)
50-
{
51-
$this->path = $path;
52-
return $this;
53-
}
54-
5545
/**
5646
* @return string
5747
*/
5848
public function getInitializationVector()
5949
{
6050
return $this->initializationVector;
6151
}
62-
63-
/**
64-
* @param string $initializationVector
65-
* @return $this
66-
*/
67-
public function setInitializationVector($initializationVector)
68-
{
69-
$this->initializationVector = $initializationVector;
70-
return $this;
71-
}
7252
}

app/code/Magento/Analytics/Model/FileRecorder.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,12 @@ private function getFileRelativePath()
101101
*/
102102
private function registerFile(EncodedContext $encodedContext, $fileRelativePath)
103103
{
104-
$newFileInfo = $this->fileInfoFactory->create();
105-
$newFileInfo->setInitializationVector($encodedContext->getInitializationVector())
106-
->setPath($fileRelativePath);
104+
$newFileInfo = $this->fileInfoFactory->create(
105+
[
106+
'path' => $fileRelativePath,
107+
'initializationVector' => $encodedContext->getInitializationVector(),
108+
]
109+
);
107110
$this->fileInfoManager->save($newFileInfo);
108111

109112
return true;
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Analytics\Test\Unit\Model;
7+
8+
use Magento\Analytics\Model\AnalyticsToken;
9+
use Magento\Analytics\Model\Cryptographer;
10+
use Magento\Analytics\Model\EncodedContext;
11+
use Magento\Analytics\Model\EncodedContextFactory;
12+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
13+
14+
/**
15+
* Class CryptographerTest
16+
*/
17+
class CryptographerTest extends \PHPUnit_Framework_TestCase
18+
{
19+
/**
20+
* @var AnalyticsToken|\PHPUnit_Framework_MockObject_MockObject
21+
*/
22+
private $analyticsTokenMock;
23+
24+
/**
25+
* @var EncodedContextFactory|\PHPUnit_Framework_MockObject_MockObject
26+
*/
27+
private $encodedContextFactoryMock;
28+
29+
/**
30+
* @var EncodedContext|\PHPUnit_Framework_MockObject_MockObject
31+
*/
32+
private $encodedContextMock;
33+
34+
/**
35+
* @var ObjectManagerHelper
36+
*/
37+
private $objectManagerHelper;
38+
39+
/**
40+
* @var Cryptographer
41+
*/
42+
private $cryptographer;
43+
44+
/**
45+
* @var string
46+
*/
47+
private $key;
48+
49+
/**
50+
* @var array
51+
*/
52+
private $initializationVectors;
53+
54+
/**
55+
* @var
56+
*/
57+
private $source;
58+
59+
/**
60+
* @var string
61+
*/
62+
private $cipherMethod = 'AES-256-CBC';
63+
64+
/**
65+
* @return void
66+
*/
67+
protected function setUp()
68+
{
69+
$this->analyticsTokenMock = $this->getMockBuilder(AnalyticsToken::class)
70+
->disableOriginalConstructor()
71+
->getMock();
72+
73+
$this->encodedContextFactoryMock = $this->getMockBuilder(EncodedContextFactory::class)
74+
->setMethods(['create'])
75+
->disableOriginalConstructor()
76+
->getMock();
77+
78+
$this->encodedContextMock = $this->getMockBuilder(EncodedContext::class)
79+
->disableOriginalConstructor()
80+
->getMock();
81+
82+
$this->key = '';
83+
$this->source = '';
84+
$this->initializationVectors = [];
85+
86+
$this->objectManagerHelper = new ObjectManagerHelper($this);
87+
88+
$this->cryptographer = $this->objectManagerHelper->getObject(
89+
Cryptographer::class,
90+
[
91+
'analyticsToken' => $this->analyticsTokenMock,
92+
'encodedContextFactory' => $this->encodedContextFactoryMock,
93+
'cipherMethod' => $this->cipherMethod,
94+
]
95+
);
96+
}
97+
98+
/**
99+
* @return void
100+
*/
101+
public function testEncode()
102+
{
103+
$token = 'some-token-value';
104+
$this->source = 'Some text';
105+
$this->key = hash('sha256', $token);
106+
107+
$checkEncodedContext = function ($parameters) {
108+
$emptyRequiredParameters =
109+
array_diff(['content', 'initializationVector'], array_keys(array_filter($parameters)));
110+
if ($emptyRequiredParameters) {
111+
return false;
112+
}
113+
114+
$encryptedData = openssl_encrypt(
115+
$this->source,
116+
$this->cipherMethod,
117+
$this->key,
118+
OPENSSL_RAW_DATA,
119+
$parameters['initializationVector']
120+
);
121+
122+
return ($encryptedData === $parameters['content']);
123+
};
124+
125+
$this->analyticsTokenMock
126+
->expects($this->once())
127+
->method('getToken')
128+
->with()
129+
->willReturn($token);
130+
131+
$this->encodedContextFactoryMock
132+
->expects($this->once())
133+
->method('create')
134+
->with($this->callback($checkEncodedContext))
135+
->willReturn($this->encodedContextMock);
136+
137+
$this->assertSame($this->encodedContextMock, $this->cryptographer->encode($this->source));
138+
}
139+
140+
/**
141+
* @return void
142+
*/
143+
public function testEncodeUniqueInitializationVector()
144+
{
145+
$this->source = 'Some text';
146+
$token = 'some-token-value';
147+
148+
$registerInitializationVector = function ($parameters) {
149+
if (empty($parameters['initializationVector'])) {
150+
return false;
151+
}
152+
153+
$this->initializationVectors[] = $parameters['initializationVector'];
154+
155+
return true;
156+
};
157+
158+
$this->analyticsTokenMock
159+
->expects($this->exactly(2))
160+
->method('getToken')
161+
->with()
162+
->willReturn($token);
163+
164+
$this->encodedContextFactoryMock
165+
->expects($this->exactly(2))
166+
->method('create')
167+
->with($this->callback($registerInitializationVector))
168+
->willReturn($this->encodedContextMock);
169+
170+
$this->assertSame($this->encodedContextMock, $this->cryptographer->encode($this->source));
171+
$this->assertSame($this->encodedContextMock, $this->cryptographer->encode($this->source));
172+
$this->assertCount(2, array_unique($this->initializationVectors));
173+
}
174+
175+
/**
176+
* @expectedException \Magento\Framework\Exception\LocalizedException
177+
* @dataProvider encodeNotValidSourceDataProvider
178+
*/
179+
public function testEncodeNotValidSource($source)
180+
{
181+
$this->cryptographer->encode($source);
182+
}
183+
184+
/**
185+
* @return array
186+
*/
187+
public function encodeNotValidSourceDataProvider()
188+
{
189+
return [
190+
'Array' => [[]],
191+
'Empty string' => [''],
192+
];
193+
}
194+
195+
/**
196+
* @expectedException \Magento\Framework\Exception\LocalizedException
197+
*/
198+
public function testEncodeNotValidCipherMethod()
199+
{
200+
$source = 'Some string';
201+
$cryptographer = $this->objectManagerHelper->getObject(
202+
Cryptographer::class,
203+
[
204+
'cipherMethod' => 'Wrong-method',
205+
]
206+
);
207+
208+
$cryptographer->encode($source);
209+
}
210+
}

0 commit comments

Comments
 (0)