Skip to content

Commit 2166016

Browse files
authored
Update test and codebase for signature verification and improvements (#84)
The patch introduces signature verification to test cases with RSA, ECDSA and EdDSA algorithms. It also refactors code by replacing 'mb_strlen', 'mb_substr' with 'strlen', 'substr' for better performance. Minor changes include renaming variables for better clarity and consistency. Several pieces of code have been modified to use more efficient methods, and some unused portions have been removed. Commit also includes a fix for configuration issue in 'deptrac.yaml'.
1 parent c2802a4 commit 2166016

File tree

11 files changed

+104
-96
lines changed

11 files changed

+104
-96
lines changed

composer.json

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
"php": ">=8.1",
2020
"ext-json": "*",
2121
"ext-openssl": "*",
22-
"ext-mbstring": "*",
2322
"brick/math": "^0.9|^0.10|^0.11|^0.12",
2423
"spomky-labs/pki-framework": "^1.0"
2524
},
@@ -29,18 +28,18 @@
2928
}
3029
},
3130
"require-dev": {
32-
"infection/infection": "^0.27",
31+
"infection/infection": "^0.29",
3332
"phpstan/phpstan": "^1.7",
3433
"phpstan/phpstan-deprecation-rules": "^1.0",
3534
"phpstan/phpstan-phpunit": "^1.1",
3635
"phpstan/phpstan-strict-rules": "^1.2",
37-
"phpunit/phpunit": "^10.1",
38-
"rector/rector": "^0.19",
36+
"phpunit/phpunit": "^10.1|^11.0",
37+
"rector/rector": "^1.0",
3938
"symplify/easy-coding-standard": "^12.0",
4039
"symfony/phpunit-bridge": "^6.4|^7.0",
4140
"ekino/phpstan-banned-code": "^1.0",
4241
"php-parallel-lint/php-parallel-lint": "^1.3",
43-
"qossmic/deptrac-shim": "^1.0",
42+
"qossmic/deptrac": "^2.0",
4443
"phpstan/extension-installer": "^1.3"
4544
},
4645
"autoload-dev": {

deptrac.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ parameters:
44
layers:
55
- name: 'CoseLib'
66
collectors:
7-
- type: 'className'
8-
regex: '^Cose\\'
7+
- type: 'classLike'
8+
value: '^Cose\\'
99
- name: 'Vendors'
1010
collectors:
11-
- { type: className, regex: '^CBOR\\' }
12-
- { type: className, regex: '^Brick\\' }
13-
- { type: className, regex: '^SpomkyLabs\\Pki\\' }
11+
- { type: 'classLike', value: '^CBOR\\' }
12+
- { type: 'classLike', value: '^Brick\\' }
13+
- { type: 'classLike', value: '^SpomkyLabs\\Pki\\' }
1414
ruleset:
1515
CoseLib:
1616
- Vendors

ecs.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
declare(strict_types=1);
44

5-
use PhpCsFixer\Fixer\Alias\MbStrFunctionsFixer;
65
use PhpCsFixer\Fixer\ArrayNotation\ArraySyntaxFixer;
76
use PhpCsFixer\Fixer\ClassNotation\ProtectedToPrivateFixer;
87
use PhpCsFixer\Fixer\Comment\HeaderCommentFixer;
@@ -25,7 +24,6 @@
2524
use PhpCsFixer\Fixer\Strict\StrictComparisonFixer;
2625
use PhpCsFixer\Fixer\Strict\StrictParamFixer;
2726
use PhpCsFixer\Fixer\Whitespace\ArrayIndentationFixer;
28-
use PhpCsFixer\Fixer\Whitespace\CompactNullableTypehintFixer;
2927
use PhpCsFixer\Fixer\Whitespace\MethodChainingIndentationFixer;
3028
use Symplify\EasyCodingStandard\Config\ECSConfig;
3129
use Symplify\EasyCodingStandard\ValueObject\Set\SetList;
@@ -53,11 +51,9 @@
5351
$config->rule(ProtectedToPrivateFixer::class);
5452
$config->rule(DeclareStrictTypesFixer::class);
5553
$config->rule(NativeConstantInvocationFixer::class);
56-
$config->rule(MbStrFunctionsFixer::class);
5754
$config->rule(LinebreakAfterOpeningTagFixer::class);
5855
$config->rule(CombineConsecutiveIssetsFixer::class);
5956
$config->rule(CombineConsecutiveUnsetsFixer::class);
60-
$config->rule(CompactNullableTypehintFixer::class);
6157
$config->rule(NoSuperfluousElseifFixer::class);
6258
$config->rule(NoSuperfluousPhpdocTagsFixer::class);
6359
$config->rule(PhpdocTrimConsecutiveBlankLineSeparationFixer::class);

src/Algorithm/Mac/Hmac.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public function hash(string $data, Key $key): string
1818
$this->checKey($key);
1919
$signature = hash_hmac($this->getHashAlgorithm(), $data, (string) $key->get(SymmetricKey::DATA_K), true);
2020

21-
return mb_substr($signature, 0, intdiv($this->getSignatureLength(), 8), '8bit');
21+
return substr($signature, 0, intdiv($this->getSignatureLength(), 8));
2222
}
2323

