Skip to content
This repository was archived by the owner on Feb 28, 2024. It is now read-only.

Commit f910656

Browse files
authored
Pulling in sapsaldog/client-encryption-php.
1 parent 5a973ce commit f910656

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2170
-715
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@
22
vendor
33
tests.xml
44
coverage.xml
5-
.scannerwork
5+
.scannerwork
6+
.phpunit.result.cache
7+
composer.lock

composer.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818
}
1919
],
2020
"require": {
21-
"phpseclib/phpseclib": "^2.0",
22-
"symfony/polyfill-php70": "^1.19"
21+
"phpseclib/phpseclib": "~3.0",
22+
"symfony/polyfill-php70": "^1.19",
23+
"galbar/jsonpath": "^2.0"
2324
},
2425
"require-dev": {
2526
"guzzlehttp/guzzle": "^6.2",
26-
"yoast/phpunit-polyfills": "^1.0"
27+
"yoast/phpunit-polyfills": "^1.0",
28+
"phake/phake": "*"
2729
},
2830
"suggest": {
2931
"psr/http-message": "Allow usage of the PsrHttpMessageEncryptionInterceptor class"
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace Mastercard\Developer\Encryption\AES;
4+
5+
use Mastercard\Developer\Encryption\EncryptionException;
6+
use phpseclib3\Crypt\AES;
7+
8+
class AESCBC
9+
{
10+
private function __construct(){
11+
// This class can't be instantiated
12+
}
13+
14+
/**
15+
* @param string $iv
16+
* @param string $key
17+
* @param string $bytes
18+
* @throws EncryptionException
19+
* @return string
20+
*/
21+
public static function encrypt($iv, $key, $bytes) {
22+
$aes = new AES('cbc');
23+
$aes->setKey($key);
24+
$aes->setIV($iv);
25+
$encryptedBytes = $aes->encrypt($bytes);
26+
if (false === $encryptedBytes) {
27+
throw new EncryptionException('Failed to encrypt bytes!');
28+
}
29+
return $encryptedBytes;
30+
}
31+
32+
/**
33+
* @param string $iv
34+
* @param string $key
35+
* @param string $encryptedBytes
36+
* @throws EncryptionException
37+
* @return string
38+
*/
39+
public static function decrypt($iv, $key, $encryptedBytes) {
40+
$aes = new AES('cbc');
41+
$aes->setKey($key);
42+
$aes->setIV($iv);
43+
$bytes = $aes->decrypt($encryptedBytes);
44+
if (false === $bytes) {
45+
throw new EncryptionException('Failed to decrypt bytes with the provided key and IV!');
46+
}
47+
return $bytes;
48+
}
49+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Mastercard\Developer\Encryption\AES;
4+
5+
class AESEncryption
6+
{
7+
private function __construct()
8+
{
9+
// Nothing to do here
10+
}
11+
12+
13+
/**
14+
* @param string $cipher_algo
15+
* @return string
16+
*/
17+
public static function generateIv($cipher_algo = 'AES-128-CBC')
18+
{
19+
$ivLength = openssl_cipher_iv_length($cipher_algo);
20+
$iv = openssl_random_pseudo_bytes($ivLength);
21+
22+
return $iv;
23+
}
24+
25+
/**
26+
* @param int $bitLength
27+
* @return string
28+
*/
29+
public static function generateCek($bitLength)
30+
{
31+
return openssl_random_pseudo_bytes($bitLength / 8);
32+
}
33+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace Mastercard\Developer\Encryption\AES;
4+
5+
use phpseclib3\Crypt\AES;
6+
7+
class AESGCM
8+
{
9+
private function __construct()
10+
{
11+
}
12+
13+
/**
14+
* @param string $iv
15+
* @param string $key
16+
* @param string $authTag
17+
* @param string $aad
18+
* @param string $cipherText
19+
* @return string
20+
*/
21+
public static function decrypt($iv, $key, $authTag, $aad, $cipherText)
22+
{
23+
$cipher = new AES('gcm');
24+
$cipher->setNonce($iv);
25+
$cipher->setKey($key);
26+
$cipher->disablePadding();
27+
$cipher->setTag($authTag);
28+
$cipher->setAAD($aad);
29+
return $cipher->decrypt($cipherText);
30+
}
31+
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
<?php
2+
3+
namespace Mastercard\Developer\Encryption;
4+
5+
use Mastercard\Developer\Keys\DecryptionKey;
6+
use Mastercard\Developer\Keys\EncryptionKey;
7+
8+
abstract class EncryptionConfig
9+
{
10+
/**
11+
* The different methods of encryption
12+
*/
13+
/**
14+
* The encryption scheme to be used
15+
*/
16+
protected $scheme = EncryptionConfigScheme::LEGACY;
17+
18+
/**
19+
* @var string|null
20+
* The SHA-256 hex-encoded digest of the key used for encryption (optional, the digest will be
21+
* automatically computed if this field is null or empty).
22+
* Example: "c3f8ef7053c4fb306f7476e7d1956f0aa992ff9dfdd5244b912a1d377ff3a84f"
23+
*/
24+
protected $encryptionKeyFingerprint = null;
25+
26+
/**
27+
* @var EncryptionKey
28+
* A certificate object whose public key will be used for encryption.
29+
*/
30+
protected $encryptionCertificate;
31+
32+
/**
33+
* @var DecryptionKey
34+
* A private key object to be used for decryption.
35+
*/
36+
protected $decryptionKey;
37+
38+
/**
39+
* @var array
40+
* A list of JSON paths to encrypt in request payloads.
41+
* Example:
42+
* <pre>
43+
* new HashMap<>() {
44+
* {
45+
* put("$.path.to.element.to.be.encrypted", "$.path.to.object.where.to.store.encryption.fields");
46+
* }
47+
* }
48+
* </pre>
49+
*/
50+
private $encryptionPaths = [];
51+
52+
/**
53+
* @var array
54+
* A list of JSON paths to decrypt in response payloads.
55+
* Example:
56+
* <pre>
57+
* new HashMap<>() {
58+
* {
59+
* put("$.path.to.object.with.encryption.fields", "$.path.where.to.write.decrypted.element");
60+
* }
61+
* }
62+
* </pre>
63+
*/
64+
private $decryptionPaths = [];
65+
66+
/**
67+
* @var string|null
68+
* The name of the payload field where to write/read the encrypted data value.
69+
*/
70+
protected $encryptedValueFieldName = null;
71+
72+
/**
73+
* @return string|null
74+
*/
75+
public function getEncryptionKeyFingerprint()
76+
{
77+
return $this->encryptionKeyFingerprint;
78+
}
79+
80+
/**
81+
* @return EncryptionKey
82+
*/
83+
public function getEncryptionCertificate()
84+
{
85+
return $this->encryptionCertificate;
86+
}
87+
88+
/**
89+
* @return DecryptionKey
90+
*/
91+
public function getDecryptionKey()
92+
{
93+
return $this->decryptionKey;
94+
}
95+
96+
/**
97+
* @return int
98+
*/
99+
public function getScheme()
100+
{
101+
return $this->scheme;
102+
}
103+
104+
/**
105+
* @return array
106+
*/
107+
public function getEncryptionPaths()
108+
{
109+
return $this->encryptionPaths;
110+
}
111+
112+
/**
113+
* @return array
114+
*/
115+
public function getDecryptionPaths()
116+
{
117+
return $this->decryptionPaths;
118+
}
119+
120+
/**
121+
* @return string
122+
*/
123+
public function getEncryptedValueFieldName()
124+
{
125+
return $this->encryptedValueFieldName;
126+
}
127+
128+
/**
129+
* @param string|null $encryptionKeyFingerprint
130+
*/
131+
public function setEncryptionKeyFingerprint($encryptionKeyFingerprint)
132+
{
133+
$this->encryptionKeyFingerprint = $encryptionKeyFingerprint;
134+
}
135+
136+
/**
137+
* @param string $encryptionCertificate
138+
*/
139+
public function setEncryptionCertificate($encryptionCertificate)
140+
{
141+
$this->encryptionCertificate = $encryptionCertificate;
142+
}
143+
144+
/**
145+
* @param string|null $decryptionKey
146+
*/
147+
public function setDecryptionKey($decryptionKey)
148+
{
149+
$this->decryptionKey = $decryptionKey;
150+
}
151+
152+
/**
153+
* @param string $encryptedValueFieldName
154+
*/
155+
public function setEncryptedValueFieldName($encryptedValueFieldName)
156+
{
157+
$this->encryptedValueFieldName = $encryptedValueFieldName;
158+
}
159+
160+
/**
161+
* @param array $encryptionPaths
162+
*/
163+
public function setEncryptionPaths($encryptionPaths)
164+
{
165+
$this->encryptionPaths = $encryptionPaths;
166+
}
167+
168+
/**
169+
* @param array $decryptionPaths
170+
*/
171+
public function setDecryptionPaths($decryptionPaths)
172+
{
173+
$this->decryptionPaths = $decryptionPaths;
174+
}
175+
176+
177+
178+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
namespace Mastercard\Developer\Encryption;
4+
5+
use Mastercard\Developer\Json\JsonPath;
6+
use Mastercard\Developer\Keys\DecryptionKey;
7+
use Mastercard\Developer\Keys\EncryptionKey;
8+
9+
abstract class EncryptionConfigBuilder
10+
{
11+
/**
12+
* @var EncryptionKey
13+
*/
14+
protected $encryptionCertificate;
15+
16+
/**
17+
* @var string|null
18+
*/
19+
protected $encryptionKeyFingerprint = null;
20+
21+
/**
22+
* @var DecryptionKey
23+
*/
24+
protected $decryptionKey;
25+
26+
/**
27+
* @var array
28+
*/
29+
protected $encryptionPaths = [];
30+
31+
/**
32+
* @var array
33+
*/
34+
protected $decryptionPaths = [];
35+
36+
/**
37+
* @var string|null
38+
*/
39+
protected $encryptedValueFieldName = null;
40+
41+
protected function computeEncryptionKeyFingerprintWhenNeeded()
42+
{
43+
try {
44+
if ($this->encryptionCertificate == null || isset($this->encryptionKeyFingerprint)) {
45+
// No encryption certificate set or key fingerprint already provided
46+
return;
47+
}
48+
49+
$cert = openssl_x509_read($this->encryptionCertificate->getBytes());
50+
$this->encryptionKeyFingerprint = openssl_x509_fingerprint($cert, 'sha256');
51+
} catch (\Exception $e) {
52+
throw new EncryptionException("Failed to compute encryption key fingerprint!", $e);
53+
}
54+
}
55+
56+
protected function checkJsonPathParameterValues()
57+
{
58+
foreach ($this->decryptionPaths as $key => $value) {
59+
if (!JsonPath::isPathDefinite($key) || !JsonPath::isPathDefinite($value)) {
60+
throw new \InvalidArgumentException("JSON paths for decryption must point to a single item!");
61+
}
62+
}
63+
64+
foreach ($this->encryptionPaths as $key => $value) {
65+
if (!JsonPath::isPathDefinite($key) || !JsonPath::isPathDefinite($value)) {
66+
throw new \InvalidArgumentException("JSON paths for decryption must point to a single item!");
67+
}
68+
}
69+
}
70+
}

0 commit comments

Comments
 (0)