Last active
August 26, 2019 10:15
-
-
Save d4r1091/a0c9f841d2071d274155723e560aaae6 to your computer and use it in GitHub Desktop.
URandom OSX - Linux no dependencies
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Source: https://github.com/vapor-community/random | |
public protocol RandomProtocol { | |
/// Get a random array of Bytes | |
func bytes(count: Int) throws -> Bytes | |
} | |
// MARK: - Throwing getter methods | |
extension RandomProtocol { | |
/// Get a random Int8 | |
public func makeInt8() throws -> Int8 { | |
return Int8(bitPattern: try makeUInt8()) | |
} | |
/// Get a random UInt8 | |
public func makeUInt8() throws -> UInt8 { | |
return try bytes(count: 1)[0] | |
} | |
/// Get a random Int16 | |
public func makeInt16() throws -> Int16 { | |
return Int16(bitPattern: try makeUInt16()) | |
} | |
/// Get a random UInt16 | |
public func makeUInt16() throws -> UInt16 { | |
let random = try bytes(count: 2) | |
return UnsafeRawPointer(random) | |
.assumingMemoryBound(to: UInt16.self) | |
.pointee | |
} | |
/// Get a random Int32 | |
public func makeInt32() throws -> Int32 { | |
return Int32(bitPattern: try makeUInt32()) | |
} | |
/// Get a random UInt32 | |
public func makeUInt32() throws -> UInt32 { | |
let random = try bytes(count: 4) | |
return UnsafeRawPointer(random) | |
.assumingMemoryBound(to: UInt32.self) | |
.pointee | |
} | |
/// Get a random Int64 | |
public func makeInt64() throws -> Int64 { | |
return Int64(bitPattern: try makeUInt64()) | |
} | |
/// Get a random UInt64 | |
public func makeUInt64() throws -> UInt64 { | |
let random = try bytes(count: 8) | |
return UnsafeRawPointer(random) | |
.assumingMemoryBound(to: UInt64.self) | |
.pointee | |
} | |
/// Get a random Int | |
public func makeInt() throws -> Int { | |
return Int(bitPattern: try makeUInt()) | |
} | |
/// Get a random UInt | |
public func makeUInt() throws -> UInt { | |
let random = try bytes(count: MemoryLayout<UInt>.size) | |
return UnsafeRawPointer(random) | |
.assumingMemoryBound(to: UInt.self) | |
.pointee | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Adapted to work with both Linux and OSX | |
// Source: https://github.com/vapor-community/random | |
#if os(Linux) | |
import Glibc | |
#else | |
import Darwin | |
#endif | |
public typealias Bytes = [UInt8] | |
public typealias Byte = UInt8 | |
/// URandom represents a file connection to /dev/urandom on Unix systems. | |
/// /dev/urandom is a cryptographically secure random generator provided by the OS. | |
public final class URandom: RandomProtocol { | |
public enum Error: Swift.Error { | |
case open(Int32) | |
case read(Int32) | |
} | |
private let file: UnsafeMutablePointer<FILE> | |
/// Initialize URandom | |
public init(path: String) throws { | |
guard let file = fopen(path, "rb") else { | |
// The Random protocol doesn't allow init to fail, so we have to | |
// check whether /dev/urandom was successfully opened here | |
throw Error.open(errno) | |
} | |
self.file = file | |
} | |
deinit { | |
fclose(file) | |
} | |
private func read(numBytes: Int) throws -> [Int8] { | |
// Initialize an empty array with space for numBytes bytes | |
var bytes = [Int8](repeating: 0, count: numBytes) | |
guard fread(&bytes, 1, numBytes, file) == numBytes else { | |
// If the requested number of random bytes couldn't be read, | |
// we need to throw an error | |
throw Error.read(errno) | |
} | |
return bytes | |
} | |
/// Get a random array of Bytes | |
public func bytes(count: Int) throws -> Bytes { | |
return try read(numBytes: count).map({ Byte(bitPattern: $0) }) | |
} | |
} | |
extension URandom { | |
public convenience init() throws { | |
try self.init(path: "/dev/urandom") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment