Skip to content

Commit 9b8e5e5

Browse files
author
Yani
committed
change session id generator to normal string based generator
1 parent 19358d0 commit 9b8e5e5

File tree

3 files changed

+23
-83
lines changed

3 files changed

+23
-83
lines changed

src/Config.php

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ public function getSidPrefix(): string
121121

122122
public function setSidLength(int $sid_length): self
123123
{
124-
if ($sid_length < 22 || $sid_length > 256) {
124+
if ($sid_length < 32 || $sid_length > 256) {
125125
throw new InvalidArgumentException(
126-
'$sid_length must be at least 22 and not greater than 256'
126+
'sid_length must be at least 32 and not greater than 256'
127127
);
128128
}
129129

@@ -136,28 +136,17 @@ public function getSidLength(): int
136136
return $this->sid_length;
137137
}
138138

139-
protected int $sid_bits_per_character = 4;
139+
protected string $sid_charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
140140

141-
public function setSidBitsPerCharacter(int $sid_bits_per_character): self
141+
public function setSidCharset(string $sid_charset): self
142142
{
143-
if ($sid_bits_per_character < 4 || $sid_bits_per_character > 6) {
144-
throw new InvalidArgumentException(
145-
'$sid_bits_per_character must be at least 4 and not greater than than 6'
146-
);
147-
}
148-
149-
$this->sid_bits_per_character = $sid_bits_per_character;
150-
151-
if ($sid_bits_per_character >= 5 && $this->sid_length < 26) {
152-
$this->setSidLength(26);
153-
}
154-
143+
$this->sid_charset = $sid_charset;
155144
return $this;
156145
}
157146

158-
public function getSidBitsPerCharacter(): int
147+
public function getSidCharset(): string
159148
{
160-
return $this->sid_bits_per_character;
149+
return $this->sid_charset;
161150
}
162151

163152
protected bool $lazy_write = true;

src/Factory.php

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,11 @@ public function configFromArray(array $settings): Config
131131
$config->setSidLength($settings['sid_length']);
132132
}
133133

134-
if (isset($settings['sid_bits_per_character'])) {
135-
if (!is_int($settings['sid_bits_per_character'])) {
136-
throw new InvalidArgumentException('sid_bits_per_character must be an integer');
134+
if (isset($settings['sid_charset'])) {
135+
if (!is_string($settings['sid_charset'])) {
136+
throw new InvalidArgumentException('sid_charset must be a string');
137137
}
138-
$config->setSidBitsPerCharacter($settings['sid_bits_per_character']);
138+
$config->setSidCharset($settings['sid_charset']);
139139
}
140140

141141
if (isset($settings['lazy_write'])) {
@@ -203,10 +203,6 @@ public function configFromSystem(): Config
203203
$config->setSidLength((int) ini_get('session.sid_length'));
204204
}
205205

206-
if (ini_get('session.sid_bits_per_character') !== false) {
207-
$config->setSidBitsPerCharacter((int) ini_get('session.sid_bits_per_character'));
208-
}
209-
210206
$config->setLazyWrite((bool) ini_get('session.lazy_write'));
211207

212208
return $config;

src/SessionId.php

Lines changed: 12 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -22,74 +22,29 @@ public function __toString(): string
2222

2323
public function create_sid(): string
2424
{
25-
$prefix = $this->config->getSidPrefix();
26-
$desiredOutputLength = $this->config->getSidLength() - strlen($prefix);
27-
$bitsPerCharacter = $this->config->getSidBitsPerCharacter();
25+
$length = $this->config->getSidLength();
26+
$charset = $this->config->getSidCharset();
27+
$prefix = $this->config->getSidPrefix();
2828

29-
$bytesNeeded = (int) ceil($desiredOutputLength * $bitsPerCharacter / 8);
30-
$randomInputBytes = random_bytes(max(1, $bytesNeeded));
29+
$lengthWithoutPrefix = $length - \strlen($prefix);
3130

32-
// The below is translated from function bin_to_readable in the PHP source
33-
// (ext/session/session.c)
34-
static $hexconvtab = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,-';
35-
36-
$out = '';
37-
38-
$p = 0;
39-
$q = strlen($randomInputBytes);
40-
$w = 0;
41-
$have = 0;
42-
43-
$mask = (1 << $bitsPerCharacter) - 1;
44-
45-
$charsRemaining = $desiredOutputLength;
46-
while ($charsRemaining--) {
47-
if ($have < $bitsPerCharacter) {
48-
if ($p < $q) {
49-
$byte = ord($randomInputBytes[$p++]);
50-
$w |= ($byte << $have);
51-
$have += 8;
52-
} else {
53-
// Should never happen. Input must be large enough.
54-
break;
55-
}
56-
}
57-
58-
// consume $bitsPerCharacter bits
59-
$out .= $hexconvtab[$w & $mask];
60-
$w >>= $bitsPerCharacter;
61-
$have -= $bitsPerCharacter;
31+
$pieces = [];
32+
$max = \strlen($charset) - 1;
33+
for ($i = 0; $i < $lengthWithoutPrefix; ++$i) {
34+
$pieces [] = $charset[\random_int(0, $max)];
6235
}
6336

64-
return $prefix . $out;
37+
return $prefix . \implode('', $pieces);
6538
}
6639

6740
public function validate_sid(string $id): bool
6841
{
69-
if (strlen($id) !== $this->config->getSidLength()) {
42+
if (\strlen($id) !== $this->config->getSidLength()) {
7043
return false;
7144
}
7245

73-
// Prefix might not validate under the rules for bits=4 or bits=5
74-
$prefix = $this->config->getSidPrefix();
75-
if ($prefix) {
76-
$id = substr($id, strlen($prefix));
77-
}
78-
79-
switch ($this->config->getSidBitsPerCharacter()) {
80-
case 4:
81-
// 0123456789abcdef
82-
return preg_match('/^[0-9a-f]+$/', $id) === 1;
83-
84-
case 5:
85-
// 0123456789abcdefghijklmnopqrstuv
86-
return preg_match('/^[0-9a-v]+$/', $id) === 1;
87-
88-
case 6:
89-
// 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,-
90-
return preg_match('/^[0-9a-zA-Z,-]+$/', $id) === 1;
91-
}
46+
$pregSafeString = \preg_quote($this->config->getSidCharset(), '/');
9247

93-
return false;
48+
return \preg_match('/^[' . $pregSafeString . ']+$/', $id) === 1;
9449
}
9550
}

0 commit comments

Comments
 (0)