mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-03 05:08:14 +00:00
Require CSPRNG in UUID generation where applicable
This commit is contained in:
@@ -16,6 +16,9 @@ VERSION_7_TIME_SHIFT :: 80
|
|||||||
VERSION_7_COUNTER_MASK :: 0x00000000_00000fff_00000000_00000000
|
VERSION_7_COUNTER_MASK :: 0x00000000_00000fff_00000000_00000000
|
||||||
VERSION_7_COUNTER_SHIFT :: 64
|
VERSION_7_COUNTER_SHIFT :: 64
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
NO_CSPRNG_ERROR :: "The context random generator is not cryptographic. See the documentation for an example of how to set one up."
|
||||||
|
|
||||||
Read_Error :: enum {
|
Read_Error :: enum {
|
||||||
None,
|
None,
|
||||||
Invalid_Length,
|
Invalid_Length,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package uuid
|
package uuid
|
||||||
|
|
||||||
|
import "base:runtime"
|
||||||
import "core:math/rand"
|
import "core:math/rand"
|
||||||
import "core:mem"
|
|
||||||
import "core:time"
|
import "core:time"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -33,8 +33,9 @@ generate_v1 :: proc(clock_seq: u16, node: Maybe([6]u8) = nil) -> (result: Identi
|
|||||||
|
|
||||||
if realized_node, ok := node.?; ok {
|
if realized_node, ok := node.?; ok {
|
||||||
mutable_node := realized_node
|
mutable_node := realized_node
|
||||||
mem.copy_non_overlapping(&result[10], &mutable_node[0], 6)
|
runtime.mem_copy_non_overlapping(&result[10], &mutable_node[0], 6)
|
||||||
} else {
|
} else {
|
||||||
|
assert(.Cryptographic in runtime.random_generator_query_info(context.random_generator), NO_CSPRNG_ERROR)
|
||||||
bytes_generated := rand.read(result[10:])
|
bytes_generated := rand.read(result[10:])
|
||||||
assert(bytes_generated == 6, "RNG failed to generate 6 bytes for UUID v1.")
|
assert(bytes_generated == 6, "RNG failed to generate 6 bytes for UUID v1.")
|
||||||
}
|
}
|
||||||
@@ -57,6 +58,7 @@ Returns:
|
|||||||
- result: The generated UUID.
|
- result: The generated UUID.
|
||||||
*/
|
*/
|
||||||
generate_v4 :: proc() -> (result: Identifier) {
|
generate_v4 :: proc() -> (result: Identifier) {
|
||||||
|
assert(.Cryptographic in runtime.random_generator_query_info(context.random_generator), NO_CSPRNG_ERROR)
|
||||||
bytes_generated := rand.read(result[:])
|
bytes_generated := rand.read(result[:])
|
||||||
assert(bytes_generated == 16, "RNG failed to generate 16 bytes for UUID v4.")
|
assert(bytes_generated == 16, "RNG failed to generate 16 bytes for UUID v4.")
|
||||||
|
|
||||||
@@ -94,6 +96,7 @@ generate_v6 :: proc(clock_seq: Maybe(u16) = nil, node: Maybe([6]u8) = nil) -> (r
|
|||||||
result[8] |= cast(u8)(realized_clock_seq & 0x3F00 >> 8)
|
result[8] |= cast(u8)(realized_clock_seq & 0x3F00 >> 8)
|
||||||
result[9] = cast(u8)realized_clock_seq
|
result[9] = cast(u8)realized_clock_seq
|
||||||
} else {
|
} else {
|
||||||
|
assert(.Cryptographic in runtime.random_generator_query_info(context.random_generator), NO_CSPRNG_ERROR)
|
||||||
temporary: [2]u8
|
temporary: [2]u8
|
||||||
bytes_generated := rand.read(temporary[:])
|
bytes_generated := rand.read(temporary[:])
|
||||||
assert(bytes_generated == 2, "RNG failed to generate 2 bytes for UUID v1.")
|
assert(bytes_generated == 2, "RNG failed to generate 2 bytes for UUID v1.")
|
||||||
@@ -103,8 +106,9 @@ generate_v6 :: proc(clock_seq: Maybe(u16) = nil, node: Maybe([6]u8) = nil) -> (r
|
|||||||
|
|
||||||
if realized_node, ok := node.?; ok {
|
if realized_node, ok := node.?; ok {
|
||||||
mutable_node := realized_node
|
mutable_node := realized_node
|
||||||
mem.copy_non_overlapping(&result[10], &mutable_node[0], 6)
|
runtime.mem_copy_non_overlapping(&result[10], &mutable_node[0], 6)
|
||||||
} else {
|
} else {
|
||||||
|
assert(.Cryptographic in runtime.random_generator_query_info(context.random_generator), NO_CSPRNG_ERROR)
|
||||||
bytes_generated := rand.read(result[10:])
|
bytes_generated := rand.read(result[10:])
|
||||||
assert(bytes_generated == 6, "RNG failed to generate 6 bytes for UUID v1.")
|
assert(bytes_generated == 6, "RNG failed to generate 6 bytes for UUID v1.")
|
||||||
}
|
}
|
||||||
@@ -128,6 +132,7 @@ Returns:
|
|||||||
- result: The generated UUID.
|
- result: The generated UUID.
|
||||||
*/
|
*/
|
||||||
generate_v7 :: proc() -> (result: Identifier) {
|
generate_v7 :: proc() -> (result: Identifier) {
|
||||||
|
assert(.Cryptographic in runtime.random_generator_query_info(context.random_generator), NO_CSPRNG_ERROR)
|
||||||
unix_time_in_milliseconds := time.to_unix_nanoseconds(time.now()) / 1e6
|
unix_time_in_milliseconds := time.to_unix_nanoseconds(time.now()) / 1e6
|
||||||
|
|
||||||
temporary := cast(u128be)unix_time_in_milliseconds << VERSION_7_TIME_SHIFT
|
temporary := cast(u128be)unix_time_in_milliseconds << VERSION_7_TIME_SHIFT
|
||||||
@@ -178,6 +183,7 @@ Returns:
|
|||||||
- result: The generated UUID.
|
- result: The generated UUID.
|
||||||
*/
|
*/
|
||||||
generate_v7_counter :: proc(counter: u16) -> (result: Identifier) {
|
generate_v7_counter :: proc(counter: u16) -> (result: Identifier) {
|
||||||
|
assert(.Cryptographic in runtime.random_generator_query_info(context.random_generator), NO_CSPRNG_ERROR)
|
||||||
assert(counter <= 0x0fff, "This implementation of the version 7 UUID does not support counters in excess of 12 bits (4,095).")
|
assert(counter <= 0x0fff, "This implementation of the version 7 UUID does not support counters in excess of 12 bits (4,095).")
|
||||||
unix_time_in_milliseconds := time.to_unix_nanoseconds(time.now()) / 1e6
|
unix_time_in_milliseconds := time.to_unix_nanoseconds(time.now()) / 1e6
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package test_core_uuid
|
package test_core_uuid
|
||||||
|
|
||||||
|
import "core:crypto"
|
||||||
import "core:encoding/uuid"
|
import "core:encoding/uuid"
|
||||||
import uuid_legacy "core:encoding/uuid/legacy"
|
import uuid_legacy "core:encoding/uuid/legacy"
|
||||||
import "core:log"
|
import "core:log"
|
||||||
@@ -8,6 +9,8 @@ import "core:time"
|
|||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_version_and_variant :: proc(t: ^testing.T) {
|
test_version_and_variant :: proc(t: ^testing.T) {
|
||||||
|
context.random_generator = crypto.random_generator()
|
||||||
|
|
||||||
v1 := uuid.generate_v1(0)
|
v1 := uuid.generate_v1(0)
|
||||||
v3 := uuid_legacy.generate_v3(uuid.Namespace_DNS, "")
|
v3 := uuid_legacy.generate_v3(uuid.Namespace_DNS, "")
|
||||||
v4 := uuid.generate_v4()
|
v4 := uuid.generate_v4()
|
||||||
@@ -62,6 +65,8 @@ test_legacy_namespaced_uuids :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_v1 :: proc(t: ^testing.T) {
|
test_v1 :: proc(t: ^testing.T) {
|
||||||
|
context.random_generator = crypto.random_generator()
|
||||||
|
|
||||||
CLOCK :: 0x3A1A
|
CLOCK :: 0x3A1A
|
||||||
v1_a := uuid.generate_v1(CLOCK)
|
v1_a := uuid.generate_v1(CLOCK)
|
||||||
time.sleep(10 * time.Millisecond)
|
time.sleep(10 * time.Millisecond)
|
||||||
@@ -90,6 +95,8 @@ test_v1 :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_v6 :: proc(t: ^testing.T) {
|
test_v6 :: proc(t: ^testing.T) {
|
||||||
|
context.random_generator = crypto.random_generator()
|
||||||
|
|
||||||
CLOCK :: 0x3A1A
|
CLOCK :: 0x3A1A
|
||||||
v6_a := uuid.generate_v6(CLOCK)
|
v6_a := uuid.generate_v6(CLOCK)
|
||||||
time.sleep(10 * time.Millisecond)
|
time.sleep(10 * time.Millisecond)
|
||||||
@@ -118,6 +125,8 @@ test_v6 :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_v7 :: proc(t: ^testing.T) {
|
test_v7 :: proc(t: ^testing.T) {
|
||||||
|
context.random_generator = crypto.random_generator()
|
||||||
|
|
||||||
v7_a := uuid.generate_v7()
|
v7_a := uuid.generate_v7()
|
||||||
time.sleep(10 * time.Millisecond)
|
time.sleep(10 * time.Millisecond)
|
||||||
v7_b := uuid.generate_v7()
|
v7_b := uuid.generate_v7()
|
||||||
|
|||||||
Reference in New Issue
Block a user