Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge SecureRandom into Random and Random::Secure #4894

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions spec/std/crypto/bcrypt_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require "spec"
require "crypto/bcrypt"
require "random/secure"

describe "Crypto::Bcrypt" do
latin1_pound_sign = String.new(Bytes.new(1, 0xa3_u8))
Expand Down Expand Up @@ -28,16 +29,16 @@ describe "Crypto::Bcrypt" do

it "validates salt size" do
expect_raises(Crypto::Bcrypt::Error, /Invalid salt size/) do
Crypto::Bcrypt.new("abcd", SecureRandom.hex(7))
Crypto::Bcrypt.new("abcd", Random::Secure.hex(7))
end

expect_raises(Crypto::Bcrypt::Error, /Invalid salt size/) do
Crypto::Bcrypt.new("abcd", SecureRandom.hex(9))
Crypto::Bcrypt.new("abcd", Random::Secure.hex(9))
end
end

it "validates cost" do
salt = SecureRandom.hex(8)
salt = Random::Secure.hex(8)

expect_raises(Crypto::Bcrypt::Error, /Invalid cost/) do
Crypto::Bcrypt.new("abcd", salt, 3)
Expand All @@ -49,7 +50,7 @@ describe "Crypto::Bcrypt" do
end

it "validates password size" do
salt = SecureRandom.random_bytes(16)
salt = Random::Secure.random_bytes(16)

expect_raises(Crypto::Bcrypt::Error, /Invalid password size/) do
Crypto::Bcrypt.new("".to_slice, salt)
Expand Down
5 changes: 3 additions & 2 deletions spec/std/http/web_socket_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require "spec"
require "http/web_socket"
require "random/secure"

private def assert_text_packet(packet, size, final = false)
assert_packet packet, HTTP::WebSocket::Protocol::Opcode::TEXT, size, final: final
Expand Down Expand Up @@ -320,7 +321,7 @@ describe HTTP::WebSocket do

ws2 = HTTP::WebSocket.new("ws://127.0.0.1:#{listen_port}")

random = SecureRandom.hex
random = Random::Secure.hex
ws2.on_message do |str|
str.should eq("pong #{random}")
ws2.close
Expand Down Expand Up @@ -361,7 +362,7 @@ describe HTTP::WebSocket do
client_context = OpenSSL::SSL::Context::Client.insecure
ws2 = HTTP::WebSocket.new("127.0.0.1", port: listen_port, path: "/", tls: client_context)

random = SecureRandom.hex
random = Random::Secure.hex
ws2.on_message do |str|
str.should eq("pong #{random}")
ws2.close
Expand Down
20 changes: 20 additions & 0 deletions spec/std/random/secure_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require "spec"
require "random/secure"

describe "Random::Secure" do
it "returns random number from a secure system source" do
Random::Secure.next_u.should be_a(Int::Unsigned)

x = Random::Secure.rand(123456...654321)
x.should be >= 123456
x.should be < 654321

Random::Secure.rand(Int64::MAX / 2).should be <= (Int64::MAX / 2)
end

it "fully fills a large buffer" do
# mostly testing the linux getrandom calls
bytes = Random::Secure.random_bytes(10000)
bytes[9990, 10].should_not eq(Bytes.new(10))
end
end
14 changes: 0 additions & 14 deletions spec/std/random/system_spec.cr

This file was deleted.

79 changes: 79 additions & 0 deletions spec/std/random_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,83 @@ describe "Random" do
rng.rand(Int8::MIN..Int8::MAX).should eq expected
end
end

describe "random_bytes" do
it "generates random bytes" do
rng = TestRNG.new([0xfa19443eu32, 1u32, 0x12345678u32])
rng.random_bytes(9).should eq Bytes[0x3e, 0x44, 0x19, 0xfa, 1, 0, 0, 0, 0x78]
rng.random_bytes(1).should eq Bytes[0x3e]
rng.random_bytes(4).should eq Bytes[1, 0, 0, 0]
rng.random_bytes(3).should eq Bytes[0x78, 0x56, 0x34]
rng.random_bytes(0).should eq Bytes.new(0)

rng = TestRNG.new([12u8, 255u8, 11u8, 5u8, 122u8, 200u8, 192u8])
rng.random_bytes(7).should eq Bytes[12, 255, 11, 5, 122, 200, 192]
end

it "gets random bytes with default number of digits" do
bytes = TestRNG.new(RNG_DATA_32).random_bytes
bytes.size.should eq(16)
end

it "gets random bytes with requested number of digits" do
bytes = TestRNG.new(RNG_DATA_32).random_bytes(50)
bytes.size.should eq(50)
end

it "fills given buffer with random bytes" do
bytes = Bytes.new(2000)
TestRNG.new(RNG_DATA_32).random_bytes(bytes)
bytes.size.should eq 2000
bytes[1990, 10].should eq(UInt8.slice(0, 0, 1, 0, 0, 0, 234, 0, 0, 0))
end
end

describe "base64" do
it "gets base64 with default number of digits" do
base64 = TestRNG.new(RNG_DATA_32).base64
base64.should eq("y0jhAQAAAAABAAAA6gAAAA==")
end

it "gets base64 with requested number of digits" do
base64 = TestRNG.new(RNG_DATA_64).base64(50)
base64.should eq("n9hX9GKDEAL//////////wAAAAAAAAAA6I06MNtOcwAhuKXjOwIAADYvUY4HAAAAYto=")
end
end

