From 88344773d2b426a9810794c5bc8718c20497c103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karim=20Cassam=20Chena=C3=AF?= Date: Tue, 2 Apr 2024 21:50:24 +0200 Subject: [PATCH 1/3] Fix https://github.com/FakerPHP/Faker/issues/759 : The output of the md5(), sha1() and sha256() generators is misleading --- src/Provider/Miscellaneous.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Provider/Miscellaneous.php b/src/Provider/Miscellaneous.php index 354f67bb3a..e34644a804 100644 --- a/src/Provider/Miscellaneous.php +++ b/src/Provider/Miscellaneous.php @@ -249,7 +249,7 @@ public static function boolean($chanceOfGettingTrue = 50) */ public static function md5() { - return md5(self::numberBetween()); + return md5(random_bytes(16)); } /** @@ -259,7 +259,7 @@ public static function md5() */ public static function sha1() { - return sha1(self::numberBetween()); + return sha1(random_bytes(20)); } /** @@ -269,7 +269,7 @@ public static function sha1() */ public static function sha256() { - return hash('sha256', self::numberBetween()); + return hash('sha256', random_bytes(32)); } /** From e229cf6bce0f91caf041cc79ced80cbdf278182b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karim=20Cassam=20Chena=C3=AF?= Date: Wed, 3 Apr 2024 23:56:02 +0200 Subject: [PATCH 2/3] Test seedibility and use seedable function n times in order to leverage the full output space of the respective hashes --- src/Provider/Miscellaneous.php | 22 +++++++++++++++++++--- test/Provider/MiscellaneousTest.php | 23 +++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/Provider/Miscellaneous.php b/src/Provider/Miscellaneous.php index e34644a804..299ec67bbc 100644 --- a/src/Provider/Miscellaneous.php +++ b/src/Provider/Miscellaneous.php @@ -242,6 +242,22 @@ public static function boolean($chanceOfGettingTrue = 50) return self::numberBetween(1, 100) <= $chanceOfGettingTrue; } + /** + * Return a string representing a big number, which size is $n * 4 bytes ($n * 32 bits) + * + * @param int $n multiplier for numberBetween. + * + * @return string + * + * @example "38921908753913698485999935526730716" + */ + public static function multiplyNumberBetweenNTimes($n) + { + return array_reduce(range(1, $n), static function ($carry, $item) { + return bcmul($carry, self::numberBetween()); + }, '1'); + } + /** * @example 'cfcd208495d565ef66e7dff9f98764da' * @@ -249,7 +265,7 @@ public static function boolean($chanceOfGettingTrue = 50) */ public static function md5() { - return md5(random_bytes(16)); + return md5(self::multiplyNumberBetweenNTimes(128 / 32)); } /** @@ -259,7 +275,7 @@ public static function md5() */ public static function sha1() { - return sha1(random_bytes(20)); + return sha1(self::multiplyNumberBetweenNTimes(160 / 32)); } /** @@ -269,7 +285,7 @@ public static function sha1() */ public static function sha256() { - return hash('sha256', random_bytes(32)); + return hash('sha256', self::multiplyNumberBetweenNTimes(256 / 32)); } /** diff --git a/test/Provider/MiscellaneousTest.php b/test/Provider/MiscellaneousTest.php index 13590b8f2c..34d09d3710 100644 --- a/test/Provider/MiscellaneousTest.php +++ b/test/Provider/MiscellaneousTest.php @@ -22,16 +22,34 @@ public function testMd5(): void self::assertMatchesRegularExpression('/^[a-z0-9]{32}$/', Miscellaneous::md5()); } + public function testMd5ExpectedSeed(): void + { + $this->faker->seed(252); + self::assertEquals('fa72146b50f73db08c92053d1fc5f263', $this->faker->md5()); + } + public function testSha1(): void { self::assertMatchesRegularExpression('/^[a-z0-9]{40}$/', Miscellaneous::sha1()); } + public function testSha1ExpectedSeed(): void + { + $this->faker->seed(252); + self::assertEquals('5ecb7a1b22291b6b15e534852e03ac72f4187a48', $this->faker->sha1()); + } + public function testSha256(): void { self::assertMatchesRegularExpression('/^[a-z0-9]{64}$/', Miscellaneous::sha256()); } + public function testSha256ExpectedSeed(): void + { + $this->faker->seed(252); + self::assertEquals('ea98b35136e020d9dd9b594252d9263021d1742da2bd4c8592b854c62b4122c2', $this->faker->sha256()); + } + public function testLocale(): void { self::assertMatchesRegularExpression('/^[a-z]{2,3}_[A-Z]{2}$/', Miscellaneous::locale()); @@ -61,4 +79,9 @@ public function testEmoji(): void { self::assertMatchesRegularExpression('/^[\x{1F600}-\x{1F637}]$/u', Miscellaneous::emoji()); } + + protected function getProviders(): iterable + { + yield new Miscellaneous($this->faker); + } } From 8dfb665061d82fd59c3a70082cee7c53cc08063c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karim=20Cassam=20Chena=C3=AF?= Date: Thu, 4 Apr 2024 15:17:31 +0200 Subject: [PATCH 3/3] seedable md5 sha1 and sha256 functions with usage of random_bytes --- src/Provider/Miscellaneous.php | 34 ++++++++--------------------- test/Provider/MiscellaneousTest.php | 9 +++----- 2 files changed, 12 insertions(+), 31 deletions(-) diff --git a/src/Provider/Miscellaneous.php b/src/Provider/Miscellaneous.php index 299ec67bbc..83698ca8e8 100644 --- a/src/Provider/Miscellaneous.php +++ b/src/Provider/Miscellaneous.php @@ -243,49 +243,33 @@ public static function boolean($chanceOfGettingTrue = 50) } /** - * Return a string representing a big number, which size is $n * 4 bytes ($n * 32 bits) - * - * @param int $n multiplier for numberBetween. - * - * @return string - * - * @example "38921908753913698485999935526730716" - */ - public static function multiplyNumberBetweenNTimes($n) - { - return array_reduce(range(1, $n), static function ($carry, $item) { - return bcmul($carry, self::numberBetween()); - }, '1'); - } - - /** - * @example 'cfcd208495d565ef66e7dff9f98764da' + * @example '7c2a5276141e81fdf60015689c53d8a1' * * @return string */ - public static function md5() + public static function md5($seed = null) { - return md5(self::multiplyNumberBetweenNTimes(128 / 32)); + return md5($seed ?? random_bytes(128 / 8)); } /** - * @example 'b5d86317c2a144cd04d0d7c03b2b02666fafadf2' + * @example '2d37797087b5130d79e51a08fa7f1cf7678c70ab' * * @return string */ - public static function sha1() + public static function sha1($seed = null) { - return sha1(self::multiplyNumberBetweenNTimes(160 / 32)); + return sha1($seed ?? random_bytes(160 / 8)); } /** - * @example '85086017559ccc40638fcde2fecaf295e0de7ca51b7517b6aebeaaf75b4d4654' + * @example 'a5aa26c454007319b3458f9a9162822c8c1ac5394c4124186b4d54703d9ac3cd' * * @return string */ - public static function sha256() + public static function sha256($seed = null) { - return hash('sha256', self::multiplyNumberBetweenNTimes(256 / 32)); + return hash('sha256', $seed ?? random_bytes(256 / 8)); } /** diff --git a/test/Provider/MiscellaneousTest.php b/test/Provider/MiscellaneousTest.php index 34d09d3710..e17b14bfa4 100644 --- a/test/Provider/MiscellaneousTest.php +++ b/test/Provider/MiscellaneousTest.php @@ -24,8 +24,7 @@ public function testMd5(): void public function testMd5ExpectedSeed(): void { - $this->faker->seed(252); - self::assertEquals('fa72146b50f73db08c92053d1fc5f263', $this->faker->md5()); + self::assertEquals('7c2a5276141e81fdf60015689c53d8a1', $this->faker->md5('seed_123')); } public function testSha1(): void @@ -35,8 +34,7 @@ public function testSha1(): void public function testSha1ExpectedSeed(): void { - $this->faker->seed(252); - self::assertEquals('5ecb7a1b22291b6b15e534852e03ac72f4187a48', $this->faker->sha1()); + self::assertEquals('2d37797087b5130d79e51a08fa7f1cf7678c70ab', $this->faker->sha1('seed_123')); } public function testSha256(): void @@ -46,8 +44,7 @@ public function testSha256(): void public function testSha256ExpectedSeed(): void { - $this->faker->seed(252); - self::assertEquals('ea98b35136e020d9dd9b594252d9263021d1742da2bd4c8592b854c62b4122c2', $this->faker->sha256()); + self::assertEquals('a5aa26c454007319b3458f9a9162822c8c1ac5394c4124186b4d54703d9ac3cd', $this->faker->sha256('seed_123')); } public function testLocale(): void