2424
public function verify(string $data, Key $key, string $signature): bool

src/Algorithm/Signature/ECDSA/ECSignature.php

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
use function dechex;
1010
use function hex2bin;
1111
use function hexdec;
12-
use function mb_strlen;
13-
use function mb_substr;
1412
use function str_pad;
13+
use function strlen;
14+
use function substr;
1515
use const STR_PAD_LEFT;
1616

1717
/**
@@ -41,8 +41,8 @@ public static function toAsn1(string $signature, int $length): string
4141
throw new InvalidArgumentException('Invalid signature length.');
4242
}
4343

44-
$pointR = self::preparePositiveInteger(mb_substr($signature, 0, $length, '8bit'));
45-
$pointS = self::preparePositiveInteger(mb_substr($signature, $length, null, '8bit'));
44+
$pointR = self::preparePositiveInteger(substr($signature, 0, $length));
45+
$pointS = self::preparePositiveInteger(substr($signature, $length, null));
4646

4747
$lengthR = self::octetLength($pointR);
4848
$lengthS = self::octetLength($pointS);
@@ -80,28 +80,28 @@ public static function fromAsn1(string $signature, int $length): string
8080

8181
private static function octetLength(string $data): int
8282
{
83-
return intdiv(mb_strlen($data, '8bit'), self::BYTE_SIZE);
83+
return intdiv(strlen($data), self::BYTE_SIZE);
8484
}
8585

8686
private static function preparePositiveInteger(string $data): string
8787
{
88-
if (mb_substr($data, 0, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) {
88+
if (substr($data, 0, self::BYTE_SIZE) > self::ASN1_BIG_INTEGER_LIMIT) {
8989
return self::ASN1_NEGATIVE_INTEGER . $data;
9090
}
9191

9292
while (
93-
mb_strpos($data, self::ASN1_NEGATIVE_INTEGER, 0, '8bit') === 0
94-
&& mb_substr($data, 2, self::BYTE_SIZE, '8bit') <= self::ASN1_BIG_INTEGER_LIMIT
93+
str_starts_with($data, self::ASN1_NEGATIVE_INTEGER)
94+
&& substr($data, 2, self::BYTE_SIZE) <= self::ASN1_BIG_INTEGER_LIMIT
9595
) {
96-
$data = mb_substr($data, 2, null, '8bit');
96+
$data = substr($data, 2, null);
9797
}
9898

9999
return $data;
100100
}
101101

102102
private static function readAsn1Content(string $message, int &$position, int $length): string
103103
{
104-
$content = mb_substr($message, $position, $length, '8bit');
104+
$content = substr($message, $position, $length);
105105
$position += $length;
106106

107107
return $content;
@@ -121,10 +121,10 @@ private static function readAsn1Integer(string $message, int &$position): string
121121
private static function retrievePositiveInteger(string $data): string
122122
{
123123
while (
124-
mb_strpos($data, self::ASN1_NEGATIVE_INTEGER, 0, '8bit') === 0
125-
&& mb_substr($data, 2, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT
124+
str_starts_with($data, self::ASN1_NEGATIVE_INTEGER)
125+
&& substr($data, 2, self::BYTE_SIZE) > self::ASN1_BIG_INTEGER_LIMIT
126126
) {
127-
$data = mb_substr($data, 2, null, '8bit');
127+
$data = substr($data, 2, null);
128128
}
129129

130130
return $data;

src/Algorithm/Signature/RSA/PSSRSA.php

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,12 @@
1414
use function ceil;
1515
use function chr;
1616
use function hash_equals;
17-
use function mb_strlen;
18-
use function mb_substr;
1917
use function ord;
2018
use function pack;
2119
use function random_bytes;
2220
use function str_pad;
2321
use function str_repeat;
22+
use function strlen;
2423
use const STR_PAD_LEFT;
2524

2625
/**
@@ -31,7 +30,7 @@ abstract class PSSRSA implements Signature
3130
public function sign(string $data, Key $key): string
3231
{
3332
$key = $this->handleKey($key);
34-
$modulusLength = mb_strlen($key->n(), '8bit');
33+
$modulusLength = strlen($key->n());
3534

3635
$em = $this->encodeEMSAPSS($data, 8 * $modulusLength - 1, $this->getHashAlgorithm());
3736
$message = BigInteger::createFromBinaryString($em);
@@ -43,8 +42,8 @@ public function sign(string $data, Key $key): string
4342
public function verify(string $data, Key $key, string $signature): bool
4443
{
4544
$key = $this->handleKey($key);
46-
$modulusLength = mb_strlen($key->n(), '8bit');
47-
if (mb_strlen($signature, '8bit') !== $modulusLength) {
45+
$modulusLength = strlen($key->n());
46+
if (strlen($signature) !== $modulusLength) {
4847
throw new InvalidArgumentException('Invalid modulus length');
4948
}
5049
$s2 = BigInteger::createFromBinaryString($signature);
@@ -99,7 +98,7 @@ private function handleKey(Key $key): RsaKey
9998
private function convertIntegerToOctetString(BigInteger $x, int $xLen): string
10099
{
101100
$xB = $x->toBytes();
102-
if (mb_strlen($xB, '8bit') > $xLen) {
101+
if (strlen($xB) > $xLen) {
103102
throw new RuntimeException('Unable to convert the integer');
104103
}
105104

@@ -118,7 +117,7 @@ private function getMGF1(string $mgfSeed, int $maskLen, Hash $mgfHash): string
118117
$t .= $mgfHash->hash($mgfSeed . $c);
119118
}
120119

121-
return mb_substr($t, 0, $maskLen, '8bit');
120+
return substr($t, 0, $maskLen);
122121
}
123122

124123
/**
@@ -155,11 +154,11 @@ private function verifyEMSAPSS(string $m, string $em, int $emBits, Hash $hash):
155154
if ($emLen < $hash->getLength() + $sLen + 2) {
156155
throw new InvalidArgumentException();
157156
}
158-
if ($em[mb_strlen($em, '8bit') - 1] !== chr(0xBC)) {
157+
if ($em[strlen($em) - 1] !== chr(0xBC)) {
159158
throw new InvalidArgumentException();
160159
}
161-
$maskedDB = mb_substr($em, 0, -$hash->getLength() - 1, '8bit');
162-
$h = mb_substr($em, -$hash->getLength() - 1, $hash->getLength(), '8bit');
160+
$maskedDB = substr($em, 0, -$hash->getLength() - 1);
161+
$h = substr($em, -$hash->getLength() - 1, $hash->getLength());
163162
$temp = chr(0xFF << ($emBits & 7));
164163
if ((~$maskedDB[0] & $temp) !== $temp) {
165164
throw new InvalidArgumentException();
@@ -168,13 +167,13 @@ private function verifyEMSAPSS(string $m, string $em, int $emBits, Hash $hash):
168167
$db = $maskedDB ^ $dbMask;
169168
$db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0];
170169
$temp = $emLen - $hash->getLength() - $sLen - 2;
171-
if (mb_strpos($db, str_repeat(chr(0), $temp), 0, '8bit') !== 0) {
170+
if (! str_starts_with($db, str_repeat(chr(0), $temp))) {
172171
throw new InvalidArgumentException();
173172
}
174173
if (ord($db[$temp]) !== 1) {
175174
throw new InvalidArgumentException();
176175
}
177-
$salt = mb_substr($db, $temp + 1, null, '8bit'); // should be $sLen long
176+
$salt = substr($db, $temp + 1, null); // should be $sLen long
178177
$m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt;
179178
$h2 = $hash->hash($m2);
180179

src/BigInteger.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Brick\Math\BigInteger as BrickBigInteger;
88
use function chr;
99
use function hex2bin;
10+
use function strlen;
1011
use function unpack;
1112

1213
/**
@@ -42,7 +43,7 @@ public function toBytes(): string
4243
}
4344

4445
$temp = $this->value->toBase(16);
45-
$temp = 0 !== (mb_strlen($temp, '8bit') & 1) ? '0' . $temp : $temp;
46+
$temp = 0 !== (strlen($temp) & 1) ? '0' . $temp : $temp;
4647
$temp = hex2bin($temp);
4748

4849
return ltrim($temp, chr(0));

src/Key/Ec2Key.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use function array_key_exists;
1515
use function in_array;
1616
use function is_int;
17+
use function strlen;
1718

1819
/**
1920
* @final
@@ -93,10 +94,10 @@ public function __construct(array $data)
9394
if (! isset($data[self::DATA_CURVE], $data[self::DATA_X], $data[self::DATA_Y])) {
9495
throw new InvalidArgumentException('Invalid EC2 key. The curve or the "x/y" coordinates are missing');
9596
}
96-
if (mb_strlen((string) $data[self::DATA_X], '8bit') !== self::CURVE_KEY_LENGTH[$data[self::DATA_CURVE]]) {
97+
if (strlen((string) $data[self::DATA_X]) !== self::CURVE_KEY_LENGTH[$data[self::DATA_CURVE]]) {
9798
throw new InvalidArgumentException('Invalid length for x coordinate');
9899
}
99-
if (mb_strlen((string) $data[self::DATA_Y], '8bit') !== self::CURVE_KEY_LENGTH[$data[self::DATA_CURVE]]) {
100+
if (strlen((string) $data[self::DATA_Y]) !== self::CURVE_KEY_LENGTH[$data[self::DATA_CURVE]]) {
100101
throw new InvalidArgumentException('Invalid length for y coordinate');
101102
}
102103
if (is_int($data[self::DATA_CURVE])) {
@@ -188,8 +189,8 @@ private function getCurveOid(): string
188189

189190
private function pem(string $type, string $der): string
190191
{
191-
return sprintf("-----BEGIN %s-----\n", mb_strtoupper($type)) .
192+
return sprintf("-----BEGIN %s-----\n", strtoupper($type)) .
192193
chunk_split(base64_encode($der), 64, "\n") .
193-
sprintf("-----END %s-----\n", mb_strtoupper($type));
194+
sprintf("-----END %s-----\n", strtoupper($type));
194195
}
195196
}

0 commit comments

Comments
 (0)