describe "urlsafe_base64" do
it "gets urlsafe base64 with default number of digits" do
base64 = TestRNG.new(RNG_DATA_32).urlsafe_base64
base64.should eq("y0jhAQAAAAABAAAA6gAAAA")
end

it "gets urlsafe base64 with requested number of digits" do
base64 = TestRNG.new(RNG_DATA_64).urlsafe_base64(50)
base64.should eq("n9hX9GKDEAL__________wAAAAAAAAAA6I06MNtOcwAhuKXjOwIAADYvUY4HAAAAYto")
end

it "keeps padding" do
base64 = TestRNG.new(RNG_DATA_32).urlsafe_base64(padding: true)
base64.should eq("y0jhAQAAAAABAAAA6gAAAA==")
end
end

describe "hex" do
it "gets hex with default number of digits" do
hex = TestRNG.new(RNG_DATA_32).hex
hex.should eq("cb48e1010000000001000000ea000000")
end

it "gets hex with requested number of digits" do
hex = TestRNG.new(RNG_DATA_64).hex(50)
hex.should eq("9fd857f462831002ffffffffffffffff0000000000000000e88d3a30db4e730021b8a5e33b020000362f518e0700000062da")
end
end

describe "uuid" do
it "gets uuid" do
uuid = TestRNG.new(RNG_DATA_8).uuid
uuid.should eq("ea990000-7f80-4fff-aa99-00007f80ffff")
end
end
end
86 changes: 0 additions & 86 deletions spec/std/secure_random_spec.cr

This file was deleted.

4 changes: 2 additions & 2 deletions src/crypto/bcrypt.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require "secure_random"
require "random/secure"
require "./subtle"

# Pure Crystal implementation of the Bcrypt algorithm by Niels Provos and David
Expand Down Expand Up @@ -46,7 +46,7 @@ class Crypto::Bcrypt
def self.hash_secret(password, cost = DEFAULT_COST) : String
# We make a clone here to we don't keep a mutable reference to the original string
passwordb = password.to_unsafe.to_slice(password.bytesize + 1).clone # include leading 0
saltb = SecureRandom.random_bytes(SALT_SIZE)
saltb = Random::Secure.random_bytes(SALT_SIZE)
new(passwordb, saltb, cost).to_s
end

Expand Down
1 change: 0 additions & 1 deletion src/docs_main.cr
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ require "./option_parser"
require "./partial_comparable"
require "./random/**"
require "./readline"
require "./secure_random"
require "./signal"
require "./string_pool"
require "./string_scanner"
Expand Down
3 changes: 2 additions & 1 deletion src/http/multipart.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require "random/secure"
require "./multipart/*"

# The `HTTP::Multipart` module contains utilities for parsing MIME multipart
Expand Down Expand Up @@ -89,7 +90,7 @@ module HTTP::Multipart
# HTTP::Multipart.generate_boundary # => "---------------------------dQu6bXHYb4m5zrRC3xPTGwV"
# ```
def self.generate_boundary
"--------------------------#{SecureRandom.urlsafe_base64(18)}"
"--------------------------#{Random::Secure.urlsafe_base64(18)}"
end

class Error < Exception
Expand Down
2 changes: 0 additions & 2 deletions src/http/multipart/builder.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
require "secure_random"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, my bad.


module HTTP::Multipart
# Builds a multipart MIME message.
#
Expand Down
2 changes: 1 addition & 1 deletion src/oauth.cr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require "http/client"
require "http/params"
require "uri"
require "secure_random"
require "random/secure"
require "openssl/hmac"
require "base64"
require "./oauth/**"
2 changes: 1 addition & 1 deletion src/oauth/oauth.cr
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ module OAuth

private def self.oauth_header(client, request, token, token_secret, consumer_key, consumer_secret, extra_params)
ts = Time.now.epoch.to_s
nonce = SecureRandom.hex
nonce = Random::Secure.hex

signature = Signature.new consumer_key, consumer_secret, token, token_secret, extra_params
signature.authorization_header request, client.tls?, ts, nonce
Expand Down
4 changes: 2 additions & 2 deletions src/oauth2/access_token/mac.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require "secure_random"
require "random/secure"
require "openssl/hmac"
require "base64"
require "./access_token"
Expand All @@ -22,7 +22,7 @@ class OAuth2::AccessToken::Mac < OAuth2::AccessToken

def authenticate(request : HTTP::Request, tls)
ts = Time.now.epoch
nonce = "#{ts - @issued_at}:#{SecureRandom.hex}"
nonce = "#{ts - @issued_at}:#{Random::Secure.hex}"
method = request.method
uri = request.resource
host, port = host_and_port request, tls
Expand Down
5 changes: 3 additions & 2 deletions src/openssl/cipher.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require "random/secure"
require "openssl"

class OpenSSL::Cipher
Expand Down Expand Up @@ -37,12 +38,12 @@ class OpenSSL::Cipher
end

def random_key
key = SecureRandom.random_bytes key_len
key = Random::Secure.random_bytes key_len
self.key = key
end

def random_iv
iv = SecureRandom.random_bytes iv_len
iv = Random::Secure.random_bytes iv_len
self.iv = iv
end

Expand Down
Loading