1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Simple `generate_token` service, independent of the rest of the nitcorn framework
20 # Generate a random token of `length` chars long
22 # The default value of `length` is 64, but it may change in the future.
24 # On Linux, `/dev/urandom` is used as source of random data.
25 # On other platforms, `rand` is used to generate pseudo-random data.
26 # using `rand` can be forced with `force_rand`.
28 # Uses `base64` to represent random bytes in the readable ASCII range.
32 # assert generate_token(4, force_rand=true) == "AMzV"
33 # assert generate_token(8, force_rand=true) == "G8Oibf+s"
34 # assert generate_token(16, force_rand=true) == "VUCPPlWLR8lZQvbb"
35 # assert generate_token(32, force_rand=true) == "JtJB9vJd+u3c6dyL+Q8U5IKZIueRoZ6h"
36 # assert generate_token( force_rand=true) == "+59Ev7/35sOPeq1y8mI5+npAE1SYbfhVgGeDAq2vo5N3mnWxSJvucd6H3HwxT8v8"
38 fun generate_token
(length
: nullable Int, force_rand
: nullable Bool): String
40 length
= length
or else 64
42 # TODO generate more entropy
44 # Generate random bytes
45 var bin_length
= ((length
.to_f
/4.0).ceil
* 3.0).to_i
48 var linux_random
= "/dev/urandom"
49 if linux_random
.file_exists
then
50 # Use Linux's random number generator
51 var reader
= new FileReader.open
(linux_random
)
52 bytes
= reader
.read_bytes
(bin_length
)
56 # TODO other operating systems random number generators
59 if bytes
== null or bytes
.length
!= bin_length
or force_rand
== true then
60 bytes
= new Bytes.with_capacity
(bin_length
)
61 for i
in bin_length
.times
do bytes
.add
256.rand
.to_b
64 # Encode in base64 so it is readable
65 var str
= bytes
.encode_base64
.to_s
66 if str
.length
> length
then
67 # This happens if `length % 4 != 0`
68 str
= str
.substring
(0, length
)