1 // upwgen generates random internationalized passwords
2 // Copyright (C) 2019 Aaron Ball <nullspoon@oper.io>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <time.h>
19 #include <locale.h>
20
21
22 // intrcat:
23 // Integer range concatenate. Appends the specified integer range to an int
24 // array.
25 //
26 // @arr Array to cat range of ints to
27 // @rstart Range start integer
28 // @rend Range end integer
29 //
30 // @return Number of integers appended to array
31 int intrcat(unsigned int* arr, unsigned int rstart, unsigned int rend) {
32 int i = 0;
33 int total = rend - rstart; // Calculate our return count
34
35 while(arr[i] != '\0')
36 i++;
37
38 while(rstart <= rend) {
39 arr[i] = rstart;
40 //printf("% -4d % -7d %lc\n", i, rstart, rstart);
41 rstart++;
42 i++;
43 }
44
45 arr[i] = '\0';
46 return total;
47 }
48
49
50 // populate_intl_arr:
51 // Populates an unsigned integer array with common unicode (utf-8) language
52 // alphabets and symbols.
53 //
54 // Some example unicode integer ranges:
55 // 33 - 126 Standard english ascii
56 // 256 - 383 Latin extended A block
57 // 256 - 383 Latin extended B block
58 // 913 - 969 Greek
59 // 1040 - 1103 Russian
60 // 1329 - 1414 Armenian
61 // 1488 - 1514 Hebrew
62 // 65166 - 65265 Arabic
63 //
64 // No/rare font support (boo!)
65 // 2325 - 2373 Devanagari (Hindi)
66 // 2437 - 2509 Bengali alphabet
67 // 2949 - 3020 Tamil
68 // 3585 - 3663 Thai
69 // 5792 - 5880 Runic
70 // 11392 - 11483 Coptic alphabet
71 // 66560 - 66639 Deseret
72 //
73 // @out Unsigned int array to be populated.
74 //
75 // @return Size of the array contents
76 int populate_intl_arr(unsigned int* out) {
77 out[0] = '\0';
78 int count = 0;
79
80 // Populate the array
81 count += intrcat(out, 33, 126); // English
82 count += intrcat(out, 256, 383); // Latin A block
83 count += intrcat(out, 399, 691); // Latin B block
84 count += intrcat(out, 913, 969); // Greek
85 count += intrcat(out, 1040, 1103); // Russian
86 count += intrcat(out, 1329, 1414); // Armenian
87 count += intrcat(out, 1488, 1514); // Hebrew
88 count += intrcat(out, 65166, 65265); // Arabic
89
90 return count;
91 }
92
93
94 // print_intl_arr:
95 // Prints array containing unsigned ints representing internal characters.
96 // Outputs to STDOUT the unicode decimal, followed by the unicode character.
97 //
98 // @arr Unicode array to print
99 void print_intl_arr(unsigned int* arr) {
100 int i = 0; // cursor
101
102 while(arr[i] != '\0') {
103 printf("%5d: [%lc]\n", arr[i], arr[i]);
104 i++;
105 }
106 }
107
108
109 int main(int argc, char* argv[]) {
110 char* passlen; // Argv 1, user specified length of the password
111 int count; // Number of international chars to choose from
112 struct timespec ts; // Timespec for seeding rng
113 int len; // Password length
114 unsigned long seed; // Seed for the RNG (current seconds * nanoseconds)
115 unsigned int chars[1024]; // Uint array to hold international chars
116
117 setlocale(LC_ALL, "en_US.UTF-8");
118
119 if(argc == 1) {
120 printf("Password length required\n");
121 return 1;
122 }
123
124 passlen = argv[1];
125
126 // Store supported chars here!
127 count = populate_intl_arr(chars);
128 //printf("%d international chars for use\n", count);
129 //print_intl_arr(chars);
130 //return 0;
131
132 clock_gettime(CLOCK_REALTIME, &ts);
133 seed = ts.tv_sec + ts.tv_nsec;
134 srand((unsigned)seed);
135
136 len = atoi(passlen);
137 while(len > 0) {
138 int r = rand() % count;
139 printf("%lc", chars[r]);
140 len--;
141 }
142 printf("\n");
143
144 return 0;
145 }
|