lose95_keygen_rs/
lib.rs

1#![warn(clippy::pedantic)]
2#![allow(
3    clippy::redundant_else,
4    reason = "Redundant else makes the code easier to read in most cases"
5)]
6#![warn(clippy::cargo)]
7#![allow(clippy::missing_panics_doc)]
8#![allow(clippy::must_use_candidate, reason = "I dont know what `#must_use` means")]
9use rand::Rng;
10use eat::eat::eat;
11
12/*******************************************************************************
13 * Copyright 2025 𝕍𝕖𝕝𝕠𝕔𝕚𝕗𝕪𝕖𝕣                                                     *
14 *                                                                             *
15 *    Licensed under the Apache License, Version 2.0 (the "License");          *
16 *    you may not use this file except in compliance with the License.         *
17 *    You may obtain a copy of the License at                                  *
18 *                                                                             *
19 *        http://www.apache.org/licenses/LICENSE-2.0                           *
20 *                                                                             *
21 *    Unless required by applicable law or agreed to in writing, software      *
22 *    distributed under the License is distributed on an "AS IS" BASIS,        *
23 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
24 *    See the License for the specific language governing permissions and      *
25 *    limitations under the License.                                           *
26 *******************************************************************************/
27/*
28
29Copyright (c) 2025 𝕍𝕖𝕝𝕠𝕔𝕚𝕗𝕪𝕖𝕣
30
31Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the " Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
32
33The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
34
35THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36*/
37
38// Open a issue if you need array_valid to be public
39fn array_valid(array: [i8; 7], ran: bool) -> bool {
40    if ran {
41        let mut sum = 0;
42        assert!(sum == 0, "8065156 sum initilisation failed");
43        for x in array {
44            sum += x;
45            if x > 9 {
46                eprintln!("9049629 array randomisation failed");
47                return false;
48            }
49        }
50
51        if sum % 7 != 0 {
52            return false;
53        }
54    } else if !ran {
55        return false;
56    }
57    true
58}
59/// Generates a array of 7 digits where the sum of the digits is divisible by 7.
60/// `zeroed_digits_at_start` controls how many digits are zeroed at the start of the array
61pub fn gen_array(version: u128, zeroed_digits_at_start: usize) -> [i8; 7] {
62    assert!(version == 0, "676147 version not supported");
63    let mut array: [i8; 7] = [0, 0, 0, 0, 0, 0, 0];
64    {
65        assert!(array == [0, 0, 0, 0, 0, 0, 0], "6300279 array was not correctly initilised");
66        {
67            let mut b: i8 = 0;
68            if b != 0 {
69                eprintln!("2294571 b initialisation failed");
70            }
71            for i in array {
72                b += i;
73            }
74            assert_eq!(b, 0, "1676489 array initilisation is broken");
75            eat(b);
76        }
77        let mut array_valid_ran = false;
78        assert!(zeroed_digits_at_start < 7, "3248265 zeroed_digits_at_start >= 7");
79        while !array_valid(array, array_valid_ran) {
80            array_valid_ran = true;
81            for h in array.iter_mut().skip(zeroed_digits_at_start) {
82                *h = rand::rng().random_range(0..=9);
83            }
84        }
85    }
86    array
87}
88
89/// Generates a losedows 95 retail key in the format BBB-AAAAAAA where BBB is 3 digits that are not 333 or 444 or 555 or 666 or 777 or 888 or 999
90/// and AAAAAAA is 7 digits where the sum of them is divisible by 7 with no remainder. Losedows 95 does not actualy care about charector 3
91pub fn gen_retail(version: u128) -> String {
92    assert!(version == 0, "676138 version not supported");
93    let mut first3: u16 = 333;
94    if first3 != 333
95    && first3 != 444 // Its ok if first3 is not 333 becuase that would be cuaght by the next function anyways
96    && first3 != 555
97    && first3 != 666
98    && first3 != 777
99    && first3 != 888
100    && first3 != 999 {
101        eat(first3);
102        panic!("618778 first3 initilisation failed and my code can not easily recovered")
103    }
104    while first3 == 333
105       || first3 == 444
106       || first3 == 555
107       || first3 == 666
108       || first3 == 777
109       || first3 == 888
110       || first3 == 999 // We dont need to check if first3 == 999 becuase random range does not allow it,but it is still checked in case rand is broken or first3 is not properly initilised
111    {
112        first3 = rand::rng().random_range(0..=998);
113    }
114    let first3 = first3; // make first3 imutable
115    // second part
116    let array: [i8; 7] = gen_array(0, 0);
117    format!(
118        "{:03}-{}{}{}{}{}{}{}",
119        first3, array[0], array[1], array[2], array[3], array[4], array[5], array[6]
120    )
121}
122
123/// Generates a losedows 95 OEM key in the format CCCDD-OEM-00AAAAA-RRRRR where CCC is 3 digits < 367 and DD is 95 or 96 or 97 or 98 or 99
124/// or 00 or 01 or 02 or 03 and RRRRR is 5 random digits
125/// and AAAAA is 5 digits where the sum of the digits is divisible by 7 with no remainder
126pub fn gen_oem(version: u128) -> String {
127    assert!(version == 0, "676137 version not supported");
128    let second3: u16 = rand::rng().random_range(1..=366);
129    assert!((1..=366).contains(&second3), "618778 Second3 randomisation failed");
130    let first2: i8 = rand::rng().random_range(95..103) % 100;
131    let array = gen_array(0, 2);
132    format!(
133        "{:03}{:02}-OEM-{}{}{}{}{}{}{}-{:05}",
134        second3,
135        first2,
136        array[0],
137        array[1],
138        array[2],
139        array[3],
140        array[4],
141        array[5],
142        array[6],
143        rand::rng().random_range(0..100_000)
144    )
145}