EXT_HASH_SOURCES="hash.c hash_md.c hash_sha.c hash_ripemd.c hash_haval.c \
hash_tiger.c hash_gost.c hash_snefru.c hash_whirlpool.c hash_adler32.c \
- hash_crc32.c hash_fnv.c hash_joaat.c"
+ hash_crc32.c hash_fnv.c hash_joaat.c hash_sha3.c"
EXT_HASH_HEADERS="php_hash.h php_hash_md.h php_hash_sha.h php_hash_ripemd.h \
php_hash_haval.h php_hash_tiger.h php_hash_gost.h php_hash_snefru.h \
php_hash_whirlpool.h php_hash_adler32.h php_hash_crc32.h \
- php_hash_fnv.h php_hash_joaat.h"
+ php_hash_fnv.h php_hash_joaat.h php_hash_sha3.h"
PHP_NEW_EXTENSION(hash, $EXT_HASH_SOURCES, $ext_shared)
ifdef([PHP_INSTALL_HEADERS], [
php_hash_register_algo("sha256", &php_hash_sha256_ops);
php_hash_register_algo("sha384", &php_hash_sha384_ops);
php_hash_register_algo("sha512", &php_hash_sha512_ops);
+ php_hash_register_algo("sha3-224", &php_hash_sha3_224_ops);
+ php_hash_register_algo("sha3-256", &php_hash_sha3_256_ops);
+ php_hash_register_algo("sha3-384", &php_hash_sha3_384_ops);
+ php_hash_register_algo("sha3-512", &php_hash_sha3_512_ops);
php_hash_register_algo("ripemd128", &php_hash_ripemd128_ops);
php_hash_register_algo("ripemd160", &php_hash_ripemd160_ops);
php_hash_register_algo("ripemd256", &php_hash_ripemd256_ops);
--- /dev/null
+#include "php_hash_sha3.h"
+
+#if (defined(__APPLE__) || defined(__APPLE_CC__)) && \
+ (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__))
+# if defined(__LITTLE_ENDIAN__)
+# undef WORDS_BIGENDIAN
+# else
+# if defined(__BIG_ENDIAN__)
+# define WORDS_BIGENDIAN
+# endif
+# endif
+#endif
+
+inline php_hash_uint64 rol64(php_hash_uint64 v, unsigned char b) {
+ return (v << b) | (v >> (64 - b));
+}
+inline unsigned char idx(unsigned char x, unsigned char y) {
+ return x + (5 * y);
+}
+
+#ifdef WORDS_BIGENDIAN
+inline php_hash_uint64 load64(const unsigned char* x) {
+ php_hash_uint64 ret = 0;
+ for (unsigned char i = 7; i >= 0; --i) {
+ ret <<= 8;
+ ret |= x[i];
+ }
+ return ret;
+}
+inline void store64(const unsigned char* x, php_hash_uint64 val) {
+ for (unsigned char i = 0; i < 8; ++i) {
+ x[i] = val & 0xFF;
+ val >>= 8;
+ }
+}
+inline void xor64(const unsigned char* x, php_hash_uint64 val) {
+ for (unsigned char i = 0; i < 8; ++i) {
+ x[i] ^= val & 0xFF;
+ val >>= 8;
+ }
+}
+# define readLane(x, y) load64(ctx->state+sizeof(php_hash_uint64)*idx(x, y))
+# define writeLane(x, y, v) store64(ctx->state+sizeof(php_hash_uint64)*idx(x, y), v)
+# define XORLane(x, y, v) xor64(ctx->state+sizeof(php_hash_uint64)*idx(x, y), v)
+#else
+# define readLane(x, y) (((php_hash_uint64*)ctx->state)[idx(x,y)])
+# define writeLane(x, y, v) (((php_hash_uint64*)ctx->state)[idx(x,y)] = v)
+# define XORLane(x, y, v) (((php_hash_uint64*)ctx->state)[idx(x,y)] ^= v)
+#endif
+
+inline char LFSR86540(unsigned char* pLFSR)
+{
+ unsigned char LFSR = *pLFSR;
+ char result = LFSR & 0x01;
+ if (LFSR & 0x80) {
+ // Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1
+ LFSR = (LFSR << 1) ^ 0x71;
+ } else {
+ LFSR <<= 1;
+ }
+ *pLFSR = LFSR;
+ return result;
+}
+
+static void permute(PHP_SHA3_CTX* ctx) {
+ unsigned char LFSRstate = 0x01;
+ unsigned char round;
+
+ for (round = 0; round < 24; ++round) {
+ { // Theta step (see [Keccak Reference, Section 2.3.2])
+ php_hash_uint64 C[5], D;
+ unsigned char x, y;
+ for (x = 0; x < 5; ++x) {
+ C[x] = readLane(x, 0) ^ readLane(x, 1) ^
+ readLane(x, 2) ^ readLane(x, 3) ^ readLane(x, 4);
+ }
+ for (x = 0; x < 5; ++x) {
+ D = C[(x+4)%5] ^ rol64(C[(x+1)%5], 1);
+ for (y = 0; y < 5; ++y) {
+ XORLane(x, y, D);
+ }
+ }
+ }
+
+ { // p and Pi steps (see [Keccak Reference, Sections 2.3.3 and 2.3.4])
+ unsigned char x = 1, y = 0, t;
+ php_hash_uint64 current = readLane(x, y);
+ for (t = 0; t < 24; ++t) {
+ unsigned char r = ((t + 1) * (t + 2) / 2) % 64;
+ unsigned char Y = (2*x + 3*y) % 5;
+ x = y; y = Y;
+ php_hash_uint64 temp = readLane(x, y);
+ writeLane(x, y, rol64(current, r));
+ current = temp;
+ }
+ }
+
+ { // X step (see [Keccak Reference, Section 2.3.1])
+ unsigned char x, y;
+ for (y = 0; y < 5; ++y) {
+ php_hash_uint64 temp[5];
+ for (x = 0; x < 5; ++x) {
+ temp[x] = readLane(x, y);
+ }
+ for (x = 0; x < 5; ++x) {
+ writeLane(x, y, temp[x] ^((~temp[(x+1)%5]) & temp[(x+2)%5]));
+ }
+ }
+ }
+
+ { // i step (see [Keccak Reference, Section 2.3.5])
+ unsigned char j;
+ for (j = 0; j < 7; ++j) {
+ if (LFSR86540(&LFSRstate)) {
+ php_hash_uint64 bitPos = (1<<j) - 1;
+ XORLane(0, 0, (php_hash_uint64)1 << bitPos);
+ }
+ }
+ }
+ }
+}
+
+// ==========================================================================
+
+static void PHP_SHA3_Init(PHP_SHA3_CTX* ctx,
+ int bits) {
+ memset(ctx, 0, sizeof(PHP_SHA3_CTX));
+}
+
+static void PHP_SHA3_Update(PHP_SHA3_CTX* ctx,
+ const unsigned char* buf,
+ unsigned int count,
+ int block_size) {
+ while (count > 0) {
+ int len = block_size - ctx->pos;
+ if (len > count) len = count;
+ count -= len;
+ while (len-- > 0) {
+ ctx->state[ctx->pos++] ^= *(buf++);
+ }
+ if (ctx->pos >= block_size) {
+ permute(ctx);
+ ctx->pos = 0;
+ }
+ }
+}
+
+static void PHP_SHA3_Final(unsigned char* digest,
+ PHP_SHA3_CTX* ctx,
+ int block_size,
+ int digest_size) {
+ int len = digest_size;
+
+ // Pad state to finalize
+ ctx->state[ctx->pos++] ^= 0x06;
+ ctx->state[block_size-1] ^= 0x80;
+ permute(ctx);
+
+ // Square output for digest
+ for(;;) {
+ int bs = (len < block_size) ? len : block_size;
+ memcpy(digest, ctx->state, bs);
+ digest += bs;
+ len -= bs;
+ if (!len) break;
+ permute(ctx);
+ }
+
+ // Zero out context
+ memset(ctx, 0, sizeof(PHP_SHA3_CTX));
+}
+
+// ==========================================================================
+
+#define DECLARE_SHA3_OPS(bits) \
+void PHP_SHA3##bits##Init(PHP_SHA3_##bits##_CTX* ctx) { \
+ PHP_SHA3_Init(ctx, bits); \
+} \
+void PHP_SHA3##bits##Update(PHP_SHA3_##bits##_CTX* ctx, \
+ const unsigned char* input, \
+ unsigned int inputLen) { \
+ PHP_SHA3_Update(ctx, input, inputLen, \
+ (1600 - (2 * bits)) >> 3); \
+} \
+void PHP_SHA3##bits##Final(unsigned char* digest, \
+ PHP_SHA3_##bits##_CTX* ctx) { \
+ PHP_SHA3_Final(digest, ctx, \
+ (1600 - (2 * bits)) >> 3, \
+ bits >> 3); \
+} \
+const php_hash_ops php_hash_sha3_##bits##_ops = { \
+ (php_hash_init_func_t) PHP_SHA3##bits##Init, \
+ (php_hash_update_func_t) PHP_SHA3##bits##Update, \
+ (php_hash_final_func_t) PHP_SHA3##bits##Final, \
+ php_hash_copy, \
+ bits >> 3, \
+ (1600 - (2 * bits)) >> 3, \
+ sizeof(PHP_SHA3_##bits##_CTX) \
+}
+
+DECLARE_SHA3_OPS(224);
+DECLARE_SHA3_OPS(256);
+DECLARE_SHA3_OPS(384);
+DECLARE_SHA3_OPS(512);
+
+#undef DECLARE_SHA3_OPS
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
extern const php_hash_ops php_hash_sha256_ops;
extern const php_hash_ops php_hash_sha384_ops;
extern const php_hash_ops php_hash_sha512_ops;
+extern const php_hash_ops php_hash_sha3_224_ops;
+extern const php_hash_ops php_hash_sha3_256_ops;
+extern const php_hash_ops php_hash_sha3_384_ops;
+extern const php_hash_ops php_hash_sha3_512_ops;
extern const php_hash_ops php_hash_ripemd128_ops;
extern const php_hash_ops php_hash_ripemd160_ops;
extern const php_hash_ops php_hash_ripemd256_ops;
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Sara Golemon <pollita@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef PHP_HASH_SHA3_H
+#define PHP_HASH_SHA3_H
+
+#include "php.h"
+#include "ext/hash/php_hash.h"
+
+typedef struct {
+ unsigned char state[200]; // 5 * 5 * sizeof(uint64)
+ php_hash_uint32 pos;
+} PHP_SHA3_CTX;
+
+typedef PHP_SHA3_CTX PHP_SHA3_224_CTX;
+typedef PHP_SHA3_CTX PHP_SHA3_256_CTX;
+typedef PHP_SHA3_CTX PHP_SHA3_384_CTX;
+typedef PHP_SHA3_CTX PHP_SHA3_512_CTX;
+
+PHP_HASH_API void PHP_SHA3224Init(PHP_SHA3_224_CTX*);
+PHP_HASH_API void PHP_SHA3224Update(PHP_SHA3_224_CTX*, const unsigned char*, unsigned int);
+PHP_HASH_API void PHP_SAH3224Final(unsigned char[32], PHP_SHA3_224_CTX*);
+
+PHP_HASH_API void PHP_SHA3256Init(PHP_SHA3_256_CTX*);
+PHP_HASH_API void PHP_SHA3256Update(PHP_SHA3_256_CTX*, const unsigned char*, unsigned int);
+PHP_HASH_API void PHP_SAH3256Final(unsigned char[32], PHP_SHA3_256_CTX*);
+
+PHP_HASH_API void PHP_SHA3384Init(PHP_SHA3_384_CTX*);
+PHP_HASH_API void PHP_SHA3384Update(PHP_SHA3_384_CTX*, const unsigned char*, unsigned int);
+PHP_HASH_API void PHP_SAH3384Final(unsigned char[32], PHP_SHA3_384_CTX*);
+
+PHP_HASH_API void PHP_SHA3512Init(PHP_SHA3_512_CTX*);
+PHP_HASH_API void PHP_SHA3512Update(PHP_SHA3_512_CTX*, const unsigned char*, unsigned int);
+PHP_HASH_API void PHP_SAH3512Final(unsigned char[32], PHP_SHA3_512_CTX*);
+
+#endif
===Done===
--EXPECTF--
*** Testing hash_algos() : basic functionality ***
-array(46) {
+array(50) {
[%d]=>
string(3) "md2"
[%d]=>
[%d]=>
string(6) "sha512"
[%d]=>
+ string(8) "sha3-224"
+ [%d]=>
+ string(8) "sha3-256"
+ [%d]=>
+ string(8) "sha3-384"
+ [%d]=>
+ string(8) "sha3-512"
+ [%d]=>
string(9) "ripemd128"
[%d]=>
string(9) "ripemd160"
string(6) "sha512"
string(128) "caced3db8e9e3a5543d5b933bcbe9e7834e6667545c3f5d4087b58ec8d78b4c8a4a5500c9b88f65f7368810ba9905e51f1cff3b25a5dccf76634108fb4e7ce13"
string(128) "caced3db8e9e3a5543d5b933bcbe9e7834e6667545c3f5d4087b58ec8d78b4c8a4a5500c9b88f65f7368810ba9905e51f1cff3b25a5dccf76634108fb4e7ce13"
+string(8) "sha3-224"
+string(56) "7e1126cffee98e5c4b0e9dd5c6efabd5c9356d668e9a2d3cfab724d4"
+string(56) "7e1126cffee98e5c4b0e9dd5c6efabd5c9356d668e9a2d3cfab724d4"
+string(8) "sha3-256"
+string(64) "834abfed9197af09cbe66b7748c65a050a3755ef7a556d6764eb6eabc93b4c7a"
+string(64) "834abfed9197af09cbe66b7748c65a050a3755ef7a556d6764eb6eabc93b4c7a"
+string(8) "sha3-384"
+string(96) "c9016992586f7a8663c5379ed892349c1140ad258f7c44ee82f61f0b8cb75c675012ea94dc1314e06699be2d1465f67b"
+string(96) "c9016992586f7a8663c5379ed892349c1140ad258f7c44ee82f61f0b8cb75c675012ea94dc1314e06699be2d1465f67b"
+string(8) "sha3-512"
+string(128) "5f85341bc9c6621406bf1841c4ce01727ea8759fdf2927106c3e70a75ad9fffd095b87f995aeee844e1a2c287e1195ce809b9bdb1c31258f7fc098175b6de0b4"
+string(128) "5f85341bc9c6621406bf1841c4ce01727ea8759fdf2927106c3e70a75ad9fffd095b87f995aeee844e1a2c287e1195ce809b9bdb1c31258f7fc098175b6de0b4"
string(9) "ripemd128"
string(32) "5f1bc5f5aeaf747574dd34a6535cd94a"
string(32) "5f1bc5f5aeaf747574dd34a6535cd94a"
string(6) "sha512"
string(128) "caced3db8e9e3a5543d5b933bcbe9e7834e6667545c3f5d4087b58ec8d78b4c8a4a5500c9b88f65f7368810ba9905e51f1cff3b25a5dccf76634108fb4e7ce13"
string(128) "28d7c721433782a880f840af0c3f3ea2cad4ef55de2114dda9d504cedeb110e1cf2519c49e4b5da3da4484bb6ba4fd1621ceadc6408f4410b2ebe9d83a4202c2"
+string(8) "sha3-224"
+string(56) "7e1126cffee98e5c4b0e9dd5c6efabd5c9356d668e9a2d3cfab724d4"
+string(56) "9a21a5464794c2c9784df50cf89cf72234e11941bddaee93f912753e"
+string(8) "sha3-256"
+string(64) "834abfed9197af09cbe66b7748c65a050a3755ef7a556d6764eb6eabc93b4c7a"
+string(64) "57aa7a90f29b5ab66592760592780da247fd39b4c911773687450f9df8cc8ed0"
+string(8) "sha3-384"
+string(96) "c9016992586f7a8663c5379ed892349c1140ad258f7c44ee82f61f0b8cb75c675012ea94dc1314e06699be2d1465f67b"
+string(96) "5d6d7e42b241288bc707b74c50f90a37d69a4afa854ca72021a22cb379356e53b6233aea1be2f33d393d6effa9b5e36c"
+string(8) "sha3-512"
+string(128) "5f85341bc9c6621406bf1841c4ce01727ea8759fdf2927106c3e70a75ad9fffd095b87f995aeee844e1a2c287e1195ce809b9bdb1c31258f7fc098175b6de0b4"
+string(128) "9b88c689bc13a36e6983b32e8ee9464d63b619f246ca451d1fe2a6c9670f01e71d0c8eb245f3204d27d27c056f2a0fef76a1e3bc30fb74cccbc984dbd4883ae6"
string(9) "ripemd128"
string(32) "5f1bc5f5aeaf747574dd34a6535cd94a"
string(32) "f95f5e22b8875ee0c48219ae97f0674b"
--- /dev/null
+--TEST--
+sha3 algorithm
+--SKIPIF--
+<?php if(!extension_loaded("hash")) print "skip"; ?>
+--FILE--
+<?php
+
+// Test vectors taken from a combination of NIST FIPS-202,
+// Wikipedia reference vectors,
+// and output from reference implementation
+$subjects = [
+ '',
+ 'a',
+ 'The quick brown fox jumps over the lazy dog',
+ 'The quick brown fox jumps over the lazy dog.',
+ str_repeat('a', 257),
+ str_repeat("\xA3", 200),
+];
+foreach ($subjects as $subject) {
+ echo '== ', urlencode($subject), " ==\n";
+ foreach ([224, 256, 384, 512] as $bits) {
+ echo $bits, ': ', hash("sha3-$bits", $subject), "\n";
+ }
+}
+--EXPECT--
+== ==
+224: 6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7
+256: a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a
+384: 0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004
+512: a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26
+== a ==
+224: 9e86ff69557ca95f405f081269685b38e3a819b309ee942f482b6a8b
+256: 80084bf2fba02475726feb2cab2d8215eab14bc6bdd8bfb2c8151257032ecd8b
+384: 1815f774f320491b48569efec794d249eeb59aae46d22bf77dafe25c5edc28d7ea44f93ee1234aa88f61c91912a4ccd9
+512: 697f2d856172cb8309d6b8b97dac4de344b549d4dee61edfb4962d8698b7fa803f4f93ff24393586e28b5b957ac3d1d369420ce53332712f997bd336d09ab02a
+== The+quick+brown+fox+jumps+over+the+lazy+dog ==
+224: d15dadceaa4d5d7bb3b48f446421d542e08ad8887305e28d58335795
+256: 69070dda01975c8c120c3aada1b282394e7f032fa9cf32f4cb2259a0897dfc04
+384: 7063465e08a93bce31cd89d2e3ca8f602498696e253592ed26f07bf7e703cf328581e1471a7ba7ab119b1a9ebdf8be41
+512: 01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450
+== The+quick+brown+fox+jumps+over+the+lazy+dog. ==
+224: 2d0708903833afabdd232a20201176e8b58c5be8a6fe74265ac54db0
+256: a80f839cd4f83f6c3dafc87feae470045e4eb0d366397d5c6ce34ba1739f734d
+384: 1a34d81695b622df178bc74df7124fe12fac0f64ba5250b78b99c1273d4b080168e10652894ecad5f1f4d5b965437fb9
+512: 18f4f4bd419603f95538837003d9d254c26c23765565162247483f65c50303597bc9ce4d289f21d1c2f1f458828e33dc442100331b35e7eb031b5d38ba6460f8
+== aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ==
+224: 10dd422d71c42ee102a0c4bd398b5b85470341a0794702c954b022ba
+256: 6d115e8744deef792419e8bdb8567d74844e0fa5c2d5e474a19de87ac001449f
+384: c9df41fa389101cde63447257835464d89fd3974e5813f3f58d30e0296e89486e2d4bfc2b4089cd3bb860a20263322b8
+512: 5008048b64c14975181175f157be4a780c3d443d2177edf323d57884bc7e3979b9b53bca1325e880df3da0d97c435693441cb5527fbe950f5585678dfbb37785
+== %A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3 ==
+224: 9376816aba503f72f96ce7eb65ac095deee3be4bf9bbc2a1cb7e11e0
+256: 79f38adec5c20307a98ef76e8324afbfd46cfd81b22e3973c65fa1bd9de31787
+384: 1881de2ca7e41ef95dc4732b8f5f002b189cc1e42b74168ed1732649ce1dbcdd76197a31fd55ee989f2d7050dd473e8f
+512: e76dfad22084a8b1467fcf2ffa58361bec7628edf5f3fdc0e4805dc48caeeca81b7c13c30adf52a3659584739a2df46be589c51ca1a4a8416df6545a1ce8ba00
+