Skip to content

Commit 82ac1c4

Browse files
committed
Add support for hmac related request signing
1 parent d3b5bbf commit 82ac1c4

File tree

5 files changed

+65
-12
lines changed

5 files changed

+65
-12
lines changed

src/Client.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public static function signRequest(RequestInterface $request, SignatureSecret $c
157157
$content = $body->getContents();
158158
$params = json_decode($content, true);
159159
$params['api_key'] = $credentials['api_key'];
160-
$signature = new Signature($params, $credentials['signature_secret']);
160+
$signature = new Signature($params, $credentials['signature_secret'], $credentials['signature_method']);
161161
$body->rewind();
162162
$body->write(json_encode($signature->getSignedParams()));
163163
break;
@@ -168,7 +168,7 @@ public static function signRequest(RequestInterface $request, SignatureSecret $c
168168
$params = [];
169169
parse_str($content, $params);
170170
$params['api_key'] = $credentials['api_key'];
171-
$signature = new Signature($params, $credentials['signature_secret']);
171+
$signature = new Signature($params, $credentials['signature_secret'], $credentials['signature_method']);
172172
$params = $signature->getSignedParams();
173173
$body->rewind();
174174
$body->write(http_build_query($params, null, '&'));
@@ -177,7 +177,7 @@ public static function signRequest(RequestInterface $request, SignatureSecret $c
177177
$query = [];
178178
parse_str($request->getUri()->getQuery(), $query);
179179
$query['api_key'] = $credentials['api_key'];
180-
$signature = new Signature($query, $credentials['signature_secret']);
180+
$signature = new Signature($query, $credentials['signature_secret'], $credentials['signature_method']);
181181
$request = $request->withUri($request->getUri()->withQuery(http_build_query($signature->getSignedParams())));
182182
break;
183183
}

src/Client/Credentials/SignatureSecret.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ class SignatureSecret extends AbstractCredentials implements CredentialsInterfac
1616
* @param string $key API Key
1717
* @param string $signature_secret Signature Secret
1818
*/
19-
public function __construct($key, $signature_secret)
19+
public function __construct($key, $signature_secret, $method='md5hash')
2020
{
2121
$this->credentials['api_key'] = $key;
2222
$this->credentials['signature_secret'] = $signature_secret;
23+
$this->credentials['signature_method'] = $method;
2324
}
2425
}

src/Client/Signature.php

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
namespace Nexmo\Client;
1010

11+
use Nexmo\Client\Exception\Exception;
12+
1113
class Signature
1214
{
1315
/**
@@ -28,7 +30,7 @@ class Signature
2830
* @param array $params
2931
* @param $secret
3032
*/
31-
public function __construct(array $params, $secret)
33+
public function __construct(array $params, $secret, $signatureMethod)
3234
{
3335
$this->params = $params;
3436
$this->signed = $params;
@@ -51,11 +53,25 @@ public function __construct(array $params, $secret)
5153
//create base string
5254
$base = '&'.urldecode(http_build_query($signed));
5355

54-
//append the secret
55-
$base .= $secret;
56+
$this->signed['sig'] = $this->sign($signatureMethod, $base, $secret);
57+
}
5658

57-
//create hash
58-
$this->signed['sig'] = md5($base);
59+
protected function sign($signatureMethod, $data, $secret) {
60+
switch($signatureMethod) {
61+
case 'md5hash':
62+
// md5hash needs the secret appended
63+
$data .= $secret;
64+
return md5($data);
65+
break;
66+
case 'md5':
67+
case 'sha1':
68+
case 'sha256':
69+
case 'sha512':
70+
return hash_hmac($signatureMethod, $data, $secret);
71+
break;
72+
default:
73+
throw new Exception('Unknown signature algorithm: '.$signatureMethod.'. Expected: md5hash, md5, sha1, sha256, or sha512');
74+
}
5975
}
6076

6177
/**
@@ -117,4 +133,4 @@ public function __toString()
117133
{
118134
return $this->getSignature();
119135
}
120-
}
136+
}

test/Client/SignatureTest.php

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,46 @@
1010

1111
use Nexmo\Client\Signature;
1212
use PHPUnit\Framework\TestCase;
13+
use Nexmo\Client\Exception\Exception;
1314

1415

1516
class SignatureTest extends TestCase
1617
{
18+
public function testInvalidSignatureMethod() {
19+
$this->expectException(Exception::class);
20+
$this->expectExceptionMessage('Unknown signature algorithm: fake_algo. Expected: md5hash, md5, sha1, sha256, or sha512');
21+
$signature = new Signature(['foo' => 'bar'], 'sig_secret', 'fake_algo');
22+
}
23+
24+
/**
25+
* @dataProvider hmacSignatureProvider
26+
*/
27+
public function testHmacSignature($algorithm, $expected){
28+
$data = [
29+
'api_key' => 'fake_api_key',
30+
'to' => '14155550100',
31+
'from' => 'AcmeInc',
32+
'text' => 'Test From Nexmo',
33+
'type' => 'text',
34+
'timestamp' => '1540924779'
35+
];
36+
$secret = '71efab63122f1d179f51c46bac838fb5';
37+
$signature = new Signature($data, $secret, $algorithm);
38+
39+
$this->assertEquals($expected, $signature->getSignature());
40+
}
41+
42+
public function hmacSignatureProvider() {
43+
$data = [];
44+
45+
$data['md5'] = ['md5', '51cdafebb4bbce9525b195c1617cb8d2'];
46+
$data['sha1'] = ['sha1', '0162aec64bc183b2e1256545951fe5639dc98020'];
47+
$data['sha256'] = ['sha256', '9fec5ef6d0f2b3d2bb7558b6e4042569823cab9ea0dd30503472b7b304601975'];
48+
$data['sha512'] = ['sha512', '40bd12b9a4b6000ad1138eefd24ffe9fbd72aee13c3fa04b32bb69dbc256ad0a04a463b1a9af6660d10f6e1e769ee14b9cff6a635502e93afcd0bfab29f38f87'];
49+
50+
return $data;
51+
}
52+
1753
/**
1854
* @dataProvider signatures
1955
* @param $sig
@@ -23,7 +59,7 @@ class SignatureTest extends TestCase
2359
public function testSignature($sig, $params, $secret)
2460
{
2561
//a signature is created from a set of parameters and a secret
26-
$signature = new Signature($params, $secret);
62+
$signature = new Signature($params, $secret, 'md5hash');
2763

2864
//the parameters should ne be changed
2965
$this->assertEquals($params, $signature->getParams());

test/ClientTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ public static function assertValidSignature($array, $secret)
569569
self::assertArrayHasKey('api_key', $array);
570570

571571
//params should be correctly signed
572-
$signature = new Signature($array, $secret);
572+
$signature = new Signature($array, $secret, 'md5hash');
573573
self::assertTrue($signature->check($array));
574574
}
575575
}

0 commit comments

Comments
 (0)