12# define __alignof__ __alignof
16# define __alignof__(type) offsetof (struct { char c; type member;}, member)
26# include <sys/param.h>
27# include <sys/types.h>
37 return strncpy(dst, src,
len) +
n;
41# define MIN(a, b) (((a) < (b)) ? (a) : (b))
44# define MAX(a, b) (((a) > (b)) ? (a) : (b))
56#if defined(PHP_WIN32) || (!defined(WORDS_BIGENDIAN))
58 (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
65static const unsigned char fillbuf[64] = { 0x80, 0 };
69static const uint32_t
K[64] = {
70 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
71 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
72 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
73 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
74 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
75 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
76 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
77 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
78 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
79 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
80 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
81 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
82 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
83 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
84 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
85 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
92 const uint32_t *words =
buffer;
93 size_t nwords =
len /
sizeof (uint32_t);
96 uint32_t
a = ctx->
H[0];
97 uint32_t b = ctx->
H[1];
98 uint32_t c = ctx->
H[2];
99 uint32_t d = ctx->
H[3];
100 uint32_t e = ctx->
H[4];
101 uint32_t f = ctx->
H[5];
102 uint32_t g = ctx->
H[6];
103 uint32_t h = ctx->
H[7];
127#define Ch(x, y, z) ((x & y) ^ (~x & z))
128#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
129#define S0(x) (CYCLIC (x, 2) ^ CYCLIC (x, 13) ^ CYCLIC (x, 22))
130#define S1(x) (CYCLIC (x, 6) ^ CYCLIC (x, 11) ^ CYCLIC (x, 25))
131#define R0(x) (CYCLIC (x, 7) ^ CYCLIC (x, 18) ^ (x >> 3))
132#define R1(x) (CYCLIC (x, 17) ^ CYCLIC (x, 19) ^ (x >> 10))
136#define CYCLIC(w, s) ((w >> s) | (w << (32 - s)))
139 for (t = 0; t < 16; ++t) {
140 W[t] =
SWAP (*words);
143 for (t = 16; t < 64; ++t)
144 W[t] =
R1 (
W[t - 2]) +
W[t - 7] +
R0 (
W[t - 15]) +
W[t - 16];
147 for (t = 0; t < 64; ++t) {
148 uint32_t
T1 = h +
S1 (e) +
Ch (e, f, g) +
K[t] +
W[t];
149 uint32_t T2 =
S0 (
a) +
Maj (
a, b, c);
189static void sha256_init_ctx(
struct sha256_ctx *ctx) {
190 ctx->
H[0] = 0x6a09e667;
191 ctx->
H[1] = 0xbb67ae85;
192 ctx->
H[2] = 0x3c6ef372;
193 ctx->
H[3] = 0xa54ff53a;
194 ctx->
H[4] = 0x510e527f;
195 ctx->
H[5] = 0x9b05688c;
196 ctx->
H[6] = 0x1f83d9ab;
197 ctx->
H[7] = 0x5be0cd19;
209static void * sha256_finish_ctx(
struct sha256_ctx *ctx,
void *resbuf) {
211 uint32_t bytes = ctx->
buflen;
216 ctx->
total[0] += bytes;
217 if (ctx->
total[0] < bytes) {
221 pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
225 *(uint32_t *) &ctx->
buffer[bytes + pad + 4] =
SWAP (ctx->
total[0] << 3);
227 (ctx->
total[0] >> 29));
230 sha256_process_block(ctx->
buffer, bytes + pad + 8, ctx);
233 for (i = 0; i < 8; ++i) {
234 ((uint32_t *) resbuf)[i] =
SWAP(ctx->
H[i]);
245 size_t left_over = ctx->
buflen;
246 size_t add = 128 - left_over >
len ?
len : 128 - left_over;
252 sha256_process_block(ctx->
buffer, ctx->
buflen & ~63, ctx);
267# define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint32_t) != 0)
269# define UNALIGNED_P(p) (((uintptr_t) p) % sizeof (uint32_t) != 0)
277 sha256_process_block(
buffer,
len & ~63, ctx);
285 size_t left_over = ctx->
buflen;
289 if (left_over >= 64) {
290 sha256_process_block(ctx->
buffer, 64, ctx);
294 ctx->
buflen = (uint32_t)left_over;
301static const char sha256_salt_prefix[] =
"$5$";
304static const char sha256_rounds_prefix[] =
"rounds=";
307#define SALT_LEN_MAX 16
309#define ROUNDS_DEFAULT 5000
311#define ROUNDS_MIN 1000
313#define ROUNDS_MAX 999999999
316static const char b64t[64] =
317"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
335 char *copied_key =
NULL;
336 char *copied_salt =
NULL;
341 bool rounds_custom = 0;
345 if (
strncmp(sha256_salt_prefix, salt,
sizeof(sha256_salt_prefix) - 1) == 0) {
347 salt +=
sizeof(sha256_salt_prefix) - 1;
350 if (
strncmp(salt, sha256_rounds_prefix,
sizeof(sha256_rounds_prefix) - 1) == 0) {
351 const char *num = salt +
sizeof(sha256_rounds_prefix) - 1;
356 if (srounds < ROUNDS_MIN || srounds >
ROUNDS_MAX) {
367 char *tmp_key =
NULL;
369 char *tmp_salt =
NULL;
380 if ((uintptr_t)salt %
__alignof__(uint32_t) != 0) {
384 copied_salt[salt_len] = 0;
388 sha256_init_ctx(&ctx);
391 sha256_process_bytes(
key, key_len, &ctx);
396 sha256_process_bytes(salt, salt_len, &ctx);
401 sha256_init_ctx(&alt_ctx);
404 sha256_process_bytes(
key, key_len, &alt_ctx);
407 sha256_process_bytes(salt, salt_len, &alt_ctx);
410 sha256_process_bytes(
key, key_len, &alt_ctx);
414 sha256_finish_ctx(&alt_ctx, alt_result);
417 for (cnt = key_len; cnt > 32; cnt -= 32) {
418 sha256_process_bytes(alt_result, 32, &ctx);
420 sha256_process_bytes(alt_result, cnt, &ctx);
424 for (cnt = key_len; cnt > 0; cnt >>= 1) {
425 if ((cnt & 1) != 0) {
426 sha256_process_bytes(alt_result, 32, &ctx);
428 sha256_process_bytes(
key, key_len, &ctx);
433 sha256_finish_ctx(&ctx, alt_result);
436 sha256_init_ctx(&alt_ctx);
439 for (cnt = 0; cnt < key_len; ++cnt) {
440 sha256_process_bytes(
key, key_len, &alt_ctx);
444 sha256_finish_ctx(&alt_ctx, temp_result);
448 cp = p_bytes =
do_alloca(key_len, use_heap_p_bytes);
449 for (cnt = key_len; cnt >= 32; cnt -= 32) {
450 cp = zend_mempcpy((
void *)
cp, (
const void *)temp_result, 32);
455 sha256_init_ctx(&alt_ctx);
458 for (cnt = 0; cnt < (size_t) (16 + alt_result[0]); ++cnt) {
459 sha256_process_bytes(salt, salt_len, &alt_ctx);
463 sha256_finish_ctx(&alt_ctx, temp_result);
467 cp = s_bytes =
do_alloca(salt_len, use_heap_s_bytes);
468 for (cnt = salt_len; cnt >= 32; cnt -= 32) {
469 cp = zend_mempcpy(
cp, temp_result, 32);
475 for (cnt = 0; cnt < rounds; ++cnt) {
477 sha256_init_ctx(&ctx);
480 if ((cnt & 1) != 0) {
481 sha256_process_bytes(p_bytes, key_len, &ctx);
483 sha256_process_bytes(alt_result, 32, &ctx);
488 sha256_process_bytes(s_bytes, salt_len, &ctx);
493 sha256_process_bytes(p_bytes, key_len, &ctx);
497 if ((cnt & 1) != 0) {
498 sha256_process_bytes(alt_result, 32, &ctx);
500 sha256_process_bytes(p_bytes, key_len, &ctx);
504 sha256_finish_ctx(&ctx, alt_result);
510 buflen -=
sizeof(sha256_salt_prefix) - 1;
530#define b64_from_24bit(B2, B1, B0, N) \
532 unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \
534 while (n-- > 0 && buflen > 0) \
536 *cp++ = b64t[w & 0x3f]; \
563 sha256_init_ctx(&ctx);
564 sha256_finish_ctx(&ctx, alt_result);
571 if (copied_key !=
NULL) {
574 if (copied_salt !=
NULL) {
577 if (tmp_key !=
NULL) {
580 if (tmp_salt !=
NULL) {
600 int needed = (
sizeof(sha256_salt_prefix) - 1
601 +
sizeof(sha256_rounds_prefix) + 9 + 1
602 + (int)
strlen(salt) + 1 + 43 + 1);
605 char *new_buffer = (
char *) realloc(
buffer, needed);
606 if (new_buffer ==
NULL) {
627 "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23"
628 "\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad" },
630 {
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
631 "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39"
632 "\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1" },
635 "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24"
636 "\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55" },
638 "\xca\x97\x81\x12\xca\x1b\xbd\xca\xfa\xc2\x31\xb3\x9a\x23\xdc\x4d"
639 "\xa7\x86\xef\xf8\x14\x7c\x4e\x72\xb9\x80\x77\x85\xaf\xee\x48\xbb" },
641 "\xf7\x84\x6f\x55\xcf\x23\xe1\x4e\xeb\xea\xb5\xb4\xe1\x55\x0c\xad"
642 "\x5b\x50\x9e\x33\x48\xfb\xc4\xef\xa3\xa1\x41\x3d\x39\x3c\xb6\x50" },
643 {
"abcdefghijklmnopqrstuvwxyz",
644 "\x71\xc4\x80\xdf\x93\xd6\xae\x2f\x1e\xfa\xd1\x44\x7c\x66\xc9\x52"
645 "\x5e\x31\x62\x18\xcf\x51\xfc\x8d\x9e\xd8\x32\xf2\xda\xf1\x8b\x73" },
646 {
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
647 "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39"
648 "\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1" },
649 {
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
650 "\xdb\x4b\xfc\xbd\x4d\xa0\xcd\x85\xa6\x0c\x3c\x37\xd3\xfb\xd8\x80"
651 "\x5c\x77\xf1\x5f\xc6\xb1\xfd\xfe\x61\x4e\xe0\xa7\xc8\xfd\xb4\xc0" },
652 {
"123456789012345678901234567890123456789012345678901234567890"
653 "12345678901234567890",
654 "\xf3\x71\xbc\x4a\x31\x1f\x2b\x00\x9e\xef\x95\x2d\xd8\x3c\xa8\x0e"
655 "\x2b\x60\x02\x6c\x8e\x93\x55\x92\xd0\xf9\xc3\x08\x45\x3c\x81\x3e" }
657#define ntests (sizeof (tests) / sizeof (tests[0]))
664 const char *expected;
667 {
"$5$saltstring",
"Hello world!",
668 "$5$saltstring$5B8vYYiY.CVt1RlTTf8KbXBH3hsxY/GNooZaBBGWEc5" },
669 {
"$5$rounds=10000$saltstringsaltstring",
"Hello world!",
670 "$5$rounds=10000$saltstringsaltst$3xv.VbSHBb41AL9AvLeujZkZRBAwqFMz2."
672 {
"$5$rounds=5000$toolongsaltstring",
"This is just a test",
673 "$5$rounds=5000$toolongsaltstrin$Un/5jzAHMgOGZ5.mWJpuVolil07guHPvOW8"
675 {
"$5$rounds=1400$anotherlongsaltstring",
676 "a very much longer text to encrypt. This one even stretches over more"
678 "$5$rounds=1400$anotherlongsalts$Rx.j8H.h8HjEDGomFU8bDkXm3XIUnzyxf12"
680 {
"$5$rounds=77777$short",
681 "we have a short salt string but not a short password",
682 "$5$rounds=77777$short$JiO1O3ZpDAxGJeaDIuqCoEFysAe1mZNJRs3pw0KQRd/" },
683 {
"$5$rounds=123456$asaltof16chars..",
"a short string",
684 "$5$rounds=123456$asaltof16chars..$gP3VQ/6X7UUEW3HkBn2w1/Ptq2jxPyzV/"
686 {
"$5$rounds=10$roundstoolow",
"the minimum number is still observed",
687 "$5$rounds=1000$roundstoolow$yfvwcWrQ8l/K0DAWyuPMDNHpIVlTQebY9l/gL97"
690#define ntests2 (sizeof (tests2) / sizeof (tests2[0]))
699 static const char expected[32] =
700 "\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67"
701 "\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0";
703 for (cnt = 0; cnt < (int) ntests; ++cnt) {
704 sha256_init_ctx(&ctx);
705 sha256_process_bytes(tests[cnt].input,
strlen(tests[cnt].input), &ctx);
706 sha256_finish_ctx(&ctx, sum);
707 if (memcmp(tests[cnt].
result, sum, 32) != 0) {
708 printf(
"test %d run %d failed\n", cnt, 1);
712 sha256_init_ctx(&ctx);
713 for (i = 0; tests[cnt].input[i] !=
'\0'; ++i) {
714 sha256_process_bytes(&tests[cnt].input[i], 1, &ctx);
716 sha256_finish_ctx(&ctx, sum);
717 if (memcmp(tests[cnt].
result, sum, 32) != 0) {
718 printf(
"test %d run %d failed\n", cnt, 2);
726 sha256_init_ctx(&ctx);
727 for (i = 0; i < 1000; ++i) {
728 sha256_process_bytes (
buf,
sizeof (
buf), &ctx);
731 sha256_finish_ctx(&ctx, sum);
733 if (memcmp(expected, sum, 32) != 0) {
734 printf(
"test %d failed\n", cnt);
738 for (cnt = 0; cnt < ntests2; ++cnt) {
740 if (
strcmp(
cp, tests2[cnt].expected) != 0) {
741 printf(
"test %d: expected \"%s\", got \"%s\"\n", cnt, tests2[cnt].expected,
cp);
747 puts(
"all tests OK");
printf(string $format, mixed ... $values)
strcspn(string $string, string $characters, int $offset=0, ?int $length=null)
#define __alignof__(type)
#define b64_from_24bit(B2, B1, B0, N)
char * __php_stpncpy(char *dst, const char *src, size_t len)
char * php_sha256_crypt_r(const char *key, const char *salt, char *buffer, int buflen)
char * php_sha256_crypt(const char *key, const char *salt)
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
#define __alignof__(type)
unsigned char key[REFLECTION_KEY_LEN]
strncmp(string $string1, string $string2, int $length)
strcmp(string $string1, string $string2)
#define ZEND_STRTOUL(s0, s1, base)
#define ALLOCA_FLAG(name)
#define do_alloca(p, use_heap)
#define ZEND_SECURE_ZERO(var, size)
#define ZEND_SET_ALIGNED(alignment, decl)
#define free_alloca(p, use_heap)
#define SET_ALLOCA_FLAG(name)