Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 2eca01b92d84
Choose a base ref
...
head repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 78b43559165f
Choose a head ref
  • 3 commits
  • 19 files changed
  • 2 contributors

Commits on Sep 25, 2017

  1. Merge SecureRandom into Random and Random::Secure

    SecureRandom has been dropped in favor to Random::Secure (renamed
    from Random::System) which is now the secure source for random
    numbers suitable for cryptography.
    
    Moves SecureRandom#random_bytes(Bytes) into Random::Secure, and
    implements a generic Random#random_bytes(Bytes) to fill a Bytes with
    random numbers from any PRNG.
    
    Moves SecureRandom methods such as #base64 and #uuid into Random, so
    any PRNG implementation may use these methods; they should only be
    used with a secure PRNG thought (except maybe in test suites). This
    change allows to swap PRNG at will. For example swap Random::Secure
    for Random::ISAAC (seeded from Random::Secure), or use a
    cryptographically secure but slow PRNG in production, and an
    insecure but fast and determinable PRNG in test suites, for example.
    ysbaddaden committed Sep 25, 2017
    Copy the full SHA
    27684db View commit details
  2. Copy the full SHA
    79d0358 View commit details

Commits on Sep 26, 2017

  1. Merge pull request #4894 from ysbaddaden/std-merge-secure-random-into…

    …-random
    
    Merge SecureRandom into Random and Random::Secure
    
    - Renames Random::System to Random::Secure.
    - Removes SecureRandom.
    - Moves #uuid, #hex and #base64 methods to Random.
    - Moves SecureRandom#random_bytes(slice) to Random::Secure.
    - Implements generic Random#random_bytes(slice).
    ysbaddaden authored Sep 26, 2017
    Copy the full SHA
    78b4355 View commit details
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))
@@ -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)
@@ -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)
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
@@ -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
@@ -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
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
@@ -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
@@ -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

1 change: 0 additions & 1 deletion src/docs_main.cr
Original file line number Diff line number Diff line change
@@ -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"
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
@@ -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
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"

module HTTP::Multipart
# Builds a multipart MIME message.
#
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
@@ -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
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"
@@ -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
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
@@ -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

Loading