replace utils module with direct generate calls (#148)

The `utils` module uses a convoluted mechanism for filling byte arrays
with random data. The `generate` function can be used directly, making
the `utils` module obsolete.
This commit is contained in:
Etan Kissling 2023-07-24 22:38:21 +02:00 committed by GitHub
parent 2c3ae3137f
commit f8ed9b40a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 30 additions and 62 deletions

View File

@ -1,5 +1,5 @@
## nim-websock ## nim-websock
## Copyright (c) 2021 Status Research & Development GmbH ## Copyright (c) 2021-2023 Status Research & Development GmbH
## Licensed under either of ## Licensed under either of
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
## * MIT license ([LICENSE-MIT](LICENSE-MIT)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT))
@ -118,10 +118,11 @@ suite "Encode frame extensions flow":
frame.opcode == Opcode.Binary frame.opcode == Opcode.Binary
suite "Decode frame extensions flow": suite "Decode frame extensions flow":
let rng = HmacDrbgContext.new()
var var
address: TransportAddress address: TransportAddress
server: StreamServer server: StreamServer
maskKey = genMaskKey(HmacDrbgContext.new()) maskKey = MaskKey.random(rng[])
transport: StreamTransport transport: StreamTransport
reader: AsyncStreamReader reader: AsyncStreamReader
frame: Frame frame: Frame

View File

@ -1,5 +1,5 @@
## nim-websock ## nim-websock
## Copyright (c) 2021 Status Research & Development GmbH ## Copyright (c) 2021-2023 Status Research & Development GmbH
## Licensed under either of ## Licensed under either of
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
## * MIT license ([LICENSE-MIT](LICENSE-MIT)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT))
@ -88,7 +88,7 @@ proc connectClient*(
onPing: ControlCb = nil, onPing: ControlCb = nil,
onPong: ControlCb = nil, onPong: ControlCb = nil,
onClose: CloseCb = nil, onClose: CloseCb = nil,
rng: Rng = nil): Future[WSSession] {.async.} = rng = HmacDrbgContext.new()): Future[WSSession] {.async.} =
let secure = when defined secure: true else: false let secure = when defined secure: true else: false
return await WebSocket.connect( return await WebSocket.connect(
host = address, host = address,

View File

@ -1,5 +1,5 @@
## nim-websock ## nim-websock
## Copyright (c) 2021 Status Research & Development GmbH ## Copyright (c) 2021-2023 Status Research & Development GmbH
## Licensed under either of ## Licensed under either of
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
## * MIT license ([LICENSE-MIT](LICENSE-MIT)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT))
@ -12,7 +12,6 @@ import
pkg/chronos/unittest2/asynctests pkg/chronos/unittest2/asynctests
include ../websock/frame include ../websock/frame
include ../websock/utils
# TODO: Fix Test. # TODO: Fix Test.

View File

@ -1,5 +1,5 @@
## nim-websock ## nim-websock
## Copyright (c) 2021-2022 Status Research & Development GmbH ## Copyright (c) 2021-2023 Status Research & Development GmbH
## Licensed under either of ## Licensed under either of
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
## * MIT license ([LICENSE-MIT](LICENSE-MIT)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT))
@ -733,6 +733,7 @@ suite "Test Closing":
suite "Test Payload": suite "Test Payload":
setup: setup:
let rng = HmacDrbgContext.new()
var var
server: HttpServer server: HttpServer
@ -837,7 +838,7 @@ suite "Test Payload":
address = initTAddress("127.0.0.1:8888"), address = initTAddress("127.0.0.1:8888"),
frameSize = maxFrameSize) frameSize = maxFrameSize)
let maskKey = genMaskKey(HmacDrbgContext.new()) let maskKey = MaskKey.random(rng[])
await session.stream.writer.write( await session.stream.writer.write(
(await Frame( (await Frame(
fin: false, fin: false,
@ -897,7 +898,7 @@ suite "Test Payload":
pong = true pong = true
) )
let maskKey = genMaskKey(HmacDrbgContext.new()) let maskKey = MaskKey.random(rng[])
await session.stream.writer.write( await session.stream.writer.write(
(await Frame( (await Frame(
fin: false, fin: false,

View File

@ -1,5 +1,5 @@
## nim-websock ## nim-websock
## Copyright (c) 2021-2022 Status Research & Development GmbH ## Copyright (c) 2021-2023 Status Research & Development GmbH
## Licensed under either of ## Licensed under either of
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
## * MIT license ([LICENSE-MIT](LICENSE-MIT)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT))
@ -11,7 +11,7 @@
import std/strformat import std/strformat
import pkg/[chronos, chronicles, stew/byteutils, stew/endians2] import pkg/[chronos, chronicles, stew/byteutils, stew/endians2]
import ./types, ./frame, ./utils, ./utf8dfa, ./http import ./types, ./frame, ./utf8dfa, ./http
import pkg/chronos/streams/asyncstream import pkg/chronos/streams/asyncstream
@ -114,8 +114,9 @@ proc nonCancellableSend(
trace "Sending data to remote" trace "Sending data to remote"
let maskKey = if ws.masked: let maskKey =
genMaskKey(ws.rng) if ws.masked:
MaskKey.random(ws.rng[])
else: else:
default(MaskKey) default(MaskKey)

View File

@ -1,5 +1,5 @@
## nim-websock ## nim-websock
## Copyright (c) 2021-2022 Status Research & Development GmbH ## Copyright (c) 2021-2023 Status Research & Development GmbH
## Licensed under either of ## Licensed under either of
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
## * MIT license ([LICENSE-MIT](LICENSE-MIT)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT))
@ -13,11 +13,11 @@ import std/deques
import pkg/[chronos, import pkg/[chronos,
chronos/streams/tlsstream, chronos/streams/tlsstream,
chronos/apps/http/httptable, chronos/apps/http/httptable,
bearssl/rand,
httputils, httputils,
stew/results] stew/results]
import ./utils
export deques export deques, rand
const const
SHA1DigestSize* = 20 SHA1DigestSize* = 20
@ -55,6 +55,7 @@ type
HeaderFlags* = set[HeaderFlag] HeaderFlags* = set[HeaderFlag]
MaskKey* = array[4, char] MaskKey* = array[4, char]
WebSecKey* = array[16, byte]
Frame* = ref object Frame* = ref object
fin*: bool ## Indicates that this is the final fragment in a message. fin*: bool ## Indicates that this is the final fragment in a message.
@ -89,7 +90,7 @@ type
masked*: bool # send masked packets masked*: bool # send masked packets
binary*: bool # is payload binary? binary*: bool # is payload binary?
flags*: set[TLSFlags] flags*: set[TLSFlags]
rng*: Rng rng*: ref HmacDrbgContext
frameSize*: int # max frame buffer size frameSize*: int # max frame buffer size
onPing*: ControlCb onPing*: ControlCb
onPong*: ControlCb onPong*: ControlCb
@ -212,3 +213,6 @@ method encode*(self: Ext, frame: Frame): Future[Frame] {.base, async.} =
method toHttpOptions*(self: Ext): string {.base, gcsafe.} = method toHttpOptions*(self: Ext): string {.base, gcsafe.} =
raiseAssert "Not implemented!" raiseAssert "Not implemented!"
func random*(T: typedesc[MaskKey|WebSecKey], rng: var HmacDrbgContext): T =
rng.generate(result)

View File

@ -1,37 +0,0 @@
## nim-websock
## Copyright (c) 2021 Status Research & Development GmbH
## Licensed under either of
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
## at your option.
## This file may not be copied, modified, or distributed except according to
## those terms.
import bearssl/[rand]
export rand
## Random helpers: similar as in stdlib, but with HmacDrbgContext rng
const randMax = 18_446_744_073_709_551_615'u64
type Rng* = ref HmacDrbgContext
proc rand*(rng: Rng, max: Natural): int =
if max == 0: return 0
var x: uint64
while true:
let x = rng[].generate(uint64)
if x < randMax - (randMax mod (uint64(max) + 1'u64)): # against modulo bias
return int(x mod (uint64(max) + 1'u64))
proc genMaskKey*(rng: Rng): array[4, char] =
## Generates a random key of 4 random chars.
proc r(): char = char(rand(rng, 255))
return [r(), r(), r(), r()]
proc genWebSecKey*(rng: Rng): seq[byte] =
var key = newSeq[byte](16)
proc r(): byte = byte(rand(rng, 255))
## Generates a random key of 16 random chars.
for i in 0..15:
key[i] = r()
return key

View File

@ -26,9 +26,9 @@ import pkg/[chronos,
stew/base10, stew/base10,
nimcrypto/sha] nimcrypto/sha]
import ./utils, ./frame, ./session, /types, ./http, ./extensions/extutils import ./frame, ./session, /types, ./http, ./extensions/extutils
export utils, session, frame, types, http, httptable export session, frame, types, http, httptable
logScope: logScope:
topics = "websock ws-server" topics = "websock ws-server"
@ -117,11 +117,10 @@ proc connect*(
onPing: ControlCb = nil, onPing: ControlCb = nil,
onPong: ControlCb = nil, onPong: ControlCb = nil,
onClose: CloseCb = nil, onClose: CloseCb = nil,
rng: Rng = nil): Future[WSSession] {.async.} = rng = HmacDrbgContext.new()): Future[WSSession] {.async.} =
let let
rng = if isNil(rng): HmacDrbgContext.new() else: rng key = Base64Pad.encode(WebSecKey.random(rng[]))
key = Base64Pad.encode(genWebSecKey(rng))
hostname = if hostName.len > 0: hostName else: $host hostname = if hostName.len > 0: hostName else: $host
let client = if secure: let client = if secure:
@ -216,7 +215,7 @@ proc connect*(
onPing: ControlCb = nil, onPing: ControlCb = nil,
onPong: ControlCb = nil, onPong: ControlCb = nil,
onClose: CloseCb = nil, onClose: CloseCb = nil,
rng: Rng = nil): Future[WSSession] rng = HmacDrbgContext.new()): Future[WSSession]
{.raises: [Defect, WSWrongUriSchemeError].} = {.raises: [Defect, WSWrongUriSchemeError].} =
## Create a new websockets client ## Create a new websockets client
## using a Uri ## using a Uri
@ -359,12 +358,12 @@ proc new*(
onPing: ControlCb = nil, onPing: ControlCb = nil,
onPong: ControlCb = nil, onPong: ControlCb = nil,
onClose: CloseCb = nil, onClose: CloseCb = nil,
rng: Rng = nil): WSServer = rng = HmacDrbgContext.new()): WSServer =
return WSServer( return WSServer(
protocols: @protos, protocols: @protos,
masked: false, masked: false,
rng: if isNil(rng): HmacDrbgContext.new() else: rng, rng: rng,
frameSize: frameSize, frameSize: frameSize,
factories: @factories, factories: @factories,
onPing: onPing, onPing: onPing,