1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#![allow(non_snake_case)]

use atoi::atoi;
use rand::prelude::*;
use std::str;

pub static MAX_BLOCK_SIZE: u32 = 1024; //Please do not exceed this value, or the webserver will deny your request
pub static ENABLE_DEBUG: bool = false; //Enable temporarily if you're encountering problems with fetching the data
pub static MAX_RETRY_COUNT: u8 = 10; //In the case the https stream is interrupted (I've had this happen quite frequenctly), increase this value. 10 should be more than enough for a stable connection

fn get_raw_data(length: u32) -> String {
    let mut url: String =
        String::from("https://qrng.anu.edu.au/API/jsonI.php?length={}&type=uint8");
    url = url.replace("{}", length.to_string().as_str());

    if ENABLE_DEBUG {
        println!("Url: {}", url);
    }

    let data = reqwest::get(url.as_str());
    String::from(data.unwrap().text().unwrap().as_str())
}

fn substring(arr: String, start: &str, end: &str) -> String {
    let start_idx = arr.find(start).unwrap();
    let end_idx = arr.find(end).unwrap();
    let ret: String = arr
        .chars()
        .skip(start_idx + 1)
        .take(end_idx - start_idx - 1)
        .collect();
    ret
}

pub fn next_u8s(len: u32) -> Option<Vec<u8>> {
    if len <= 1024 {
        return get_bytes(len);
    }

    let mut r_bytes: Vec<u8> = Vec::new();
    let mut amt_left = len;
    while amt_left > MAX_BLOCK_SIZE {
        let next_vals: Vec<u8> = get_bytes(MAX_BLOCK_SIZE)?;
        for v in next_vals.iter() {
            r_bytes.push(*v);
        }
        amt_left -= MAX_BLOCK_SIZE;
    }
    let next_vals: Vec<u8> = get_bytes(amt_left)?;
    for v in next_vals.iter() {
        r_bytes.push(*v);
    }
    Some(r_bytes.to_owned())
}

pub fn next_u16s(len: u32) -> Option<Vec<u16>> {
    let mut rng = rand::thread_rng();
    let mut arr: Vec<u16> = Vec::new();
    let ref_arr: Vec<u8> = next_u8s(len * 2)?;

    let mut idx: usize = 0;
    while idx < ref_arr.len() {
        let y: u16 = rng.gen();
        let vector_combined = format!("{:02x}{:02x}", ref_arr[idx], ref_arr[idx + 1]);
        let v = u16::from_str_radix(&vector_combined, 16).unwrap();
        arr.push(y ^ v);
        idx += 2;
    }

    Some(arr.to_owned())
}

pub fn next_u32s(len: u32) -> Option<Vec<u32>> {
    let mut rng = rand::thread_rng();
    let mut arr: Vec<u32> = Vec::new();
    let ref_arr: Vec<u16> = next_u16s(len * 2)?;

    let mut idx: usize = 0;
    while idx < ref_arr.len() {
        let y: u32 = rng.gen();
        let vector_combined = format!("{:02x}{:02x}", ref_arr[idx], ref_arr[idx + 1]);
        let v = u32::from_str_radix(&vector_combined, 16).unwrap();
        arr.push(y ^ v);
        idx += 2;
    }

    Some(arr.to_owned())
}

pub fn next_u64s(len: u32) -> Option<Vec<u64>> {
    let mut rng = rand::thread_rng();
    let mut arr: Vec<u64> = Vec::new();
    let ref_arr: Vec<u32> = next_u32s(len * 2)?;

    let mut idx: usize = 0;
    while idx < ref_arr.len() {
        let y: u64 = rng.gen();
        let vector_combined = format!("{:02x}{:02x}", ref_arr[idx], ref_arr[idx + 1]);
        let v = u64::from_str_radix(&vector_combined, 16).unwrap();
        arr.push(y ^ v);
        idx += 2;
    }

    Some(arr.to_owned())
}

pub fn next_u128s(len: u32) -> Option<Vec<u128>> {
    let mut rng = rand::thread_rng();
    let mut arr: Vec<u128> = Vec::new();
    let ref_arr: Vec<u64> = next_u64s(len * 2)?;

    let mut idx: usize = 0;
    while idx < ref_arr.len() {
        let y: u128 = rng.gen();
        let vector_combined = format!("{:02x}{:02x}", ref_arr[idx], ref_arr[idx + 1]);
        let v = u128::from_str_radix(&vector_combined, 16).unwrap();
        arr.push(y ^ v);
        idx += 2;
    }
    Some(arr.to_owned())
}

fn get_bytes(len: u32) -> Option<Vec<u8>> {
    let mut rng = rand::thread_rng();
    let mut store: Vec<u8> = Vec::new();
    let mut raw_data = get_raw_data(len);
    let mut retries: u8 = 0;

    while !raw_data.contains("\"success\":true") {
        retries += 1;
        if retries >= MAX_RETRY_COUNT {
            return None;
        }
        raw_data = get_raw_data(len);
    }

    if ENABLE_DEBUG {
        println!("Success code received! {} ", raw_data);
    }

    raw_data = substring(raw_data, "[", "]");

    if ENABLE_DEBUG {
        println!("Substring: {}", raw_data);
    }

    let parts: Vec<&str> = raw_data.split(",").collect();
    if parts.len() != len as usize {
        eprintln!("Error: bytes expected not equal to the input length");
        return None;
    }
    for byte in parts.iter() {
        let y: u8 = rng.gen();
        store.push(atoi::<u8>(byte.as_bytes()).unwrap() ^ y);
    }

    Some(store.to_owned())
}