├── README.md └── krypta_luajit.lua /README.md: -------------------------------------------------------------------------------- 1 | # Krypta 2 | 3 | Generating random bits, passwords, recovery phrases and Bitcoin private keys / addresses (including QR codes) from text seed and salt. Deliberately implemented in single file pure LuaJIT (including crypto routines and hashing functions) without any external dependencies. This is useful for generating passwords / private keys etc for the most important stuff you have. This software is ugly, not user friendly and not meant for computer illiterate. If you don't understand what is written in this document, then Krypta is very probably not for you and using it might be dangerous. 4 | 5 | Run it without arguments to see the basic explanation of options. 6 | 7 | Krypta is a less traditional way to keep your important passwords / codes / wordlists safe. Extremely important things. Like the private keys from your 100 BTC Bitcoin address. Instead of keeping this info in the physical safe or hardware device (e.g. Trezor), you have to remember one long super-secret passphrase and all your other secret info is derived from this passphrase using this script and your notes which you don't have to keep especially secret. 8 | 9 | You might think this sounds dangerously similar to the infamous "memory wallets" but bear with me. 10 | 11 | When you start Krypta, you enter your secret passphrase which you have to remember exactly and never forget. This passphrase should have sufficient entropy to generate 256 bits checksum and not be something that can be found using brute force or dictionary attacks. Note that this definition if rather vague and it's not easy to evaluate the suitability of any given passphrase. But it's very very important to choose something that cannot be easily guessed / cracked (and, again, "easily" is very vague term here). One acceptable way MIGHT BE for example to take first 50 characters from the middle of your favorite song, for example "NoStopSignsSpeedLimitNobodysGonnaSlowMeDownLikeAWh" (from "Highway to Hell"). In this specific example, note that 50 ASCII characters are still not enough for full 256 bits of entropy and that you have to be sure to remember whether you used "NobodysGonna...", "NobodySGonna..." or "NobodyIsGonna...". This is not an easy decision and it cannot be underestimated! 12 | 13 | The security of your passphrase is further increased by optional Salt, which is another piece of information that pertains SPECIFICALLY TO YOU, e.g. your e-mail or your phone number or some important date. This information is not secure by itself (at all) but when Krypta combines it with your passphrase, it increases its security significantly (evil people can no longer perform large-scale dictionary and brute-force attacks hoping that they will discover some random person's BTC private key). 14 | 15 | The Passphrase and Salt are then used to generate your 256-bit Master key using a hash function. First, SHA256 hash is calculated from Passphrase and Salt and the resulting 256 bits (still not the Master key) are used as a seed for a special generator function that calculates the Master key. This function is specifically designed to take a long time to run. You can select the difficulty of this generator function from 1 to 31, where 1 takes a fraction of second on average computer and each subsequent difficulty takes approximately twice as long (the max difficulty takes many years on current PC). You should select as high difficulty as possible for your computer because it makes any bruteforcing / dictionary attacks much, much harder if the attacker can only try 1 combination in 5 seconds instead in 1 million combinations in 1 second. 16 | 17 | The Master key is generated by running a 32 bit [XorShift pseudorandom number generator](https://en.wikipedia.org/wiki/Xorshift) with 128 state bits, clocked by 4 sequentially linked 32bit [linear feedback shift registers](https://en.wikipedia.org/wiki/Linear-feedback_shift_register) which cause "skipping" of approximately every 16th PRNG value, making the generator less susceptible to predictive analysis and parallel (multi-CPU) algorithms. Both PRNG and LFSR registers are seeded with the original SHA256 hash (128 bits for PRNG, 4 x 32 bits for LFSRs) and then 32 bit numbers are generated (lots and lots of them) until some specific math conditions are met (many, many times in sequence, depending on the selected Difficulty). The Master key is then taken from 256 PRNG values that immediately follow (one bit from each). Because the PRNG has a period of 2^128 - 1 and each of the 4 LFSRs has a period of 2^32 - 1, the generator's period is exactly (2^32 − 1)^4 × (2^128 − 1), which is *a litlle bit* under 2^256. 18 | 19 | So, the resulting 256 bit Master key is uniquely defined by your Passphrase, your Salt and your Difficulty. Krypta will never actually show you your Master key (although you can see its 12-bit checksum) but it's used to calculate all other keys / passwords that you need. After Krypta takes a bit of time to calculate your Master key (which SHOULD take a while, using high Difficulty), you can then (almost instantly) derive any quantity of secret data from the combination of this Master key and any textual Index (explained below). 20 | 21 | For any Index that you enter, Krypta will immediately show you things like password, Bitcoin private key, BIP39 word sequence and other security data you might need to generate. These are different for each Index and cannot be traced back to your Master key, Index or Passphrase. Some examples of Indexes: "BTCColdStorage", "Facebook", "Mycelium" etc... 22 | 23 | For each Index, you get full set of security data, e.g. long password, short password, uncompressed BTC private key, compressed private key, long hex number, BIP39 word sequence, etc... To prevent clutter, you can add a Prefix to your Index (all Prefixes are displayed after you enter any non-prefixed Index). For example entering the Index "btcu:ColdStorage" is the same thing as entering just "ColdStorage" and then looking for the line that has prefix "btcu:" (uncompressed BTC key). Because Bitcoin QR codes take lots of screen space, they are displayed only when you enter specific prefix ("btcu:" or "btcc:"). 24 | 25 | In addition, all Master key / Index combinations generate two "Check words", and all Master key / Prefix / Index combinations generate three "Check words". You can use these as a checksum of sorts. 26 | 27 | Note that different Prefixes for the same Index are intentionally closely related to each other! E.g. whoever has the pwd40 password for index XYZ can easily deduce the pwd15 password or the BIP39 wordlist for the same Index. You are not supposed to use two prefixes of the same Index for two different purposes! 28 | 29 | At this time, you might be overwhelmed by all this information and you might think that you can never remember all of this. But you don't have to! 30 | 31 | The only thing you absolutely, positively have to remember, is your Passphrase. Everything else, i.e. Salt, Difficulty, Master key checksum, Indexes, Prefixes, Check words, can be stored in a text file which you don't have to be extremely paranoid about (of course it IS better if no one else sees it). 32 | 33 | So, for example, you can have the following in your "not so secret" file (note that this is just a normal text file in any format, meant to be read by human, not by Krypta or any other software): 34 | 35 | ``` 36 | passphrase hint: 50 letters from second verse of THAT song, in CamelCase. 37 | difficulty: 8 38 | salt: satan@hell.org 39 | checksum: 0x89A 40 | Main BTC Cold storage: btcc:BTCcold, checkwords "leader author tunnel" 41 | Facebook password: pwd40:Facebook, checkwords "penalty party ritual" 42 | Mycelium wordlist: wrd24:Mycelium, checkwords "enlist enjoy midnight" 43 | ``` 44 | 45 | IMPORTANT: Do you see something wrong with this? The Passphrase hint in this specific example is UNSAFE and makes you much easier target for someone who sees this hint! Someone can quite easily write a script that downloads song lyrics from some online database, converts the second verse to CamelCase, feeds it to Krypta and repeats this for all existing songs until he finds a Master key with checksum 0x89A, at which point you are completely screwed and all your passwords are compromised. It's all about balance of security and ease of remembering. Do your homework. 46 | 47 | You can keep copies of this file in Dropbox, Google Drive, Google Keep and/or your desk drawer. Don't forget to update all copies when you update the file (e.g. add new Indexes). The Check words written down like this are a good way to immediately see if you entered something wrong somewhere. Check words, Prefixes and Indexes are totally safe to be made public and cannot be traced back to your Master key. 48 | 49 | You can also use some of this data as a command line options to Krypta (and call it from your Bash script) or enter them directly into Krypta source code (have a look at the first few lines of code). Of course having your Difficulty or Salt in a Bash script alongside Krypta decreases your security a little bit more. 50 | 51 | ## Practical security considerations: 52 | 53 | * If you forget/lose your Passphrase, Salt, Difficulty **or** relevant Index(es), you are doomed and cannot recover your secure data. 54 | * If someone guesses and/or steals your Passphrase, Salt, Difficulty **and** Index(es), you are doomed because he can see your secure data. 55 | * If you have keylogger in the PC you use to run Krypta, you are very probably doomed. 56 | * If you have a virus that can see what happens in your PCs memory, you are very probably doomed. 57 | * Your strings (e.g. Passphrase, Indexes) are not sanitized / converted in any way. They are just binary data for Krypta. If you use non-ASCII characters in them (e.g. diacritics), be very sure that you know their encoding and are able to re-create it e.g. in 5 years, when accessing your secret data. 58 | 59 | It's best to run Krypta on a special computer (e.g. old laptop, Raspberry Pi...) with minimal Linux installation and no Internet connection. That's why Krypta runs in text mode, requires only minimal LuaJIT (no dependency on any libraries / apps) and is self-contained in a single script file. After using Krypta, you should immediately shut down / reboot that computer. 60 | -------------------------------------------------------------------------------- /krypta_luajit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env luajit 2 | -- Krypta by fuka@fuxoft.cz 3 | -- https://github.com/fuxoft/krypta 4 | -- If you don't know exactly what all of this does, please don't use it, you could lose money. 5 | _G.VERSION = string.match([[*<= Version '20190113a' =>*]], "'(.*)'") 6 | 7 | --[[ 8 | Set the SALT to something you can easily remember. 9 | For example your e-mail, your phone number or your full date of birth. 10 | It can be fairly obvious info, known to people around you 11 | but it should be fairly unique 12 | so it SHOULD NOT be the name of your pet or your favorite food or color. 13 | ]] 14 | local SALT = "" --Put the SALT between the quotes. 15 | local DIFFICULTY = 0 --Put desired difficulty here 16 | local CHECKSUM = nil --Put three digit hex checksum here - for example 0x123 17 | 18 | local bxor, band, bor, ror, rol, tohex, tobit, bnot, rshift, lshift = bit.bxor, bit.band, bit.bor, bit.ror, bit.rol, bit.tohex, bit.tobit, bit.bnot, bit.rshift, bit.lshift 19 | 20 | local MAXDIFC = 31 21 | 22 | local function hex256(dwords, separator) 23 | assert(#dwords == 8) 24 | separator = separator or "" 25 | assert(type(separator)=="string") 26 | local res = {} 27 | for i = 1, 8 do 28 | res[i] = tohex(dwords[i]) 29 | end 30 | return table.concat(res,separator) 31 | end 32 | 33 | --RSA256 implementation from https://github.com/JustAPerson/LuaCrypt/ 34 | --- Round constants 35 | -- computed as the fractional parts of the cuberoots of the first 64 primes 36 | local k256 = { 37 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 38 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 39 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 40 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 41 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 42 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 43 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 44 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 45 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 46 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 47 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 48 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 49 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 50 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 51 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 52 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, 53 | } 54 | 55 | --- Preprocess input message 56 | local function preprocess256(input) 57 | local length = #input; -- length in bits 58 | local padding = (-length-9) % 64 59 | input = input .. "\128" .. ("\0"):rep(padding) .. "\0\0\0\0"; 60 | local l = length * 8 61 | for i = 1, 4 do 62 | l = rol(l, 8) 63 | input = input .. string.char(band(l,0xff)) 64 | end 65 | return input 66 | end 67 | 68 | --- Process an individual block using SHA256 69 | -- Note: Lua arrays start at 1, not 0. 70 | -- This behavior is respected in loop counters. 71 | -- 72 | --@param `input` is the original input message 73 | --@param `t` is the position of the first byte of this block 74 | --@param `H` is the internal hash state 75 | local function digest_block256(input, t, H) 76 | local s10 -- Using 1 var for s0,s1 to help LuaJIT register alloc 77 | local t1, t2 78 | local chmaj -- May be used in place of s0 79 | local word 80 | local a, b, c, d, e, f, g, h 81 | local k = k256 82 | 83 | local W = {} 84 | local chunk 85 | local c1 = 0 -- #W, #words 86 | chunk = input:sub(t, t + 63) 87 | c1 = 0 88 | for i = 1, 64, 4 do 89 | c1 = c1 + 1; 90 | local num = 0 91 | for j = 0, 3 do 92 | num = rol(num, 8) 93 | num = bor(num, string.byte(chunk:sub(i+j, i+j))) 94 | end 95 | W[c1] = num 96 | end 97 | 98 | -- Extend 16 words into 64 99 | for t = 17, 64 do 100 | word = W[t - 2] 101 | s10 = bxor(ror(word, 17), ror(word, 19), rshift(word, 10)) 102 | word = W[t - 15] 103 | chmaj = bxor(ror(word, 7), ror(word, 18), rshift(word, 3)) 104 | W[t] = s10 + W[t - 7] + chmaj + W[t - 16] 105 | end 106 | 107 | a, b, c, d = H[1], H[2], H[3], H[4]; 108 | e, f, g, h = H[5], H[6], H[7], H[8]; 109 | 110 | for t = 1, 64 do 111 | s10 = bxor(ror(e, 6), ror(e, 11), ror(e, 25)); 112 | chmaj = bxor(band(e, f), band(bnot(e), g)); 113 | t1 = h + s10 + chmaj + k[t] + W[t]; 114 | s10 = bxor(ror(a, 2), ror(a, 13), ror(a, 22)); 115 | chmaj = bxor(band(a, b), band(a, c), band(b, c)); 116 | t2 = s10 + chmaj; 117 | h = g; 118 | g = f; 119 | f = e; 120 | e = d + t1; 121 | d = c; 122 | c = b; 123 | b = a; 124 | a = t1 + t2; 125 | end 126 | 127 | H[1] = (a + H[1]) 128 | H[2] = (b + H[2]) 129 | H[3] = (c + H[3]) 130 | H[4] = (d + H[4]) 131 | H[5] = (e + H[5]) 132 | H[6] = (f + H[6]) 133 | H[7] = (g + H[7]) 134 | H[8] = (h + H[8]) 135 | for i = 1, 8 do 136 | H[i] = band(H[i],0xffffffff) 137 | end 138 | 139 | end 140 | 141 | --- Calculate the SHA256 digest of a message 142 | -- Note: sha256() does not use variable names complaint with FIPS 180-2 143 | --@param `input` the message 144 | local function sha256(input, format) 145 | input = preprocess256(input); 146 | local state = { 147 | 0x6a09e667, 148 | 0xbb67ae85, 149 | 0x3c6ef372, 150 | 0xa54ff53a, 151 | 0x510e527f, 152 | 0x9b05688c, 153 | 0x1f83d9ab, 154 | 0x5be0cd19, 155 | } 156 | 157 | for i = 1, #input, 64 do 158 | digest_block256(input, i, state); 159 | end 160 | 161 | if format == "dwords" then 162 | return state 163 | end 164 | 165 | return hex256(state) 166 | end 167 | ----- END SHA256 168 | 169 | 170 | local function load_qr() 171 | local _M = {} 172 | --- The qrcode library is licensed under the 3-clause BSD license (aka "new BSD") 173 | --- To get in contact with the author, mail to . 174 | --- 175 | --- Please report bugs on the [github project page](http://speedata.github.com/luaqrcode/). 176 | -- Copyright (c) 2012, Patrick Gundlach 177 | -- All rights reserved. 178 | -- 179 | -- Redistribution and use in source and binary forms, with or without 180 | -- modification, are permitted provided that the following conditions are met: 181 | -- * Redistributions of source code must retain the above copyright 182 | -- notice, this list of conditions and the following disclaimer. 183 | -- * Redistributions in binary form must reproduce the above copyright 184 | -- notice, this list of conditions and the following disclaimer in the 185 | -- documentation and/or other materials provided with the distribution. 186 | -- * Neither the name of the nor the 187 | -- names of its contributors may be used to endorse or promote products 188 | -- derived from this software without specific prior written permission. 189 | -- 190 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 191 | -- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 192 | -- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 193 | -- DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 194 | -- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 195 | -- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 196 | -- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 197 | -- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 198 | -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 199 | -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 200 | 201 | 202 | --- Overall workflow 203 | --- ================ 204 | --- The steps to generate the qrcode, assuming we already have the codeword: 205 | --- 206 | --- 1. Determine version, ec level and mode (=encoding) for codeword 207 | --- 1. Encode data 208 | --- 1. Arrange data and calculate error correction code 209 | --- 1. Generate 8 matrices with different masks and calculate the penalty 210 | --- 1. Return qrcode with least penalty 211 | --- 212 | --- Each step is of course more or less complex and needs further description 213 | 214 | --- Helper functions 215 | --- ================ 216 | --- 217 | --- We start with some helper functions 218 | 219 | -- Return a number that is the result of interpreting the table tbl (msb first) 220 | local function tbl_to_number(tbl) 221 | local n = #tbl 222 | local rslt = 0 223 | local power = 1 224 | for i = 1, n do 225 | rslt = rslt + tbl[i]*power 226 | power = power*2 227 | end 228 | return rslt 229 | end 230 | 231 | -- Calculate bitwise xor of bytes m and n. 0 <= m,n <= 256. 232 | local function bit_xor(m, n) 233 | return bit.band(0xff, bit.bxor(m, n)) 234 | end 235 | 236 | -- Return the binary representation of the number x with the width of `digits`. 237 | local function binary(x,digits) 238 | local s=string.format("%o",x) 239 | local a={["0"]="000",["1"]="001", ["2"]="010",["3"]="011", 240 | ["4"]="100",["5"]="101", ["6"]="110",["7"]="111"} 241 | s=string.gsub(s,"(.)",function (d) return a[d] end) 242 | -- remove leading 0s 243 | s = string.gsub(s,"^0*(.*)$","%1") 244 | local fmtstring = string.format("%%%ds",digits) 245 | local ret = string.format(fmtstring,s) 246 | return string.gsub(ret," ","0") 247 | end 248 | 249 | -- A small helper function for add_typeinfo_to_matrix() and add_version_information() 250 | -- Add a 2 (black by default) / -2 (blank by default) to the matrix at position x,y 251 | -- depending on the bitstring (size 1!) where "0"=blank and "1"=black. 252 | local function fill_matrix_position(matrix,bitstring,x,y) 253 | if bitstring == "1" then 254 | matrix[x][y] = 2 255 | else 256 | matrix[x][y] = -2 257 | end 258 | end 259 | 260 | 261 | --- Step 1: Determine version, ec level and mode for codeword 262 | --- ======================================================== 263 | --- 264 | --- First we need to find out the version (= size) of the QR code. This depends on 265 | --- the input data (the mode to be used), the requested error correction level 266 | --- (normally we use the maximum level that fits into the minimal size). 267 | 268 | -- Return the mode for the given string `str`. 269 | -- See table 2 of the spec. We only support mode 1, 2 and 4. 270 | -- That is: numeric, alaphnumeric and binary. 271 | local function get_mode( str ) 272 | local mode 273 | if string.match(str,"^[0-9]+$") then 274 | return 1 275 | elseif string.match(str,"^[0-9A-Z $%%*./:+-]+$") then 276 | return 2 277 | else 278 | return 4 279 | end 280 | assert(false,"never reached") 281 | return nil 282 | end 283 | 284 | 285 | 286 | --- Capacity of QR codes 287 | --- -------------------- 288 | --- The capacity is calculated as follow: \\(\text{Number of data bits} = \text{number of codewords} * 8\\). 289 | --- The number of data bits is now reduced by 4 (the mode indicator) and the length string, 290 | --- that varies between 8 and 16, depending on the version and the mode (see method `get_length()`). The 291 | --- remaining capacity is multiplied by the amount of data per bit string (numeric: 3, alphanumeric: 2, other: 1) 292 | --- and divided by the length of the bit string (numeric: 10, alphanumeric: 11, binary: 8, kanji: 13). 293 | --- Then the floor function is applied to the result: 294 | --- $$\Big\lfloor \frac{( \text{#data bits} - 4 - \text{length string}) * \text{data per bit string}}{\text{length of the bit string}} \Big\rfloor$$ 295 | --- 296 | --- There is one problem remaining. The length string depends on the version, 297 | --- and the version depends on the length string. But we take this into account when calculating the 298 | --- the capacity, so this is not really a problem here. 299 | 300 | -- The capacity (number of codewords) of each version (1-40) for error correction levels 1-4 (LMQH). 301 | -- The higher the ec level, the lower the capacity of the version. Taken from spec, tables 7-11. 302 | local capacity = { 303 | { 19, 16, 13, 9},{ 34, 28, 22, 16},{ 55, 44, 34, 26},{ 80, 64, 48, 36}, 304 | { 108, 86, 62, 46},{ 136, 108, 76, 60},{ 156, 124, 88, 66},{ 194, 154, 110, 86}, 305 | { 232, 182, 132, 100},{ 274, 216, 154, 122},{ 324, 254, 180, 140},{ 370, 290, 206, 158}, 306 | { 428, 334, 244, 180},{ 461, 365, 261, 197},{ 523, 415, 295, 223},{ 589, 453, 325, 253}, 307 | { 647, 507, 367, 283},{ 721, 563, 397, 313},{ 795, 627, 445, 341},{ 861, 669, 485, 385}, 308 | { 932, 714, 512, 406},{1006, 782, 568, 442},{1094, 860, 614, 464},{1174, 914, 664, 514}, 309 | {1276, 1000, 718, 538},{1370, 1062, 754, 596},{1468, 1128, 808, 628},{1531, 1193, 871, 661}, 310 | {1631, 1267, 911, 701},{1735, 1373, 985, 745},{1843, 1455, 1033, 793},{1955, 1541, 1115, 845}, 311 | {2071, 1631, 1171, 901},{2191, 1725, 1231, 961},{2306, 1812, 1286, 986},{2434, 1914, 1354, 1054}, 312 | {2566, 1992, 1426, 1096},{2702, 2102, 1502, 1142},{2812, 2216, 1582, 1222},{2956, 2334, 1666, 1276}} 313 | 314 | 315 | --- Return the smallest version for this codeword. If `requested_ec_level` is supplied, 316 | --- then the ec level (LMQH - 1,2,3,4) must be at least the requested level. 317 | -- mode = 1,2,4,8 318 | local function get_version_eclevel(len,mode,requested_ec_level) 319 | local local_mode = mode 320 | if mode == 4 then 321 | local_mode = 3 322 | elseif mode == 8 then 323 | local_mode = 4 324 | end 325 | assert( local_mode <= 4 ) 326 | 327 | local bytes, bits, digits, modebits, c 328 | local tab = { {10,9,8,8},{12,11,16,10},{14,13,16,12} } 329 | local minversion = 40 330 | local maxec_level = requested_ec_level or 1 331 | local min,max = 1, 4 332 | if requested_ec_level and requested_ec_level >= 1 and requested_ec_level <= 4 then 333 | min = requested_ec_level 334 | max = requested_ec_level 335 | end 336 | for ec_level=min,max do 337 | for version=1,#capacity do 338 | bits = capacity[version][ec_level] * 8 339 | bits = bits - 4 -- the mode indicator 340 | if version < 10 then 341 | digits = tab[1][local_mode] 342 | elseif version < 27 then 343 | digits = tab[2][local_mode] 344 | elseif version <= 40 then 345 | digits = tab[3][local_mode] 346 | end 347 | modebits = bits - digits 348 | if local_mode == 1 then -- numeric 349 | c = math.floor(modebits * 3 / 10) 350 | elseif local_mode == 2 then -- alphanumeric 351 | c = math.floor(modebits * 2 / 11) 352 | elseif local_mode == 3 then -- binary 353 | c = math.floor(modebits * 1 / 8) 354 | else 355 | c = math.floor(modebits * 1 / 13) 356 | end 357 | if c >= len then 358 | if version <= minversion then 359 | minversion = version 360 | maxec_level = ec_level 361 | end 362 | break 363 | end 364 | end 365 | end 366 | return minversion, maxec_level 367 | end 368 | 369 | -- Return a bit string of 0s and 1s that includes the length of the code string. 370 | -- The modes are numeric = 1, alphanumeric = 2, binary = 4, and japanese = 8 371 | local function get_length(str,version,mode) 372 | local i = mode 373 | if mode == 4 then 374 | i = 3 375 | elseif mode == 8 then 376 | i = 4 377 | end 378 | assert( i <= 4 ) 379 | local tab = { {10,9,8,8},{12,11,16,10},{14,13,16,12} } 380 | local digits 381 | if version < 10 then 382 | digits = tab[1][i] 383 | elseif version < 27 then 384 | digits = tab[2][i] 385 | elseif version <= 40 then 386 | digits = tab[3][i] 387 | else 388 | assert(false, "get_length, version > 40 not supported") 389 | end 390 | local len = binary(#str,digits) 391 | return len 392 | end 393 | 394 | --- If the `requested_ec_level` or the `mode` are provided, this will be used if possible. 395 | --- The mode depends on the characters used in the string `str`. It seems to be 396 | --- possible to split the QR code to handle multiple modes, but we don't do that. 397 | local function get_version_eclevel_mode_bistringlength(str,requested_ec_level,mode) 398 | local local_mode 399 | if mode then 400 | assert(false,"not implemented") 401 | -- check if the mode is OK for the string 402 | local_mode = mode 403 | else 404 | local_mode = get_mode(str) 405 | end 406 | local version, ec_level 407 | version, ec_level = get_version_eclevel(#str,local_mode,requested_ec_level) 408 | local length_string = get_length(str,version,local_mode) 409 | return version,ec_level,binary(local_mode,4),local_mode,length_string 410 | end 411 | 412 | --- Step 2: Encode data 413 | --- =================== 414 | 415 | --- There are several ways to encode the data. We currently support only numeric, alphanumeric and binary. 416 | --- We already chose the encoding (a.k.a. mode) in the first step, so we need to apply the mode to the 417 | --- codeword. 418 | --- 419 | --- **Numeric**: take three digits and encode them in 10 bits 420 | --- **Alphanumeric**: take two characters and encode them in 11 bits 421 | --- **Binary**: take one octet and encode it in 8 bits 422 | 423 | local asciitbl = { 424 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -- 0x01-0x0f 425 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -- 0x10-0x1f 426 | 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, -- 0x20-0x2f 427 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, -- 0x30-0x3f 428 | -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -- 0x40-0x4f 429 | 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -- 0x50-0x5f 430 | } 431 | 432 | -- Return a binary representation of the numeric string `str`. This must contain only digits 0-9. 433 | local function encode_string_numeric(str) 434 | local bitstring = "" 435 | local int 436 | string.gsub(str,"..?.?",function(a) 437 | int = tonumber(a) 438 | if #a == 3 then 439 | bitstring = bitstring .. binary(int,10) 440 | elseif #a == 2 then 441 | bitstring = bitstring .. binary(int,7) 442 | else 443 | bitstring = bitstring .. binary(int,4) 444 | end 445 | end) 446 | return bitstring 447 | end 448 | 449 | -- Return a binary representation of the alphanumeric string `str`. This must contain only 450 | -- digits 0-9, uppercase letters A-Z, space and the following chars: $%*./:+-. 451 | local function encode_string_ascii(str) 452 | local bitstring = "" 453 | local int 454 | local b1, b2 455 | string.gsub(str,"..?",function(a) 456 | if #a == 2 then 457 | b1 = asciitbl[string.byte(string.sub(a,1,1))] 458 | b2 = asciitbl[string.byte(string.sub(a,2,2))] 459 | int = b1 * 45 + b2 460 | bitstring = bitstring .. binary(int,11) 461 | else 462 | int = asciitbl[string.byte(a)] 463 | bitstring = bitstring .. binary(int,6) 464 | end 465 | end) 466 | return bitstring 467 | end 468 | 469 | -- Return a bitstring representing string str in binary mode. 470 | -- We don't handle UTF-8 in any special way because we assume the 471 | -- scanner recognizes UTF-8 and displays it correctly. 472 | local function encode_string_binary(str) 473 | local ret = {} 474 | string.gsub(str,".",function(x) 475 | ret[#ret + 1] = binary(string.byte(x),8) 476 | end) 477 | return table.concat(ret) 478 | end 479 | 480 | -- Return a bitstring representing string str in the given mode. 481 | local function encode_data(str,mode) 482 | if mode == 1 then 483 | return encode_string_numeric(str) 484 | elseif mode == 2 then 485 | return encode_string_ascii(str) 486 | elseif mode == 4 then 487 | return encode_string_binary(str) 488 | else 489 | assert(false,"not implemented yet") 490 | end 491 | end 492 | 493 | -- Encoding the codeword is not enough. We need to make sure that 494 | -- the length of the binary string is equal to the number of codewords of the version. 495 | local function add_pad_data(version,ec_level,data) 496 | local count_to_pad, missing_digits 497 | local cpty = capacity[version][ec_level] * 8 498 | count_to_pad = math.min(4,cpty - #data) 499 | if count_to_pad > 0 then 500 | data = data .. string.rep("0",count_to_pad) 501 | end 502 | if math.fmod(#data,8) ~= 0 then 503 | missing_digits = 8 - math.fmod(#data,8) 504 | data = data .. string.rep("0",missing_digits) 505 | end 506 | assert(math.fmod(#data,8) == 0) 507 | -- add "11101100" and "00010001" until enough data 508 | while #data < cpty do 509 | data = data .. "11101100" 510 | if #data < cpty then 511 | data = data .. "00010001" 512 | end 513 | end 514 | return data 515 | end 516 | 517 | 518 | 519 | --- Step 3: Organize data and calculate error correction code 520 | --- ======================================================= 521 | --- The data in the qrcode is not encoded linearly. For example code 5-H has four blocks, the first two blocks 522 | --- contain 11 codewords and 22 error correction codes each, the second block contain 12 codewords and 22 ec codes each. 523 | --- We just take the table from the spec and don't calculate the blocks ourself. The table `ecblocks` contains this info. 524 | --- 525 | --- During the phase of splitting the data into codewords, we do the calculation for error correction codes. This step involves 526 | --- polynomial division. Find a math book from school and follow the code here :) 527 | 528 | --- ### Reed Solomon error correction 529 | --- Now this is the slightly ugly part of the error correction. We start with log/antilog tables 530 | local alpha_int = { 531 | [0] = 0, 532 | 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, 19, 38, 76, 533 | 152, 45, 90, 180, 117, 234, 201, 143, 3, 6, 12, 24, 48, 96, 192, 157, 534 | 39, 78, 156, 37, 74, 148, 53, 106, 212, 181, 119, 238, 193, 159, 35, 70, 535 | 140, 5, 10, 20, 40, 80, 160, 93, 186, 105, 210, 185, 111, 222, 161, 95, 536 | 190, 97, 194, 153, 47, 94, 188, 101, 202, 137, 15, 30, 60, 120, 240, 253, 537 | 231, 211, 187, 107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, 217, 538 | 175, 67, 134, 17, 34, 68, 136, 13, 26, 52, 104, 208, 189, 103, 206, 129, 539 | 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197, 151, 51, 102, 204, 133, 540 | 23, 46, 92, 184, 109, 218, 169, 79, 158, 33, 66, 132, 21, 42, 84, 168, 541 | 77, 154, 41, 82, 164, 85, 170, 73, 146, 57, 114, 228, 213, 183, 115, 230, 542 | 209, 191, 99, 198, 145, 63, 126, 252, 229, 215, 179, 123, 246, 241, 255, 227, 543 | 219, 171, 75, 150, 49, 98, 196, 149, 55, 110, 220, 165, 87, 174, 65, 130, 544 | 25, 50, 100, 200, 141, 7, 14, 28, 56, 112, 224, 221, 167, 83, 166, 81, 545 | 162, 89, 178, 121, 242, 249, 239, 195, 155, 43, 86, 172, 69, 138, 9, 18, 546 | 36, 72, 144, 61, 122, 244, 245, 247, 243, 251, 235, 203, 139, 11, 22, 44, 547 | 88, 176, 125, 250, 233, 207, 131, 27, 54, 108, 216, 173, 71, 142, 1 548 | } 549 | 550 | local int_alpha = { 551 | [0] = 0, 552 | 255, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238, 27, 104, 199, 75, 4, 553 | 100, 224, 14, 52, 141, 239, 129, 28, 193, 105, 248, 200, 8, 76, 113, 5, 554 | 138, 101, 47, 225, 36, 15, 33, 53, 147, 142, 218, 240, 18, 130, 69, 29, 555 | 181, 194, 125, 106, 39, 249, 185, 201, 154, 9, 120, 77, 228, 114, 166, 6, 556 | 191, 139, 98, 102, 221, 48, 253, 226, 152, 37, 179, 16, 145, 34, 136, 54, 557 | 208, 148, 206, 143, 150, 219, 189, 241, 210, 19, 92, 131, 56, 70, 64, 30, 558 | 66, 182, 163, 195, 72, 126, 110, 107, 58, 40, 84, 250, 133, 186, 61, 202, 559 | 94, 155, 159, 10, 21, 121, 43, 78, 212, 229, 172, 115, 243, 167, 87, 7, 560 | 112, 192, 247, 140, 128, 99, 13, 103, 74, 222, 237, 49, 197, 254, 24, 227, 561 | 165, 153, 119, 38, 184, 180, 124, 17, 68, 146, 217, 35, 32, 137, 46, 55, 562 | 63, 209, 91, 149, 188, 207, 205, 144, 135, 151, 178, 220, 252, 190, 97, 242, 563 | 86, 211, 171, 20, 42, 93, 158, 132, 60, 57, 83, 71, 109, 65, 162, 31, 564 | 45, 67, 216, 183, 123, 164, 118, 196, 23, 73, 236, 127, 12, 111, 246, 108, 565 | 161, 59, 82, 41, 157, 85, 170, 251, 96, 134, 177, 187, 204, 62, 90, 203, 566 | 89, 95, 176, 156, 169, 160, 81, 11, 245, 22, 235, 122, 117, 44, 215, 79, 567 | 174, 213, 233, 230, 231, 173, 232, 116, 214, 244, 234, 168, 80, 88, 175 568 | } 569 | 570 | -- We only need the polynomial generators for block sizes 7, 10, 13, 15, 16, 17, 18, 20, 22, 24, 26, 28, and 30. Version 571 | -- 2 of the qr codes don't need larger ones (as opposed to version 1). The table has the format x^1*ɑ^21 + x^2*a^102 ... 572 | local generator_polynomial = { 573 | [7] = { 21, 102, 238, 149, 146, 229, 87, 0}, 574 | [10] = { 45, 32, 94, 64, 70, 118, 61, 46, 67, 251, 0 }, 575 | [13] = { 78, 140, 206, 218, 130, 104, 106, 100, 86, 100, 176, 152, 74, 0 }, 576 | [15] = {105, 99, 5, 124, 140, 237, 58, 58, 51, 37, 202, 91, 61, 183, 8, 0}, 577 | [16] = {120, 225, 194, 182, 169, 147, 191, 91, 3, 76, 161, 102, 109, 107, 104, 120, 0}, 578 | [17] = {136, 163, 243, 39, 150, 99, 24, 147, 214, 206, 123, 239, 43, 78, 206, 139, 43, 0}, 579 | [18] = {153, 96, 98, 5, 179, 252, 148, 152, 187, 79, 170, 118, 97, 184, 94, 158, 234, 215, 0}, 580 | [20] = {190, 188, 212, 212, 164, 156, 239, 83, 225, 221, 180, 202, 187, 26, 163, 61, 50, 79, 60, 17, 0}, 581 | [22] = {231, 165, 105, 160, 134, 219, 80, 98, 172, 8, 74, 200, 53, 221, 109, 14, 230, 93, 242, 247, 171, 210, 0}, 582 | [24] = { 21, 227, 96, 87, 232, 117, 0, 111, 218, 228, 226, 192, 152, 169, 180, 159, 126, 251, 117, 211, 48, 135, 121, 229, 0}, 583 | [26] = { 70, 218, 145, 153, 227, 48, 102, 13, 142, 245, 21, 161, 53, 165, 28, 111, 201, 145, 17, 118, 182, 103, 2, 158, 125, 173, 0}, 584 | [28] = {123, 9, 37, 242, 119, 212, 195, 42, 87, 245, 43, 21, 201, 232, 27, 205, 147, 195, 190, 110, 180, 108, 234, 224, 104, 200, 223, 168, 0}, 585 | [30] = {180, 192, 40, 238, 216, 251, 37, 156, 130, 224, 193, 226, 173, 42, 125, 222, 96, 239, 86, 110, 48, 50, 182, 179, 31, 216, 152, 145, 173, 41, 0}} 586 | 587 | 588 | -- Turn a binary string of length 8*x into a table size x of numbers. 589 | local function convert_bitstring_to_bytes(data) 590 | local msg = {} 591 | local tab = string.gsub(data,"(........)",function(x) 592 | msg[#msg+1] = tonumber(x,2) 593 | end) 594 | return msg 595 | end 596 | 597 | -- Return a table that has 0's in the first entries and then the alpha 598 | -- representation of the generator polynominal 599 | local function get_generator_polynominal_adjusted(num_ec_codewords,highest_exponent) 600 | local gp_alpha = {[0]=0} 601 | for i=0,highest_exponent - num_ec_codewords - 1 do 602 | gp_alpha[i] = 0 603 | end 604 | local gp = generator_polynomial[num_ec_codewords] 605 | for i=1,num_ec_codewords + 1 do 606 | gp_alpha[highest_exponent - num_ec_codewords + i - 1] = gp[i] 607 | end 608 | return gp_alpha 609 | end 610 | 611 | --- These converter functions use the log/antilog table above. 612 | --- We could have created the table programatically, but I like fixed tables. 613 | -- Convert polynominal in int notation to alpha notation. 614 | local function convert_to_alpha( tab ) 615 | local new_tab = {} 616 | for i=0,#tab do 617 | new_tab[i] = int_alpha[tab[i]] 618 | end 619 | return new_tab 620 | end 621 | 622 | -- Convert polynominal in alpha notation to int notation. 623 | local function convert_to_int(tab,len_message) 624 | local new_tab = {} 625 | for i=0,#tab do 626 | new_tab[i] = alpha_int[tab[i]] 627 | end 628 | return new_tab 629 | end 630 | 631 | -- That's the heart of the error correction calculation. 632 | local function calculate_error_correction(data,num_ec_codewords) 633 | local mp 634 | if type(data)=="string" then 635 | mp = convert_bitstring_to_bytes(data) 636 | elseif type(data)=="table" then 637 | mp = data 638 | else 639 | assert(false,"Unknown type for data: %s",type(data)) 640 | end 641 | local len_message = #mp 642 | 643 | local highest_exponent = len_message + num_ec_codewords - 1 644 | local gp_alpha,tmp 645 | local he 646 | local gp_int = {} 647 | local mp_int,mp_alpha = {},{} 648 | -- create message shifted to left (highest exponent) 649 | for i=1,len_message do 650 | mp_int[highest_exponent - i + 1] = mp[i] 651 | end 652 | for i=1,highest_exponent - len_message do 653 | mp_int[i] = 0 654 | end 655 | mp_int[0] = 0 656 | 657 | mp_alpha = convert_to_alpha(mp_int) 658 | 659 | while highest_exponent >= num_ec_codewords do 660 | gp_alpha = get_generator_polynominal_adjusted(num_ec_codewords,highest_exponent) 661 | 662 | -- Multiply generator polynomial by first coefficient of the above polynomial 663 | 664 | -- take the highest exponent from the message polynom (alpha) and add 665 | -- it to the generator polynom 666 | local exp = mp_alpha[highest_exponent] 667 | for i=highest_exponent,highest_exponent - num_ec_codewords,-1 do 668 | if gp_alpha[i] + exp > 255 then 669 | gp_alpha[i] = math.fmod(gp_alpha[i] + exp,255) 670 | else 671 | gp_alpha[i] = gp_alpha[i] + exp 672 | end 673 | end 674 | for i=highest_exponent - num_ec_codewords - 1,0,-1 do 675 | gp_alpha[i] = 0 676 | end 677 | 678 | gp_int = convert_to_int(gp_alpha) 679 | mp_int = convert_to_int(mp_alpha) 680 | 681 | 682 | tmp = {} 683 | for i=highest_exponent,0,-1 do 684 | tmp[i] = bit_xor(gp_int[i],mp_int[i]) 685 | end 686 | -- remove leading 0's 687 | he = highest_exponent 688 | for i=he,0,-1 do 689 | -- We need to stop if the length of the codeword is matched 690 | if i < num_ec_codewords then break end 691 | if tmp[i] == 0 then 692 | tmp[i] = nil 693 | highest_exponent = highest_exponent - 1 694 | else 695 | break 696 | end 697 | end 698 | mp_int = tmp 699 | mp_alpha = convert_to_alpha(mp_int) 700 | end 701 | local ret = {} 702 | 703 | -- reverse data 704 | for i=#mp_int,0,-1 do 705 | ret[#ret + 1] = mp_int[i] 706 | end 707 | return ret 708 | end 709 | 710 | --- #### Arranging the data 711 | --- Now we arrange the data into smaller chunks. This table is taken from the spec. 712 | -- ecblocks has 40 entries, one for each version. Each version entry has 4 entries, for each LMQH 713 | -- ec level. Each entry has two or four fields, the odd files are the number of repetitions for the 714 | -- folowing block info. The first entry of the block is the total number of codewords in the block, 715 | -- the second entry is the number of data codewords. The third is not important. 716 | local ecblocks = { 717 | {{ 1,{ 26, 19, 2} }, { 1,{26,16, 4}}, { 1,{26,13, 6}}, { 1, {26, 9, 8} }}, 718 | {{ 1,{ 44, 34, 4} }, { 1,{44,28, 8}}, { 1,{44,22,11}}, { 1, {44,16,14} }}, 719 | {{ 1,{ 70, 55, 7} }, { 1,{70,44,13}}, { 2,{35,17, 9}}, { 2, {35,13,11} }}, 720 | {{ 1,{100, 80,10} }, { 2,{50,32, 9}}, { 2,{50,24,13}}, { 4, {25, 9, 8} }}, 721 | {{ 1,{134,108,13} }, { 2,{67,43,12}}, { 2,{33,15, 9}, 2,{34,16, 9}}, { 2, {33,11,11}, 2,{34,12,11}}}, 722 | {{ 2,{ 86, 68, 9} }, { 4,{43,27, 8}}, { 4,{43,19,12}}, { 4, {43,15,14} }}, 723 | {{ 2,{ 98, 78,10} }, { 4,{49,31, 9}}, { 2,{32,14, 9}, 4,{33,15, 9}}, { 4, {39,13,13}, 1,{40,14,13}}}, 724 | {{ 2,{121, 97,12} }, { 2,{60,38,11}, 2,{61,39,11}}, { 4,{40,18,11}, 2,{41,19,11}}, { 4, {40,14,13}, 2,{41,15,13}}}, 725 | {{ 2,{146,116,15} }, { 3,{58,36,11}, 2,{59,37,11}}, { 4,{36,16,10}, 4,{37,17,10}}, { 4, {36,12,12}, 4,{37,13,12}}}, 726 | {{ 2,{ 86, 68, 9}, 2,{ 87, 69, 9}}, { 4,{69,43,13}, 1,{70,44,13}}, { 6,{43,19,12}, 2,{44,20,12}}, { 6, {43,15,14}, 2,{44,16,14}}}, 727 | {{ 4,{101, 81,10} }, { 1,{80,50,15}, 4,{81,51,15}}, { 4,{50,22,14}, 4,{51,23,14}}, { 3, {36,12,12}, 8,{37,13,12}}}, 728 | {{ 2,{116, 92,12}, 2,{117, 93,12}}, { 6,{58,36,11}, 2,{59,37,11}}, { 4,{46,20,13}, 6,{47,21,13}}, { 7, {42,14,14}, 4,{43,15,14}}}, 729 | {{ 4,{133,107,13} }, { 8,{59,37,11}, 1,{60,38,11}}, { 8,{44,20,12}, 4,{45,21,12}}, { 12, {33,11,11}, 4,{34,12,11}}}, 730 | {{ 3,{145,115,15}, 1,{146,116,15}}, { 4,{64,40,12}, 5,{65,41,12}}, { 11,{36,16,10}, 5,{37,17,10}}, { 11, {36,12,12}, 5,{37,13,12}}}, 731 | {{ 5,{109, 87,11}, 1,{110, 88,11}}, { 5,{65,41,12}, 5,{66,42,12}}, { 5,{54,24,15}, 7,{55,25,15}}, { 11, {36,12,12}, 7,{37,13,12}}}, 732 | {{ 5,{122, 98,12}, 1,{123, 99,12}}, { 7,{73,45,14}, 3,{74,46,14}}, { 15,{43,19,12}, 2,{44,20,12}}, { 3, {45,15,15}, 13,{46,16,15}}}, 733 | {{ 1,{135,107,14}, 5,{136,108,14}}, { 10,{74,46,14}, 1,{75,47,14}}, { 1,{50,22,14}, 15,{51,23,14}}, { 2, {42,14,14}, 17,{43,15,14}}}, 734 | {{ 5,{150,120,15}, 1,{151,121,15}}, { 9,{69,43,13}, 4,{70,44,13}}, { 17,{50,22,14}, 1,{51,23,14}}, { 2, {42,14,14}, 19,{43,15,14}}}, 735 | {{ 3,{141,113,14}, 4,{142,114,14}}, { 3,{70,44,13}, 11,{71,45,13}}, { 17,{47,21,13}, 4,{48,22,13}}, { 9, {39,13,13}, 16,{40,14,13}}}, 736 | {{ 3,{135,107,14}, 5,{136,108,14}}, { 3,{67,41,13}, 13,{68,42,13}}, { 15,{54,24,15}, 5,{55,25,15}}, { 15, {43,15,14}, 10,{44,16,14}}}, 737 | {{ 4,{144,116,14}, 4,{145,117,14}}, { 17,{68,42,13}}, { 17,{50,22,14}, 6,{51,23,14}}, { 19, {46,16,15}, 6,{47,17,15}}}, 738 | {{ 2,{139,111,14}, 7,{140,112,14}}, { 17,{74,46,14}}, { 7,{54,24,15}, 16,{55,25,15}}, { 34, {37,13,12} }}, 739 | {{ 4,{151,121,15}, 5,{152,122,15}}, { 4,{75,47,14}, 14,{76,48,14}}, { 11,{54,24,15}, 14,{55,25,15}}, { 16, {45,15,15}, 14,{46,16,15}}}, 740 | {{ 6,{147,117,15}, 4,{148,118,15}}, { 6,{73,45,14}, 14,{74,46,14}}, { 11,{54,24,15}, 16,{55,25,15}}, { 30, {46,16,15}, 2,{47,17,15}}}, 741 | {{ 8,{132,106,13}, 4,{133,107,13}}, { 8,{75,47,14}, 13,{76,48,14}}, { 7,{54,24,15}, 22,{55,25,15}}, { 22, {45,15,15}, 13,{46,16,15}}}, 742 | {{ 10,{142,114,14}, 2,{143,115,14}}, { 19,{74,46,14}, 4,{75,47,14}}, { 28,{50,22,14}, 6,{51,23,14}}, { 33, {46,16,15}, 4,{47,17,15}}}, 743 | {{ 8,{152,122,15}, 4,{153,123,15}}, { 22,{73,45,14}, 3,{74,46,14}}, { 8,{53,23,15}, 26,{54,24,15}}, { 12, {45,15,15}, 28,{46,16,15}}}, 744 | {{ 3,{147,117,15}, 10,{148,118,15}}, { 3,{73,45,14}, 23,{74,46,14}}, { 4,{54,24,15}, 31,{55,25,15}}, { 11, {45,15,15}, 31,{46,16,15}}}, 745 | {{ 7,{146,116,15}, 7,{147,117,15}}, { 21,{73,45,14}, 7,{74,46,14}}, { 1,{53,23,15}, 37,{54,24,15}}, { 19, {45,15,15}, 26,{46,16,15}}}, 746 | {{ 5,{145,115,15}, 10,{146,116,15}}, { 19,{75,47,14}, 10,{76,48,14}}, { 15,{54,24,15}, 25,{55,25,15}}, { 23, {45,15,15}, 25,{46,16,15}}}, 747 | {{ 13,{145,115,15}, 3,{146,116,15}}, { 2,{74,46,14}, 29,{75,47,14}}, { 42,{54,24,15}, 1,{55,25,15}}, { 23, {45,15,15}, 28,{46,16,15}}}, 748 | {{ 17,{145,115,15} }, { 10,{74,46,14}, 23,{75,47,14}}, { 10,{54,24,15}, 35,{55,25,15}}, { 19, {45,15,15}, 35,{46,16,15}}}, 749 | {{ 17,{145,115,15}, 1,{146,116,15}}, { 14,{74,46,14}, 21,{75,47,14}}, { 29,{54,24,15}, 19,{55,25,15}}, { 11, {45,15,15}, 46,{46,16,15}}}, 750 | {{ 13,{145,115,15}, 6,{146,116,15}}, { 14,{74,46,14}, 23,{75,47,14}}, { 44,{54,24,15}, 7,{55,25,15}}, { 59, {46,16,15}, 1,{47,17,15}}}, 751 | {{ 12,{151,121,15}, 7,{152,122,15}}, { 12,{75,47,14}, 26,{76,48,14}}, { 39,{54,24,15}, 14,{55,25,15}}, { 22, {45,15,15}, 41,{46,16,15}}}, 752 | {{ 6,{151,121,15}, 14,{152,122,15}}, { 6,{75,47,14}, 34,{76,48,14}}, { 46,{54,24,15}, 10,{55,25,15}}, { 2, {45,15,15}, 64,{46,16,15}}}, 753 | {{ 17,{152,122,15}, 4,{153,123,15}}, { 29,{74,46,14}, 14,{75,47,14}}, { 49,{54,24,15}, 10,{55,25,15}}, { 24, {45,15,15}, 46,{46,16,15}}}, 754 | {{ 4,{152,122,15}, 18,{153,123,15}}, { 13,{74,46,14}, 32,{75,47,14}}, { 48,{54,24,15}, 14,{55,25,15}}, { 42, {45,15,15}, 32,{46,16,15}}}, 755 | {{ 20,{147,117,15}, 4,{148,118,15}}, { 40,{75,47,14}, 7,{76,48,14}}, { 43,{54,24,15}, 22,{55,25,15}}, { 10, {45,15,15}, 67,{46,16,15}}}, 756 | {{ 19,{148,118,15}, 6,{149,119,15}}, { 18,{75,47,14}, 31,{76,48,14}}, { 34,{54,24,15}, 34,{55,25,15}}, { 20, {45,15,15}, 61,{46,16,15}}} 757 | } 758 | 759 | -- The bits that must be 0 if the version does fill the complete matrix. 760 | -- Example: for version 1, no bits need to be added after arranging the data, for version 2 we need to add 7 bits at the end. 761 | local remainder = {0, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0} 762 | 763 | -- This is the formula for table 1 in the spec: 764 | -- function get_capacity_remainder( version ) 765 | -- local len = version * 4 + 17 766 | -- local size = len^2 767 | -- local function_pattern_modules = 192 + 2 * len - 32 -- Position Adjustment pattern + timing pattern 768 | -- local count_alignemnt_pattern = #alignment_pattern[version] 769 | -- if count_alignemnt_pattern > 0 then 770 | -- -- add 25 for each aligment pattern 771 | -- function_pattern_modules = function_pattern_modules + 25 * ( count_alignemnt_pattern^2 - 3 ) 772 | -- -- but substract the timing pattern occupied by the aligment pattern on the top and left 773 | -- function_pattern_modules = function_pattern_modules - ( count_alignemnt_pattern - 2) * 10 774 | -- end 775 | -- size = size - function_pattern_modules 776 | -- if version > 6 then 777 | -- size = size - 67 778 | -- else 779 | -- size = size - 31 780 | -- end 781 | -- return math.floor(size/8),math.fmod(size,8) 782 | -- end 783 | 784 | 785 | --- Example: Version 5-H has four data and four error correction blocks. The table above lists 786 | --- `2, {33,11,11}, 2,{34,12,11}` for entry [5][4]. This means we take two blocks with 11 codewords 787 | --- and two blocks with 12 codewords, and two blocks with 33 - 11 = 22 ec codes and another 788 | --- two blocks with 34 - 12 = 22 ec codes. 789 | --- Block 1: D1 D2 D3 ... D11 790 | --- Block 2: D12 D13 D14 ... D22 791 | --- Block 3: D23 D24 D25 ... D33 D34 792 | --- Block 4: D35 D36 D37 ... D45 D46 793 | --- Then we place the data like this in the matrix: D1, D12, D23, D35, D2, D13, D24, D36 ... D45, D34, D46. The same goes 794 | --- with error correction codes. 795 | 796 | -- The given data can be a string of 0's and 1' (with #string mod 8 == 0). 797 | -- Alternatively the data can be a table of codewords. The number of codewords 798 | -- must match the capacity of the qr code. 799 | local function arrange_codewords_and_calculate_ec( version,ec_level,data ) 800 | if type(data)=="table" then 801 | local tmp = "" 802 | for i=1,#data do 803 | tmp = tmp .. binary(data[i],8) 804 | end 805 | data = tmp 806 | end 807 | -- If the size of the data is not enough for the codeword, we add 0's and two special bytes until finished. 808 | local blocks = ecblocks[version][ec_level] 809 | local size_datablock_bytes, size_ecblock_bytes 810 | local datablocks = {} 811 | local ecblocks = {} 812 | local count = 1 813 | local pos = 0 814 | local cpty_ec_bits = 0 815 | for i=1,#blocks/2 do 816 | for j=1,blocks[2*i - 1] do 817 | size_datablock_bytes = blocks[2*i][2] 818 | size_ecblock_bytes = blocks[2*i][1] - blocks[2*i][2] 819 | cpty_ec_bits = cpty_ec_bits + size_ecblock_bytes * 8 820 | datablocks[#datablocks + 1] = string.sub(data, pos * 8 + 1,( pos + size_datablock_bytes)*8) 821 | tmp_tab = calculate_error_correction(datablocks[#datablocks],size_ecblock_bytes) 822 | tmp_str = "" 823 | for x=1,#tmp_tab do 824 | tmp_str = tmp_str .. binary(tmp_tab[x],8) 825 | end 826 | ecblocks[#ecblocks + 1] = tmp_str 827 | pos = pos + size_datablock_bytes 828 | count = count + 1 829 | end 830 | end 831 | local arranged_data = "" 832 | pos = 1 833 | repeat 834 | for i=1,#datablocks do 835 | if pos < #datablocks[i] then 836 | arranged_data = arranged_data .. string.sub(datablocks[i],pos, pos + 7) 837 | end 838 | end 839 | pos = pos + 8 840 | until #arranged_data == #data 841 | -- ec 842 | local arranged_ec = "" 843 | pos = 1 844 | repeat 845 | for i=1,#ecblocks do 846 | if pos < #ecblocks[i] then 847 | arranged_ec = arranged_ec .. string.sub(ecblocks[i],pos, pos + 7) 848 | end 849 | end 850 | pos = pos + 8 851 | until #arranged_ec == cpty_ec_bits 852 | return arranged_data .. arranged_ec 853 | end 854 | 855 | --- Step 4: Generate 8 matrices with different masks and calculate the penalty 856 | --- ========================================================================== 857 | --- 858 | --- Prepare matrix 859 | --- -------------- 860 | --- The first step is to prepare an _empty_ matrix for a given size/mask. The matrix has a 861 | --- few predefined areas that must be black or blank. We encode the matrix with a two 862 | --- dimensional field where the numbers determine which pixel is blank or not. 863 | --- 864 | --- The following code is used for our matrix: 865 | --- 0 = not in use yet, 866 | --- -2 = blank by mandatory pattern, 867 | --- 2 = black by mandatory pattern, 868 | --- -1 = blank by data, 869 | --- 1 = black by data 870 | --- 871 | --- 872 | --- To prepare the _empty_, we add positioning, alingment and timing patters. 873 | 874 | --- ### Positioning patterns ### 875 | local function add_position_detection_patterns(tab_x) 876 | local size = #tab_x 877 | -- allocate quite zone in the matrix area 878 | for i=1,8 do 879 | for j=1,8 do 880 | tab_x[i][j] = -2 881 | tab_x[size - 8 + i][j] = -2 882 | tab_x[i][size - 8 + j] = -2 883 | end 884 | end 885 | -- draw the detection pattern (outer) 886 | for i=1,7 do 887 | -- top left 888 | tab_x[1][i]=2 889 | tab_x[7][i]=2 890 | tab_x[i][1]=2 891 | tab_x[i][7]=2 892 | 893 | -- top right 894 | tab_x[size][i]=2 895 | tab_x[size - 6][i]=2 896 | tab_x[size - i + 1][1]=2 897 | tab_x[size - i + 1][7]=2 898 | 899 | -- bottom left 900 | tab_x[1][size - i + 1]=2 901 | tab_x[7][size - i + 1]=2 902 | tab_x[i][size - 6]=2 903 | tab_x[i][size]=2 904 | end 905 | -- draw the detection pattern (inner) 906 | for i=1,3 do 907 | for j=1,3 do 908 | -- top left 909 | tab_x[2+j][i+2]=2 910 | -- top right 911 | tab_x[size - j - 1][i+2]=2 912 | -- bottom left 913 | tab_x[2 + j][size - i - 1]=2 914 | end 915 | end 916 | end 917 | 918 | --- ### Timing patterns ### 919 | -- The timing patterns (two) are the dashed lines between two adjacent positioning patterns on row/column 7. 920 | local function add_timing_pattern(tab_x) 921 | local line,col 922 | line = 7 923 | col = 9 924 | for i=col,#tab_x - 8 do 925 | if math.fmod(i,2) == 1 then 926 | tab_x[i][line] = 2 927 | else 928 | tab_x[i][line] = -2 929 | end 930 | end 931 | for i=col,#tab_x - 8 do 932 | if math.fmod(i,2) == 1 then 933 | tab_x[line][i] = 2 934 | else 935 | tab_x[line][i] = -2 936 | end 937 | end 938 | end 939 | 940 | 941 | --- ### Alignment patterns ### 942 | --- The alignment patterns must be added to the matrix for versions > 1. The amount and positions depend on the versions and are 943 | --- given by the spec. Beware: the patterns must not be placed where we have the positioning patterns 944 | --- (that is: top left, top right and bottom left.) 945 | 946 | -- For each version, where should we place the alignment patterns? See table E.1 of the spec 947 | local alignment_pattern = { 948 | {},{6,18},{6,22},{6,26},{6,30},{6,34}, -- 1-6 949 | {6,22,38},{6,24,42},{6,26,46},{6,28,50},{6,30,54},{6,32,58},{6,34,62}, -- 7-13 950 | {6,26,46,66},{6,26,48,70},{6,26,50,74},{6,30,54,78},{6,30,56,82},{6,30,58,86},{6,34,62,90}, -- 14-20 951 | {6,28,50,72,94},{6,26,50,74,98},{6,30,54,78,102},{6,28,54,80,106},{6,32,58,84,110},{6,30,58,86,114},{6,34,62,90,118}, -- 21-27 952 | {6,26,50,74,98 ,122},{6,30,54,78,102,126},{6,26,52,78,104,130},{6,30,56,82,108,134},{6,34,60,86,112,138},{6,30,58,86,114,142},{6,34,62,90,118,146}, -- 28-34 953 | {6,30,54,78,102,126,150}, {6,24,50,76,102,128,154},{6,28,54,80,106,132,158},{6,32,58,84,110,136,162},{6,26,54,82,110,138,166},{6,30,58,86,114,142,170} -- 35 - 40 954 | } 955 | 956 | --- The alignment pattern has size 5x5 and looks like this: 957 | --- XXXXX 958 | --- X X 959 | --- X X X 960 | --- X X 961 | --- XXXXX 962 | local function add_alignment_pattern( tab_x ) 963 | local version = (#tab_x - 17) / 4 964 | local ap = alignment_pattern[version] 965 | local pos_x, pos_y 966 | for x=1,#ap do 967 | for y=1,#ap do 968 | -- we must not put an alignment pattern on top of the positioning pattern 969 | if not (x == 1 and y == 1 or x == #ap and y == 1 or x == 1 and y == #ap ) then 970 | pos_x = ap[x] + 1 971 | pos_y = ap[y] + 1 972 | tab_x[pos_x][pos_y] = 2 973 | tab_x[pos_x+1][pos_y] = -2 974 | tab_x[pos_x-1][pos_y] = -2 975 | tab_x[pos_x+2][pos_y] = 2 976 | tab_x[pos_x-2][pos_y] = 2 977 | tab_x[pos_x ][pos_y - 2] = 2 978 | tab_x[pos_x+1][pos_y - 2] = 2 979 | tab_x[pos_x-1][pos_y - 2] = 2 980 | tab_x[pos_x+2][pos_y - 2] = 2 981 | tab_x[pos_x-2][pos_y - 2] = 2 982 | tab_x[pos_x ][pos_y + 2] = 2 983 | tab_x[pos_x+1][pos_y + 2] = 2 984 | tab_x[pos_x-1][pos_y + 2] = 2 985 | tab_x[pos_x+2][pos_y + 2] = 2 986 | tab_x[pos_x-2][pos_y + 2] = 2 987 | 988 | tab_x[pos_x ][pos_y - 1] = -2 989 | tab_x[pos_x+1][pos_y - 1] = -2 990 | tab_x[pos_x-1][pos_y - 1] = -2 991 | tab_x[pos_x+2][pos_y - 1] = 2 992 | tab_x[pos_x-2][pos_y - 1] = 2 993 | tab_x[pos_x ][pos_y + 1] = -2 994 | tab_x[pos_x+1][pos_y + 1] = -2 995 | tab_x[pos_x-1][pos_y + 1] = -2 996 | tab_x[pos_x+2][pos_y + 1] = 2 997 | tab_x[pos_x-2][pos_y + 1] = 2 998 | end 999 | end 1000 | end 1001 | end 1002 | 1003 | --- ### Type information ### 1004 | --- Let's not forget the type information that is in column 9 next to the left positioning patterns and on row 9 below 1005 | --- the top positioning patterns. This type information is not fixed, it depends on the mask and the error correction. 1006 | 1007 | -- The first index is ec level (LMQH,1-4), the second is the mask (0-7). This bitstring of length 15 is to be used 1008 | -- as mandatory pattern in the qrcode. Mask -1 is for debugging purpose only and is the 'noop' mask. 1009 | local typeinfo = { 1010 | { [-1]= "111111111111111", [0] = "111011111000100", "111001011110011", "111110110101010", "111100010011101", "110011000101111", "110001100011000", "110110001000001", "110100101110110" }, 1011 | { [-1]= "111111111111111", [0] = "101010000010010", "101000100100101", "101111001111100", "101101101001011", "100010111111001", "100000011001110", "100111110010111", "100101010100000" }, 1012 | { [-1]= "111111111111111", [0] = "011010101011111", "011000001101000", "011111100110001", "011101000000110", "010010010110100", "010000110000011", "010111011011010", "010101111101101" }, 1013 | { [-1]= "111111111111111", [0] = "001011010001001", "001001110111110", "001110011100111", "001100111010000", "000011101100010", "000001001010101", "000110100001100", "000100000111011" } 1014 | } 1015 | 1016 | -- The typeinfo is a mixture of mask and ec level information and is 1017 | -- added twice to the qr code, one horizontal, one vertical. 1018 | local function add_typeinfo_to_matrix( matrix,ec_level,mask ) 1019 | local ec_mask_type = typeinfo[ec_level][mask] 1020 | 1021 | local bit 1022 | -- vertical from bottom to top 1023 | for i=1,7 do 1024 | bit = string.sub(ec_mask_type,i,i) 1025 | fill_matrix_position(matrix, bit, 9, #matrix - i + 1) 1026 | end 1027 | for i=8,9 do 1028 | bit = string.sub(ec_mask_type,i,i) 1029 | fill_matrix_position(matrix,bit,9,17-i) 1030 | end 1031 | for i=10,15 do 1032 | bit = string.sub(ec_mask_type,i,i) 1033 | fill_matrix_position(matrix,bit,9,16 - i) 1034 | end 1035 | -- horizontal, left to right 1036 | for i=1,6 do 1037 | bit = string.sub(ec_mask_type,i,i) 1038 | fill_matrix_position(matrix,bit,i,9) 1039 | end 1040 | bit = string.sub(ec_mask_type,7,7) 1041 | fill_matrix_position(matrix,bit,8,9) 1042 | for i=8,15 do 1043 | bit = string.sub(ec_mask_type,i,i) 1044 | fill_matrix_position(matrix,bit,#matrix - 15 + i,9) 1045 | end 1046 | end 1047 | 1048 | -- Bits for version information 7-40 1049 | local version_information = {"001010010011111000", "000111101101000100", "100110010101100100","011001011001010100", 1050 | "011011111101110100", "001000110111001100", "111000100001101100", "010110000011011100", "000101001001111100", 1051 | "000111101101000010", "010111010001100010", "111010000101010010", "001001100101110010", "011001011001001010", 1052 | "011000001011101010", "100100110001011010", "000110111111111010", "001000110111000110", "000100001111100110", 1053 | "110101011111010110", "000001110001110110", "010110000011001110", "001111110011101110", "101011101011011110", 1054 | "000000101001111110", "101010111001000001", "000001111011100001", "010111010001010001", "011111001111110001", 1055 | "110100001101001001", "001110100001101001", "001001100101011001", "010000010101111001", "100101100011000101" } 1056 | 1057 | -- Versions 7 and above need two bitfields with version information added to the code 1058 | local function add_version_information(matrix,version) 1059 | if version < 7 then return end 1060 | local size = #matrix 1061 | local bitstring = version_information[version - 6] 1062 | local x,y, bit 1063 | local start_x, start_y 1064 | -- first top right 1065 | start_x = #matrix - 10 1066 | start_y = 1 1067 | for i=1,#bitstring do 1068 | bit = string.sub(bitstring,i,i) 1069 | x = start_x + math.fmod(i - 1,3) 1070 | y = start_y + math.floor( (i - 1) / 3 ) 1071 | fill_matrix_position(matrix,bit,x,y) 1072 | end 1073 | 1074 | -- now bottom left 1075 | start_x = 1 1076 | start_y = #matrix - 10 1077 | for i=1,#bitstring do 1078 | bit = string.sub(bitstring,i,i) 1079 | x = start_x + math.floor( (i - 1) / 3 ) 1080 | y = start_y + math.fmod(i - 1,3) 1081 | fill_matrix_position(matrix,bit,x,y) 1082 | end 1083 | end 1084 | 1085 | --- Now it's time to use the methods above to create a prefilled matrix for the given mask 1086 | local function prepare_matrix_with_mask( version,ec_level, mask ) 1087 | local size 1088 | local tab_x = {} 1089 | 1090 | size = version * 4 + 17 1091 | for i=1,size do 1092 | tab_x[i]={} 1093 | for j=1,size do 1094 | tab_x[i][j] = 0 1095 | end 1096 | end 1097 | add_position_detection_patterns(tab_x) 1098 | add_timing_pattern(tab_x) 1099 | add_version_information(tab_x,version) 1100 | 1101 | -- black pixel above lower left position detection pattern 1102 | tab_x[9][size - 7] = 2 1103 | add_alignment_pattern(tab_x) 1104 | add_typeinfo_to_matrix(tab_x,ec_level, mask) 1105 | return tab_x 1106 | end 1107 | 1108 | --- Finally we come to the place where we need to put the calculated data (remember step 3?) into the qr code. 1109 | --- We do this for each mask. BTW speaking of mask, this is what we find in the spec: 1110 | --- Mask Pattern Reference Condition 1111 | --- 000 (y + x) mod 2 = 0 1112 | --- 001 y mod 2 = 0 1113 | --- 010 x mod 3 = 0 1114 | --- 011 (y + x) mod 3 = 0 1115 | --- 100 ((y div 2) + (x div 3)) mod 2 = 0 1116 | --- 101 (y x) mod 2 + (y x) mod 3 = 0 1117 | --- 110 ((y x) mod 2 + (y x) mod 3) mod 2 = 0 1118 | --- 111 ((y x) mod 3 + (y+x) mod 2) mod 2 = 0 1119 | 1120 | -- Return 1 (black) or -1 (blank) depending on the mask, value and position. 1121 | -- Parameter mask is 0-7 (-1 for 'no mask'). x and y are 1-based coordinates, 1122 | -- 1,1 = upper left. tonumber(value) must be 0 or 1. 1123 | local function get_pixel_with_mask( mask, x,y,value ) 1124 | x = x - 1 1125 | y = y - 1 1126 | local invert = false 1127 | -- test purpose only: 1128 | if mask == -1 then 1129 | -- ignore, no masking applied 1130 | elseif mask == 0 then 1131 | if math.fmod(x + y,2) == 0 then invert = true end 1132 | elseif mask == 1 then 1133 | if math.fmod(y,2) == 0 then invert = true end 1134 | elseif mask == 2 then 1135 | if math.fmod(x,3) == 0 then invert = true end 1136 | elseif mask == 3 then 1137 | if math.fmod(x + y,3) == 0 then invert = true end 1138 | elseif mask == 4 then 1139 | if math.fmod(math.floor(y / 2) + math.floor(x / 3),2) == 0 then invert = true end 1140 | elseif mask == 5 then 1141 | if math.fmod(x * y,2) + math.fmod(x * y,3) == 0 then invert = true end 1142 | elseif mask == 6 then 1143 | if math.fmod(math.fmod(x * y,2) + math.fmod(x * y,3),2) == 0 then invert = true end 1144 | elseif mask == 7 then 1145 | if math.fmod(math.fmod(x * y,3) + math.fmod(x + y,2),2) == 0 then invert = true end 1146 | else 1147 | assert(false,"This can't happen (mask must be <= 7)") 1148 | end 1149 | if invert then 1150 | -- value = 1? -> -1, value = 0? -> 1 1151 | return 1 - 2 * tonumber(value) 1152 | else 1153 | -- value = 1? -> 1, value = 0? -> -1 1154 | return -1 + 2*tonumber(value) 1155 | end 1156 | end 1157 | 1158 | 1159 | -- We need up to 8 positions in the matrix. Only the last few bits may be less then 8. 1160 | -- The function returns a table of (up to) 8 entries with subtables where 1161 | -- the x coordinate is the first and the y coordinate is the second entry. 1162 | local function get_next_free_positions(matrix,x,y,dir,byte) 1163 | local ret = {} 1164 | local count = 1 1165 | local mode = "right" 1166 | while count <= #byte do 1167 | if mode == "right" and matrix[x][y] == 0 then 1168 | ret[#ret + 1] = {x,y} 1169 | mode = "left" 1170 | count = count + 1 1171 | elseif mode == "left" and matrix[x-1][y] == 0 then 1172 | ret[#ret + 1] = {x-1,y} 1173 | mode = "right" 1174 | count = count + 1 1175 | if dir == "up" then 1176 | y = y - 1 1177 | else 1178 | y = y + 1 1179 | end 1180 | elseif mode == "right" and matrix[x-1][y] == 0 then 1181 | ret[#ret + 1] = {x-1,y} 1182 | count = count + 1 1183 | if dir == "up" then 1184 | y = y - 1 1185 | else 1186 | y = y + 1 1187 | end 1188 | else 1189 | if dir == "up" then 1190 | y = y - 1 1191 | else 1192 | y = y + 1 1193 | end 1194 | end 1195 | if y < 1 or y > #matrix then 1196 | x = x - 2 1197 | -- don't overwrite the timing pattern 1198 | if x == 7 then x = 6 end 1199 | if dir == "up" then 1200 | dir = "down" 1201 | y = 1 1202 | else 1203 | dir = "up" 1204 | y = #matrix 1205 | end 1206 | end 1207 | end 1208 | return ret,x,y,dir 1209 | end 1210 | 1211 | -- Add the data string (0's and 1's) to the matrix for the given mask. 1212 | local function add_data_to_matrix(matrix,data,mask) 1213 | size = #matrix 1214 | local x,y,positions 1215 | local _x,_y,m 1216 | local dir = "up" 1217 | local byte_number = 0 1218 | x,y = size,size 1219 | string.gsub(data,".?.?.?.?.?.?.?.?",function ( byte ) 1220 | byte_number = byte_number + 1 1221 | positions,x,y,dir = get_next_free_positions(matrix,x,y,dir,byte,mask) 1222 | for i=1,#byte do 1223 | _x = positions[i][1] 1224 | _y = positions[i][2] 1225 | m = get_pixel_with_mask(mask,_x,_y,string.sub(byte,i,i)) 1226 | if debugging then 1227 | matrix[_x][_y] = m * (i + 10) 1228 | else 1229 | matrix[_x][_y] = m 1230 | end 1231 | end 1232 | end) 1233 | end 1234 | 1235 | 1236 | --- The total penalty of the matrix is the sum of four steps. The following steps are taken into account: 1237 | --- 1238 | --- 1. Adjacent modules in row/column in same color 1239 | --- 1. Block of modules in same color 1240 | --- 1. 1:1:3:1:1 ratio (dark:light:dark:light:dark) pattern in row/column 1241 | --- 1. Proportion of dark modules in entire symbol 1242 | --- 1243 | --- This all is done to avoid bad patterns in the code that prevent the scanner from 1244 | --- reading the code. 1245 | -- Return the penalty for the given matrix 1246 | local function calculate_penalty(matrix) 1247 | local penalty1, penalty2, penalty3, penalty4 = 0,0,0,0 1248 | local size = #matrix 1249 | -- this is for penalty 4 1250 | local number_of_dark_cells = 0 1251 | 1252 | -- 1: Adjacent modules in row/column in same color 1253 | -- -------------------------------------------- 1254 | -- No. of modules = (5+i) -> 3 + i 1255 | local last_bit_blank -- < 0: blank, > 0: black 1256 | local is_blank 1257 | local number_of_consecutive_bits 1258 | -- first: vertical 1259 | for x=1,size do 1260 | number_of_consecutive_bits = 0 1261 | last_bit_blank = nil 1262 | for y = 1,size do 1263 | if matrix[x][y] > 0 then 1264 | -- small optimization: this is for penalty 4 1265 | number_of_dark_cells = number_of_dark_cells + 1 1266 | is_blank = false 1267 | else 1268 | is_blank = true 1269 | end 1270 | is_blank = matrix[x][y] < 0 1271 | if last_bit_blank == is_blank then 1272 | number_of_consecutive_bits = number_of_consecutive_bits + 1 1273 | else 1274 | if number_of_consecutive_bits >= 5 then 1275 | penalty1 = penalty1 + number_of_consecutive_bits - 2 1276 | end 1277 | number_of_consecutive_bits = 1 1278 | end 1279 | last_bit_blank = is_blank 1280 | end 1281 | if number_of_consecutive_bits >= 5 then 1282 | penalty1 = penalty1 + number_of_consecutive_bits - 2 1283 | end 1284 | end 1285 | -- now horizontal 1286 | for y=1,size do 1287 | number_of_consecutive_bits = 0 1288 | last_bit_blank = nil 1289 | for x = 1,size do 1290 | is_blank = matrix[x][y] < 0 1291 | if last_bit_blank == is_blank then 1292 | number_of_consecutive_bits = number_of_consecutive_bits + 1 1293 | else 1294 | if number_of_consecutive_bits >= 5 then 1295 | penalty1 = penalty1 + number_of_consecutive_bits - 2 1296 | end 1297 | number_of_consecutive_bits = 1 1298 | end 1299 | last_bit_blank = is_blank 1300 | end 1301 | if number_of_consecutive_bits >= 5 then 1302 | penalty1 = penalty1 + number_of_consecutive_bits - 2 1303 | end 1304 | end 1305 | for x=1,size do 1306 | for y=1,size do 1307 | -- 2: Block of modules in same color 1308 | -- ----------------------------------- 1309 | -- Blocksize = m × n -> 3 × (m-1) × (n-1) 1310 | if (y < size - 1) and ( x < size - 1) and ( (matrix[x][y] < 0 and matrix[x+1][y] < 0 and matrix[x][y+1] < 0 and matrix[x+1][y+1] < 0) or (matrix[x][y] > 0 and matrix[x+1][y] > 0 and matrix[x][y+1] > 0 and matrix[x+1][y+1] > 0) ) then 1311 | penalty2 = penalty2 + 3 1312 | end 1313 | 1314 | -- 3: 1:1:3:1:1 ratio (dark:light:dark:light:dark) pattern in row/column 1315 | -- ------------------------------------------------------------------ 1316 | -- Gives 40 points each 1317 | -- 1318 | -- I have no idea why we need the extra 0000 on left or right side. The spec doesn't mention it, 1319 | -- other sources do mention it. This is heavily inspired by zxing. 1320 | if (y + 6 < size and 1321 | matrix[x][y] > 0 and 1322 | matrix[x][y + 1] < 0 and 1323 | matrix[x][y + 2] > 0 and 1324 | matrix[x][y + 3] > 0 and 1325 | matrix[x][y + 4] > 0 and 1326 | matrix[x][y + 5] < 0 and 1327 | matrix[x][y + 6] > 0 and 1328 | ((y + 10 < size and 1329 | matrix[x][y + 7] < 0 and 1330 | matrix[x][y + 8] < 0 and 1331 | matrix[x][y + 9] < 0 and 1332 | matrix[x][y + 10] < 0) or 1333 | (y - 4 >= 1 and 1334 | matrix[x][y - 1] < 0 and 1335 | matrix[x][y - 2] < 0 and 1336 | matrix[x][y - 3] < 0 and 1337 | matrix[x][y - 4] < 0))) then penalty3 = penalty3 + 40 end 1338 | if (x + 6 <= size and 1339 | matrix[x][y] > 0 and 1340 | matrix[x + 1][y] < 0 and 1341 | matrix[x + 2][y] > 0 and 1342 | matrix[x + 3][y] > 0 and 1343 | matrix[x + 4][y] > 0 and 1344 | matrix[x + 5][y] < 0 and 1345 | matrix[x + 6][y] > 0 and 1346 | ((x + 10 <= size and 1347 | matrix[x + 7][y] < 0 and 1348 | matrix[x + 8][y] < 0 and 1349 | matrix[x + 9][y] < 0 and 1350 | matrix[x + 10][y] < 0) or 1351 | (x - 4 >= 1 and 1352 | matrix[x - 1][y] < 0 and 1353 | matrix[x - 2][y] < 0 and 1354 | matrix[x - 3][y] < 0 and 1355 | matrix[x - 4][y] < 0))) then penalty3 = penalty3 + 40 end 1356 | end 1357 | end 1358 | -- 4: Proportion of dark modules in entire symbol 1359 | -- ---------------------------------------------- 1360 | -- 50 ± (5 × k)% to 50 ± (5 × (k + 1))% -> 10 × k 1361 | local dark_ratio = number_of_dark_cells / ( size * size ) 1362 | penalty4 = math.floor(math.abs(dark_ratio * 100 - 50)) * 2 1363 | return penalty1 + penalty2 + penalty3 + penalty4 1364 | end 1365 | 1366 | -- Create a matrix for the given parameters and calculate the penalty score. 1367 | -- Return both (matrix and penalty) 1368 | local function get_matrix_and_penalty(version,ec_level,data,mask) 1369 | local tab = prepare_matrix_with_mask(version,ec_level,mask) 1370 | add_data_to_matrix(tab,data,mask) 1371 | local penalty = calculate_penalty(tab) 1372 | return tab, penalty 1373 | end 1374 | 1375 | -- Return the matrix with the smallest penalty. To to this 1376 | -- we try out the matrix for all 8 masks and determine the 1377 | -- penalty (score) each. 1378 | local function get_matrix_with_lowest_penalty(version,ec_level,data) 1379 | local tab, penalty 1380 | local tab_min_penalty, min_penalty 1381 | 1382 | -- try masks 0-7 1383 | tab_min_penalty, min_penalty = get_matrix_and_penalty(version,ec_level,data,0) 1384 | for i=1,7 do 1385 | tab, penalty = get_matrix_and_penalty(version,ec_level,data,i) 1386 | if penalty < min_penalty then 1387 | tab_min_penalty = tab 1388 | min_penalty = penalty 1389 | end 1390 | end 1391 | return tab_min_penalty 1392 | end 1393 | 1394 | --- The main function. We connect everything together. Remember from above: 1395 | --- 1396 | --- 1. Determine version, ec level and mode (=encoding) for codeword 1397 | --- 1. Encode data 1398 | --- 1. Arrange data and calculate error correction code 1399 | --- 1. Generate 8 matrices with different masks and calculate the penalty 1400 | --- 1. Return qrcode with least penalty 1401 | -- If ec_level or mode is given, use the ones for generating the qrcode. (mode is not implemented yet) 1402 | local function qrcode( str, ec_level, mode ) 1403 | local arranged_data, version, data_raw, mode, len_bitstring 1404 | version, ec_level, data_raw, mode, len_bitstring = get_version_eclevel_mode_bistringlength(str,ec_level) 1405 | data_raw = data_raw .. len_bitstring 1406 | data_raw = data_raw .. encode_data(str,mode) 1407 | data_raw = add_pad_data(version,ec_level,data_raw) 1408 | arranged_data = arrange_codewords_and_calculate_ec(version,ec_level,data_raw) 1409 | if math.fmod(#arranged_data,8) ~= 0 then 1410 | return false, string.format("Arranged data %% 8 != 0: data length = %d, mod 8 = %d",#arranged_data, math.fmod(#arranged_data,8)) 1411 | end 1412 | arranged_data = arranged_data .. string.rep("0",remainder[version]) 1413 | local tab = get_matrix_with_lowest_penalty(version,ec_level,arranged_data) 1414 | return true, tab 1415 | end 1416 | 1417 | 1418 | _M.testing = function() 1419 | return { 1420 | encode_string_numeric = encode_string_numeric, 1421 | encode_string_ascii = encode_string_ascii, 1422 | qrcode = qrcode, 1423 | binary = binary, 1424 | get_mode = get_mode, 1425 | get_length = get_length, 1426 | add_pad_data = add_pad_data, 1427 | get_generator_polynominal_adjusted = get_generator_polynominal_adjusted, 1428 | get_pixel_with_mask = get_pixel_with_mask, 1429 | get_version_eclevel_mode_bistringlength = get_version_eclevel_mode_bistringlength, 1430 | remainder = remainder, 1431 | --get_capacity_remainder = get_capacity_remainder, 1432 | arrange_codewords_and_calculate_ec = arrange_codewords_and_calculate_ec, 1433 | calculate_error_correction = calculate_error_correction, 1434 | convert_bitstring_to_bytes = convert_bitstring_to_bytes, 1435 | bit_xor = bit_xor, 1436 | } 1437 | end 1438 | 1439 | _M.test = function() 1440 | function err( ... ) 1441 | print(string.format(...)) 1442 | end 1443 | 1444 | local failed = false 1445 | function assert_equal( a,b,func ) 1446 | if a ~= b then 1447 | err("Assertion failed: %s: %q is not equal to %q",func,tostring(a),tostring(b)) 1448 | failed = true 1449 | end 1450 | end 1451 | 1452 | local qrcode = _M.testing() 1453 | local tab 1454 | str = "HELLO WORLD" 1455 | assert_equal(qrcode.get_mode("0101"), 1,"get_encoding_byte 1") 1456 | assert_equal(qrcode.get_mode(str), 2,"get_encoding_byte 2") 1457 | assert_equal(qrcode.get_mode("0-9A-Z $%*./:+-"),2,"get_encoding_byte 3") 1458 | assert_equal(qrcode.get_mode("foär"), 4,"get_encoding_byte 4") 1459 | assert_equal(qrcode.get_length(str,1,2),"000001011","get_length") 1460 | assert_equal(qrcode.binary(5,10),"0000000101","binary()") 1461 | assert_equal(qrcode.binary(779,11),"01100001011","binary()") 1462 | assert_equal(qrcode.add_pad_data(1,3,"0010101"),"00101010000000001110110000010001111011000001000111101100000100011110110000010001111011000001000111101100","pad_data") 1463 | 1464 | tab = qrcode.get_generator_polynominal_adjusted(13,25) 1465 | assert_equal(tab[1],0,"get_generator_polynominal_adjusted 0") 1466 | assert_equal(tab[24],74,"get_generator_polynominal_adjusted 24") 1467 | assert_equal(tab[25],0,"get_generator_polynominal_adjusted 25") 1468 | tab = qrcode.get_generator_polynominal_adjusted(13,24) 1469 | assert_equal(tab[1],0,"get_generator_polynominal_adjusted 0") 1470 | assert_equal(tab[23],74,"get_generator_polynominal_adjusted 23") 1471 | assert_equal(tab[24],0,"get_generator_polynominal_adjusted 24") 1472 | 1473 | tab = qrcode.convert_bitstring_to_bytes("00100000010110110000101101111000110100010111001011011100010011010100001101000000111011000001000111101100") 1474 | assert_equal(tab[1],32,"convert_bitstring_to_bytes") 1475 | assert_equal(qrcode.bit_xor(141,43), 166,"bit_xor") 1476 | assert_equal(qrcode.bit_xor(179,0), 179,"bit_xor") 1477 | 1478 | -- local hello_world_msg_with_ec = "0010000001011011000010110111100011010001011100101101110001001101010000110100000011101100000100011110110010101000010010000001011001010010110110010011011010011100000000000010111000001111101101000111101000010000" 1479 | 1480 | assert_equal(qrcode.get_pixel_with_mask(0,21,21,1),-1,"get_pixel_with_mask 1") 1481 | assert_equal(qrcode.get_pixel_with_mask(0,1,1,1),-1,"get_pixel_with_mask 2") 1482 | local a,b,c,d,e = qrcode.get_version_eclevel_mode_bistringlength(str) 1483 | assert_equal(a,1,"get_version_eclevel_mode_bistringlength 1") 1484 | assert_equal(b,3,"get_version_eclevel_mode_bistringlength 2") 1485 | assert_equal(c,"0010","get_version_eclevel_mode_bistringlength 3") 1486 | assert_equal(d,2,"get_version_eclevel_mode_bistringlength 4") 1487 | assert_equal(e,"000001011","get_version_eclevel_mode_bistringlength 5") 1488 | 1489 | assert_equal(qrcode.encode_string_numeric("01234567"),"000000110001010110011000011","encode string numeric") 1490 | assert_equal(qrcode.encode_string_ascii(str),"0110000101101111000110100010111001011011100010011010100001101","encode string ascii") 1491 | assert_equal(qrcode.remainder[40],0,"get_remainder") 1492 | assert_equal(qrcode.remainder[2],7,"get_remainder") 1493 | 1494 | 1495 | ------------------- 1496 | -- Error correction 1497 | ------------------- 1498 | local data = {32, 234, 187, 136, 103, 116, 252, 228, 127, 141, 73, 236, 12, 206, 138, 7, 230, 101, 30, 91, 152, 80, 0, 236, 17, 236, 17, 236} 1499 | local ec_expected = {73, 31, 138, 44, 37, 176, 170, 36, 254, 246, 191, 187, 13, 137, 84, 63} 1500 | local ec = qrcode.calculate_error_correction(data,16) 1501 | for i=1,#ec_expected do 1502 | assert_equal(ec_expected[i],ec[i],string.format("calculate_error_correction %d",i)) 1503 | end 1504 | data = {32, 234, 187, 136, 103, 116, 252, 228, 127, 141, 73, 236, 12, 206, 138, 7, 230, 101, 30, 91, 152, 80, 0, 236, 17, 236, 17, 236, 17, 236, 17, 236, 17, 236} 1505 | ec_expected = {66, 146, 126, 122, 79, 146, 2, 105, 180, 35} 1506 | local ec = qrcode.calculate_error_correction(data,10) 1507 | for i=1,#ec_expected do 1508 | assert_equal(ec_expected[i],ec[i],string.format("calculate_error_correction %d",i)) 1509 | end 1510 | data = {32, 83, 7, 120, 209, 114, 215, 60, 224} 1511 | ec_expected = {123, 120, 222, 125, 116, 92, 144, 245, 58, 73, 104, 30, 108, 0, 30, 166, 152} 1512 | local ec = qrcode.calculate_error_correction(data,17) 1513 | for i=1,#ec_expected do 1514 | assert_equal(ec_expected[i],ec[i],string.format("calculate_error_correction %d",i)) 1515 | end 1516 | data = {32,83,7,120,209,114,215,60,224,236,17} 1517 | ec_expected = {3, 67, 244, 57, 183, 14, 171, 101, 213, 52, 148, 3, 144, 148, 6, 155, 3, 252, 228, 100, 11, 56} 1518 | local ec = qrcode.calculate_error_correction(data,22) 1519 | for i=1,#ec_expected do 1520 | assert_equal(ec_expected[i],ec[i],string.format("calculate_error_correction %d",i)) 1521 | end 1522 | data = {236,17,236,17,236, 17,236, 17,236, 17,236} 1523 | ec_expected = {171, 165, 230, 109, 241, 45, 198, 125, 213, 84, 88, 187, 89, 61, 220, 255, 150, 75, 113, 77, 147, 164} 1524 | local ec = qrcode.calculate_error_correction(data,22) 1525 | for i=1,#ec_expected do 1526 | assert_equal(ec_expected[i],ec[i],string.format("calculate_error_correction %d",i)) 1527 | end 1528 | data = {17,236, 17,236, 17,236,17,236, 17,236, 17,236} 1529 | ec_expected = {23, 115, 68, 245, 125, 66, 203, 235, 85, 88, 174, 178, 229, 181, 118, 148, 44, 175, 213, 243, 27, 215} 1530 | local ec = qrcode.calculate_error_correction(data,22) 1531 | for i=1,#ec_expected do 1532 | assert_equal(ec_expected[i],ec[i],string.format("calculate_error_correction %d",i)) 1533 | end 1534 | 1535 | -- "HALLO WELT" in alphanumeric, code 5-H 1536 | data = { 32,83,7,120,209,114,215,60,224,236,17,236,17,236,17,236, 17,236, 17,236, 17,236, 17, 236, 17,236, 17,236, 17,236, 17,236, 17,236, 17, 236, 17,236, 17,236, 17,236, 17,236, 17,236} 1537 | message_expected = {32, 236, 17, 17, 83, 17, 236, 236, 7, 236, 17, 17, 120, 17, 236, 236, 209, 236, 17, 17, 114, 17, 236, 236, 215, 236, 17, 17, 60, 17, 236, 236, 224, 236, 17, 17, 236, 17, 236, 236, 17, 236, 17, 17, 236, 236, 3, 171, 23, 23, 67, 165, 115, 115, 244, 230, 68, 68, 57, 109, 245, 245, 183, 241, 125, 125, 14, 45, 66, 66, 171, 198, 203, 203, 101, 125, 235, 235, 213, 213, 85, 85, 52, 84, 88, 88, 148, 88, 174, 174, 3, 187, 178, 178, 144, 89, 229, 229, 148, 61, 181, 181, 6, 220, 118, 118, 155, 255, 148, 148, 3, 150, 44, 44, 252, 75, 175, 175, 228, 113, 213, 213, 100, 77, 243, 243, 11, 147, 27, 27, 56, 164, 215, 215} 1538 | tmp = qrcode.arrange_codewords_and_calculate_ec(5,4,data) 1539 | message = qrcode.convert_bitstring_to_bytes(tmp) 1540 | for i=1,#message do 1541 | assert_equal(message_expected[i],message[i],string.format("arrange_codewords_and_calculate_ec %d",i)) 1542 | end 1543 | 1544 | --print("Tests end here") 1545 | if failed then 1546 | error("Some tests failed, see above") 1547 | else --Fuxoft render tests 1548 | local opts = assert(_M.opts) 1549 | _M.init({character = "X", qr_doublewidth = true}) 1550 | local pkey = "L4DDkHFfLaRfRuHLf2xNcVyytugJ6bVkvrxxECDpTajDLJA4mDG7" 1551 | assert(sha256(_M.render(pkey, 0)) == "d44e5cbaf7ee0e9ad1e34b48fd435a40f586ca4af18d59ef42f4f2992fae64f5", sha256(_M.render(pkey, 0))) 1552 | _M.init({qr_invert=true, qr_halfheight=true}) 1553 | assert(sha256(_M.render(pkey, 3)) == "1562cc34d97e1cbb362ec86b65d75cc5658b5fefeefe033ba3f6637b426548a2", sha256(_M.render(pkey, 3))) 1554 | _M.opts = opts --Restore the old options values 1555 | end 1556 | end 1557 | 1558 | _M.qrcode = qrcode 1559 | 1560 | local function pad(tab, num) 1561 | local function copy(lst) 1562 | local cp = {} 1563 | for i, num in ipairs(lst) do 1564 | cp[i] = num 1565 | end 1566 | return cp 1567 | end 1568 | 1569 | for rn, r in ipairs(tab) do 1570 | table.insert(r, num) 1571 | table.insert(r, 1, num) 1572 | end 1573 | local er = {} 1574 | for i = 1, #tab[1] do 1575 | table.insert(er, num) 1576 | end 1577 | table.insert(tab, copy(er)) 1578 | table.insert(tab, 1, copy(er)) 1579 | return tab 1580 | end 1581 | 1582 | _M.init = function(o) 1583 | _M.opts = {} 1584 | opts = _M.opts 1585 | 1586 | if o.qr_invert then 1587 | opts.invert = true 1588 | end 1589 | 1590 | if o.qr_halfheight then 1591 | opts.halfheight = true 1592 | return 1593 | end 1594 | 1595 | if o.qr_character then 1596 | opts.character = o.qr_character 1597 | else 1598 | opts.character = "\226\150\136" 1599 | end 1600 | 1601 | if o.qr_doublewidth then 1602 | opts.doublewidth = true 1603 | end 1604 | end 1605 | 1606 | _M.render = function(data, leftmargin) 1607 | local ok, ret = _M.qrcode(data) 1608 | if not ok then 1609 | error(result) 1610 | end 1611 | 1612 | for i = 1, #ret do --Mirror it 1613 | for j = 1, i do 1614 | ret[i][j], ret[j][i] = ret[j][i], ret[i][j] 1615 | end 1616 | end 1617 | 1618 | ret = pad(ret, -2) 1619 | ret = pad(ret, -2) 1620 | ret = pad(ret, -2) 1621 | ret = pad(ret, -2) 1622 | 1623 | if not leftmargin then 1624 | leftmargin = 0 1625 | end 1626 | local margintxt = string.rep(" ", leftmargin) 1627 | if _M.opts.halfheight then 1628 | return _M.render_halfchars(ret, margintxt) 1629 | end 1630 | local empty, full = " ", assert(_M.opts.character) 1631 | if _M.opts.invert then 1632 | empty, full = full, empty 1633 | end 1634 | 1635 | if _M.opts.doublewidth then 1636 | empty = empty..empty 1637 | full = full..full 1638 | end 1639 | 1640 | local result = {} 1641 | for rn, r in ipairs(ret) do 1642 | local row = {margintxt} 1643 | for i, num in ipairs(r) do 1644 | if num > 0 then 1645 | table.insert(row, full) 1646 | else 1647 | table.insert(row, empty) 1648 | end 1649 | end 1650 | table.insert(result, table.concat(row)) 1651 | end 1652 | return table.concat(result, "\n") 1653 | end 1654 | 1655 | _M.render_halfchars = function(ret, margintxt) 1656 | assert(margintxt) 1657 | local upper = "▀" 1658 | local lower = "▄" 1659 | local full = "█" 1660 | local empty = " " 1661 | 1662 | if _M.opts.invert then 1663 | empty, full, upper, lower = full, empty, lower, upper 1664 | end 1665 | 1666 | if #ret % 2 ~= 0 then 1667 | table.insert(ret, ret[1]) 1668 | end 1669 | local result = {} 1670 | for rn = 1, #ret, 2 do 1671 | local row = {margintxt} 1672 | for i, num in ipairs(ret[rn]) do 1673 | local chr = "?" 1674 | if ret[rn+1][i] > 0 then 1675 | if num > 0 then 1676 | chr = full 1677 | else 1678 | chr = lower 1679 | end 1680 | else 1681 | if num > 0 then 1682 | chr = upper 1683 | else 1684 | chr = empty 1685 | end 1686 | end 1687 | table.insert(row, assert(chr)) 1688 | end 1689 | table.insert(result, table.concat(row)) 1690 | end 1691 | return table.concat(result, "\n") 1692 | end 1693 | 1694 | _M.init({}) 1695 | return _M 1696 | end 1697 | 1698 | local function load_bignum() 1699 | 1700 | -- BigNum module 1701 | local _M = {} 1702 | local bpd = 30 1703 | local maxd = bit.rol(1,bpd) - 1 1704 | --print (bit.tohex(maxd)) 1705 | 1706 | local function normalize(self) 1707 | while #self > 1 and self[#self] == 0 do 1708 | table.remove(self) 1709 | end 1710 | --print("normalized", table.concat(self, ",")) 1711 | return self 1712 | end 1713 | 1714 | local mt = {} 1715 | 1716 | local function check_bignum(n) 1717 | if not(getmetatable(n) == mt) then 1718 | error (tostring(n).." is not a bignum") 1719 | end 1720 | end 1721 | 1722 | mt.__tostring = function(self, padding) 1723 | --print(">", self[1], self.negative, "<") 1724 | local cr = coroutine.create( function() 1725 | for d = 1, #self do 1726 | local digit, last = self[d], d==#self 1727 | for b = 1, bpd do 1728 | coroutine.yield (bit.band(digit, 1)) 1729 | digit = bit.rshift(digit, 1) 1730 | if last and digit == 0 then 1731 | while true do 1732 | coroutine.yield(false) 1733 | end 1734 | end 1735 | end 1736 | end 1737 | end) 1738 | 1739 | local result = {} 1740 | local function get() 1741 | local ok, got = coroutine.resume(cr) 1742 | if not ok then 1743 | error(got) 1744 | end 1745 | return got 1746 | end 1747 | while true do 1748 | local d = get() 1749 | if not d then 1750 | break 1751 | end 1752 | d = d + 2 * (get() or 0) + 4 * (get() or 0) + 8 * (get() or 0) 1753 | table.insert(result, 1, string.format("%x", d)) 1754 | end 1755 | if not next(result) then 1756 | result = {"0"} 1757 | end 1758 | if padding then 1759 | while #result < padding do 1760 | table.insert(result, 1, "0") 1761 | end 1762 | end 1763 | table.insert(result, 1,"0x") 1764 | if self.negative then 1765 | table.insert(result, 1, "-") 1766 | end 1767 | return (table.concat(result)) 1768 | end 1769 | 1770 | mt.__eq = function(self, oth) 1771 | check_bignum(oth) 1772 | if self.negative ~= oth.negative then 1773 | return false 1774 | end 1775 | if #self ~= #oth then 1776 | return false 1777 | end 1778 | for i, d in ipairs(self) do 1779 | if d ~= oth[i] then 1780 | return false 1781 | end 1782 | end 1783 | return true 1784 | end 1785 | 1786 | mt.__lt = function(self, oth) 1787 | check_bignum(oth) 1788 | if self.negative ~= oth.negative then 1789 | return not oth.negative 1790 | end 1791 | if self == oth then 1792 | return false 1793 | end 1794 | 1795 | local function lt0(n1, n2) --assert not equal, ignore sign 1796 | if #n1 ~= #n2 then 1797 | return #n1 < #n2 1798 | end 1799 | for i = #n1, 1, -1 do 1800 | if n1[i] ~= n2[i] then 1801 | return n1[i] < n2[i] 1802 | end 1803 | end 1804 | error("Shouldn't be equal") 1805 | end 1806 | 1807 | if self.negative then 1808 | return lt0(oth, self) 1809 | else 1810 | return lt0(self, oth) 1811 | end 1812 | end 1813 | 1814 | mt.__le = function(self, oth) 1815 | check_bignum(oth) 1816 | if self == oth then 1817 | return true 1818 | end 1819 | return self < oth 1820 | end 1821 | 1822 | _M.copy = function(self) 1823 | check_bignum(self) 1824 | local c = {} 1825 | for k, v in pairs(self) do 1826 | c[k] = v 1827 | end 1828 | setmetatable(c, mt) 1829 | return c 1830 | end 1831 | 1832 | _M.to_dwords = function(self, dw) 1833 | self = _M.copy(self) 1834 | local dwords = {} 1835 | for i = 1, dw do 1836 | local dword = bit.band(0xffff, self[1]) 1837 | _M.rshift(self, 16) 1838 | dword = bit.bor(dword, bit.lshift(bit.band(0xffff, self[1]), 16)) 1839 | _M.rshift(self, 16) 1840 | table.insert(dwords, 1, dword) 1841 | end 1842 | return dwords 1843 | end 1844 | 1845 | mt.__unm = function(self) 1846 | local x = _M.copy(self) 1847 | if x ~= _M.zero then 1848 | x.negative = not self.negative 1849 | end 1850 | --print("negated", self, x) 1851 | return x 1852 | end 1853 | 1854 | mt.__add = function(self, oth) 1855 | --print("add", self, oth) 1856 | 1857 | check_bignum(oth) 1858 | if oth == _M.zero then 1859 | return self 1860 | end 1861 | 1862 | if self == _M.zero then 1863 | return oth 1864 | end 1865 | 1866 | if self == -oth then 1867 | return _M.zero 1868 | end 1869 | 1870 | if self.negative ~= oth.negative then 1871 | if oth.negative then 1872 | return self - (-oth) 1873 | else 1874 | return - (-self - (oth)) 1875 | end 1876 | end 1877 | --Both have same sign 1878 | if #self < #oth then 1879 | self, oth = oth, self 1880 | end 1881 | local result = {negative = self.negative} 1882 | setmetatable (result, mt) 1883 | local carry = 0 1884 | for i = 1, #self do 1885 | local sum = self[i] + (oth[i] or 0) + carry 1886 | result[i] = bit.band(maxd, sum) 1887 | if sum > maxd then 1888 | carry = 1 1889 | else 1890 | carry = 0 1891 | end 1892 | end 1893 | if carry == 1 then 1894 | table.insert(result, 1) 1895 | end 1896 | return result 1897 | end 1898 | 1899 | mt.__mul = function(self, oth) 1900 | check_bignum(oth) 1901 | 1902 | local zero, one = _M.zero, _M.new(1) 1903 | if self == one then 1904 | return oth 1905 | end 1906 | 1907 | if oth == one then 1908 | return self 1909 | end 1910 | 1911 | if self == zero or oth == zero then 1912 | return zero 1913 | end 1914 | 1915 | local acc = zero 1916 | local m1, m2 = _M.abs(self), _M.abs(oth) 1917 | if m1 < m2 then 1918 | m1, m2 = m2, m1 1919 | end 1920 | --m1 >= m2 1921 | m2 = _M.copy(m2) --Will be modified (shifted) 1922 | while m2 ~= zero do 1923 | if _M.rshift(m2, 1) ~= 0 then 1924 | acc = acc + m1 1925 | end 1926 | m1 = m1 + m1 1927 | end 1928 | acc.negative = self.negative ~= oth.negative 1929 | return acc 1930 | end 1931 | 1932 | _M.pow = function(x, y, p) --a la Python 1933 | local zero = _M.zero 1934 | local acc = _M.new(1) 1935 | local m1, m2 = _M.abs(x), _M.abs(y) 1936 | m2 = _M.copy(m2) --Will be modified (shifted) 1937 | assert(m2 > zero) -- ? TODO ? 1938 | while m2 ~= zero do 1939 | if _M.rshift(m2, 1) ~= 0 then 1940 | acc = acc * m1 1941 | if p then 1942 | acc = _M.mod(acc, p) 1943 | end 1944 | end 1945 | m1 = m1 * m1 1946 | if p then 1947 | m1 = _M.mod(m1, p) 1948 | end 1949 | --print(m1, acc, p) 1950 | end 1951 | return acc 1952 | end 1953 | 1954 | mt.__sub = function(self, oth) 1955 | --print("sub", self, oth) 1956 | check_bignum(oth) 1957 | if self == oth then 1958 | return _M.zero 1959 | end 1960 | if oth == _M.zero then 1961 | return self 1962 | end 1963 | if self == _M.zero then 1964 | return -oth 1965 | end 1966 | 1967 | if self.negative ~= oth.negative then 1968 | if oth.negative then 1969 | return self + (-oth) 1970 | else 1971 | return -(-self + oth) 1972 | end 1973 | end 1974 | 1975 | --assume same signs 1976 | 1977 | if self.negative then 1978 | if self > oth then 1979 | return (-oth - (-self)) 1980 | end 1981 | else 1982 | if self < oth then 1983 | return -(oth - self) 1984 | end 1985 | end 1986 | 1987 | local result = {negative = self.negative} 1988 | setmetatable(result, mt) 1989 | 1990 | local carry = 0 1991 | 1992 | for i = 1, #self do 1993 | sum = self[i] - (oth[i] or 0) - carry 1994 | if sum < 0 then 1995 | sum = sum + maxd + 1 1996 | carry = 1 1997 | else 1998 | carry = 0 1999 | end 2000 | result[i] = sum 2001 | end 2002 | assert(carry == 0) 2003 | normalize(result) 2004 | return(result) 2005 | end 2006 | 2007 | _M.new = function(n) 2008 | if type(n) == "number" then 2009 | local int = n 2010 | local num = {math.abs(int)} 2011 | num.negative = int < 0 2012 | setmetatable(num, mt) 2013 | return num 2014 | elseif type(n) == "string" then -- "0xffff" 2015 | local num = _M.copy(_M.zero) --Needs copy because we modify it manually 2016 | local digits = n:match("0x(.+)") 2017 | for digit in digits:gmatch(".") do 2018 | num = num + num 2019 | num = num + num 2020 | num = num + num 2021 | num = num + num 2022 | local d = tonumber(digit, 16) 2023 | --print(d) 2024 | assert(d, "Invalid char: "..digit) 2025 | --print(num) 2026 | num[1] = bit.bor(num[1], d) 2027 | --print(num) 2028 | end 2029 | if n:match("^%-") then 2030 | num.negative = true 2031 | end 2032 | return num 2033 | else 2034 | error("Invalid number type") 2035 | end 2036 | end 2037 | 2038 | _M.padding = function(num, chrs) 2039 | return mt.__tostring(num, chrs) 2040 | end 2041 | 2042 | _M.rshift = function(num, x) --Right shift x bits IN PLACE and return the overflown bits (already shifted!) 2043 | check_bignum(num) 2044 | assert(x < bpd) 2045 | local mask = 2 ^ x - 1 2046 | local carry = 0 2047 | for i = #num, 1, -1 do 2048 | local bits = bit.band(num[i], mask) 2049 | num[i] = bit.bor(bit.rshift(num[i], x), carry) 2050 | carry = bit.lshift(bits, bpd - x) 2051 | end 2052 | normalize(num) 2053 | return carry 2054 | end 2055 | 2056 | _M.divmod = function(x, y, fl) -- fl == true -> mod only 2057 | fl = not fl 2058 | local one = _M.new(1) 2059 | if x.negative then 2060 | if y.negative then -- -x, -y 2061 | local d, m = _M.divmod0(-x, -y, fl) 2062 | return d, -m 2063 | else -- -x, +y 2064 | local d, m = _M.divmod0(-x, y, fl) 2065 | return -(d+one), y-m 2066 | end 2067 | else -- x > zero 2068 | if y.negative then -- +x, -y 2069 | local d, m = _M.divmod0(x, -y, fl) 2070 | return -(d+one), y + m 2071 | else -- +x, +y 2072 | local d, m = _M.divmod0(x, y, fl) 2073 | return d, m 2074 | end 2075 | end 2076 | end 2077 | 2078 | _M.mod = function(x, y) 2079 | local d, m = _M.divmod(x, y, true) 2080 | --print("mod", d, m) 2081 | return m 2082 | end 2083 | 2084 | --[[divmod: 2085 | 100, 3 = 33, 1 2086 | -100, -3 = 33, -1 2087 | -100, 3 = -34, 2 2088 | 100, -3 = -34, -2 2089 | ]] 2090 | 2091 | _M.divmod0 = function(x, y, divmod) 2092 | check_bignum(x) 2093 | check_bignum(y) 2094 | --assume positive x, y 2095 | assert(not x.negative) 2096 | assert(not y.negative) 2097 | local zero = _M.zero 2098 | assert(x >= zero) 2099 | assert(y > zero) 2100 | local one = _M.new(1) 2101 | if x < y then 2102 | return zero, x 2103 | end 2104 | if y == one then 2105 | return x, zero 2106 | end 2107 | assert(y > zero) 2108 | 2109 | local dm = zero 2110 | 2111 | local powers = {} 2112 | local pow = y 2113 | local ind = 0 2114 | repeat 2115 | ind = ind + 1 2116 | powers[ind] = pow 2117 | pow = pow + pow 2118 | until pow > x 2119 | for i = ind, 1, -1 do 2120 | if divmod then 2121 | dm = dm + dm 2122 | end 2123 | if powers[i] <= x then 2124 | x = x - powers[i] 2125 | if divmod then 2126 | dm = dm + one 2127 | end 2128 | end 2129 | end 2130 | return dm, x 2131 | end 2132 | 2133 | _M.zero = _M.new(0) 2134 | 2135 | _M.abs = function(num) 2136 | if num >= _M.zero then 2137 | return num 2138 | end 2139 | return -num 2140 | end 2141 | 2142 | _M.test = function() 2143 | assert(_M.new(-23) == _M.new(-23)) 2144 | assert(_M.new(-23) ~= _M.new(23)) 2145 | assert(_M.new(-23) == -_M.new(23)) 2146 | local sum = _M.zero 2147 | math.randomseed(1) 2148 | local iters = 20 2149 | for i = 1, iters do 2150 | local x = _M.new(math.random(maxd) - math.floor(maxd / 2)) 2151 | for i = 1, math.random(20) do 2152 | x = x + x - _M.new(math.random(9)) 2153 | end 2154 | if i <= iters / 2 then 2155 | -- print("+", sum, x) 2156 | sum = sum + x 2157 | else 2158 | -- print("-", sum, x) 2159 | sum = sum - x 2160 | end 2161 | --print("sum is", sum) 2162 | if i == iters / 2 then 2163 | math.randomseed(1) 2164 | end 2165 | end 2166 | assert(sum == _M.zero) 2167 | assert(tostring(_M.new("-0x1234567890abcdef")) == "-0x1234567890abcdef") 2168 | assert(_M.padding(_M.new("-0x12abc"),8) == "-0x00012abc") 2169 | assert(_M.new("0x123456789") * _M.new("-0xdeadbeef") == _M.new("-0xFD5BDEED363856E7")) 2170 | assert(_M.mod(_M.new("0x3b9ac9ff"), _M.new("0x3e7")) == _M.zero) 2171 | assert(_M.mod(_M.new("0x1234567890"), _M.new("0x6789")) == _M.new("0x59a6")) 2172 | for i, test in ipairs {{"0x64", "0x3", "0x21", "0x1"}, {"-0x64", "-0x3", "0x21", "-0x1"}, {"-0x64", "0x3", "-0x22", "0x2"}, {"0x64", "-0x3", "-0x22", "-0x2"}} do 2173 | local x, y, d0, m0 = _M.new(test[1]), _M.new(test[2]), _M.new(test[3]), _M.new(test[4]) 2174 | local d, m = _M.divmod(x,y) 2175 | --print(x, y, d0, m0) 2176 | --print(d, m) 2177 | assert(d == d0 and m == m0) 2178 | end 2179 | 2180 | --assert(_M.pow(_M.new("0x10"), _M.new("0x3"), _M.new("0xbeef")) == _M.new("0x1000")) 2181 | --assert(_M.pow(_M.new("0xabcdef"), _M.new("0x123456789"), _M.new("0x123456789abcdef")) == _M.new("0x2d357497e15f50")) 2182 | --print(_M.pow(_M.new("0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef"), _M.new("0x123456789123456789123456789123456789123456789123456789123456789123456789"), _M.new("0x123456789abcdef"))) 2183 | end 2184 | 2185 | return _M 2186 | end 2187 | 2188 | local pubkey_cache = {} 2189 | 2190 | local privkey_to_pubkey = function(secret0) 2191 | assert(#secret0 > 30) 2192 | if pubkey_cache[secret0] then 2193 | print("Retrieved cached BTC pubkey.") 2194 | return pubkey_cache[secret0] 2195 | end 2196 | local new = BIGNUM.new 2197 | local zero = BIGNUM.zero 2198 | local one = new(1) 2199 | local two = new(2) 2200 | local three = new(3) 2201 | local p = new("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F") 2202 | local g = {x=new("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"), y=new("0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8")} 2203 | local order = new("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141") 2204 | local secret = new(secret0) 2205 | 2206 | local function inverse_mod(a) 2207 | if a < zero or a >= p then 2208 | a = BIGNUM.mod(a, p) 2209 | end 2210 | local c, d, uc, vc, ud, vd = a, p, one, zero, zero, one 2211 | local q 2212 | while c ~= zero do 2213 | --print("call divmod", d, c) 2214 | local c0 = c 2215 | q, c = BIGNUM.divmod(d, c) 2216 | d = c0 2217 | --print("q c d", q, c, d) 2218 | uc, vc, ud, vd = ud - q * uc, vd - q * vc, uc, vc 2219 | end 2220 | --print("while ended") 2221 | --print("ud", ud) 2222 | local bool = ud > zero 2223 | if ud > zero then 2224 | return ud 2225 | end 2226 | return ud + p 2227 | end 2228 | 2229 | local function calc(self, top, bottom, other_x) 2230 | local l = BIGNUM.mod(top * inverse_mod(bottom), p) 2231 | local x3 = BIGNUM.mod(l * l - self.x - other_x, p) 2232 | return {x = x3, y = BIGNUM.mod(l * (self.x - x3) - self.y, p)} 2233 | end 2234 | 2235 | local function double(self) 2236 | if self == "inf" then 2237 | return self 2238 | end 2239 | return calc(self, three * self.x * self.x, two * self.y, self.x) 2240 | end 2241 | 2242 | local function add(self, other) 2243 | if other == "inf" then 2244 | return self 2245 | end 2246 | if self == "inf" then 2247 | return other 2248 | end 2249 | if self.x == other.x then 2250 | if BIGNUM.mod((self.y + other.y), p) == zero then 2251 | return "inf" 2252 | end 2253 | return double(self) 2254 | end 2255 | return calc(self, other.y - self.y, other.x - self.x, other.x) 2256 | end 2257 | 2258 | local function mult(self, e) 2259 | e = BIGNUM.mod(e, order) 2260 | e = BIGNUM.copy(e) 2261 | local result, q = "inf", self 2262 | local progress = 0 2263 | io.write("Pubkey calculation (32 steps)") 2264 | io.flush() 2265 | while e ~= zero do 2266 | if bit.band(e[1],1) == 1 then 2267 | result = add(result, q) 2268 | end 2269 | BIGNUM.rshift(e, 1) 2270 | q = double(q) 2271 | --print("result", result.x, result.y) 2272 | if progress % 8 == 0 then 2273 | io.write(".") 2274 | io.flush() 2275 | end 2276 | progress = progress + 1 2277 | end 2278 | print("done") 2279 | return result 2280 | end 2281 | 2282 | local pubkey0 = mult(g, secret) 2283 | local pubkey = {x=BIGNUM.to_dwords(pubkey0.x,8), y=BIGNUM.to_dwords(pubkey0.y,8)} 2284 | pubkey_cache[secret0] = pubkey 2285 | return pubkey 2286 | end 2287 | 2288 | local WORDLIST = { 2289 | [0]="abandon", "ability", "able", "about", "above", "absent", "absorb", "abstract", "absurd", "abuse", "access", "accident", "account", "accuse", "achieve", "acid", "acoustic", "acquire", "across", "act", "action", "actor", "actress", "actual", "adapt", "add", "addict", "address", "adjust", "admit", "adult", "advance", "advice", "aerobic", "affair", "afford", "afraid", "again", "age", "agent", "agree", "ahead", "aim", "air", "airport", "aisle", "alarm", "album", "alcohol", "alert", "alien", "all", "alley", "allow", "almost", "alone", "alpha", "already", "also", "alter", "always", "amateur", "amazing", "among", "amount", "amused", "analyst", "anchor", "ancient", "anger", "angle", "angry", "animal", "ankle", "announce", "annual", "another", "answer", "antenna", "antique", "anxiety", "any", "apart", "apology", "appear", "apple", "approve", "april", "arch", "arctic", "area", "arena", "argue", "arm", "armed", "armor", "army", "around", "arrange", "arrest", "arrive", "arrow", "art", "artefact", "artist", "artwork", "ask", "aspect", "assault", "asset", "assist", "assume", "asthma", "athlete", "atom", "attack", "attend", "attitude", "attract", "auction", "audit", "august", "aunt", "author", "auto", "autumn", "average", "avocado", "avoid", "awake", "aware", "away", "awesome", "awful", "awkward", "axis", "baby", "bachelor", "bacon", "badge", "bag", "balance", "balcony", "ball", "bamboo", "banana", "banner", "bar", "barely", "bargain", "barrel", "base", "basic", "basket", "battle", "beach", "bean", "beauty", "because", "become", "beef", "before", "begin", "behave", "behind", "believe", "below", "belt", "bench", "benefit", "best", "betray", "better", "between", "beyond", "bicycle", "bid", "bike", "bind", "biology", "bird", "birth", "bitter", "black", "blade", "blame", "blanket", "blast", "bleak", "bless", "blind", "blood", "blossom", "blouse", "blue", "blur", "blush", "board", "boat", "body", "boil", "bomb", "bone", "bonus", "book", "boost", "border", "boring", "borrow", "boss", "bottom", "bounce", "box", "boy", "bracket", "brain", "brand", "brass", "brave", "bread", "breeze", "brick", "bridge", "brief", "bright", "bring", "brisk", "broccoli", "broken", "bronze", "broom", "brother", "brown", "brush", "bubble", "buddy", "budget", "buffalo", "build", "bulb", "bulk", "bullet", "bundle", "bunker", "burden", "burger", "burst", "bus", "business", "busy", "butter", "buyer", "buzz", "cabbage", "cabin", "cable", "cactus", "cage", "cake", "call", "calm", "camera", "camp", "can", "canal", "cancel", "candy", "cannon", "canoe", "canvas", "canyon", "capable", "capital", "captain", "car", "carbon", "card", "cargo", "carpet", "carry", "cart", "case", "cash", "casino", "castle", "casual", "cat", "catalog", "catch", "category", "cattle", "caught", "cause", "caution", "cave", "ceiling", "celery", "cement", "census", "century", "cereal", "certain", "chair", "chalk", "champion", "change", "chaos", "chapter", "charge", "chase", "chat", "cheap", "check", "cheese", "chef", "cherry", "chest", "chicken", "chief", "child", "chimney", "choice", "choose", "chronic", "chuckle", "chunk", "churn", "cigar", "cinnamon", "circle", "citizen", "city", "civil", "claim", "clap", "clarify", "claw", "clay", "clean", "clerk", "clever", "click", "client", "cliff", "climb", "clinic", "clip", "clock", "clog", "close", "cloth", "cloud", "clown", "club", "clump", "cluster", "clutch", "coach", "coast", "coconut", "code", "coffee", "coil", "coin", "collect", "color", "column", "combine", "come", "comfort", "comic", "common", "company", "concert", "conduct", "confirm", "congress", "connect", "consider", "control", "convince", "cook", "cool", "copper", "copy", "coral", "core", "corn", "correct", "cost", "cotton", "couch", "country", "couple", "course", "cousin", "cover", "coyote", "crack", "cradle", "craft", "cram", "crane", "crash", "crater", "crawl", "crazy", "cream", "credit", "creek", "crew", "cricket", "crime", "crisp", "critic", "crop", "cross", "crouch", "crowd", "crucial", "cruel", "cruise", "crumble", "crunch", "crush", "cry", "crystal", "cube", "culture", "cup", "cupboard", "curious", "current", "curtain", "curve", "cushion", "custom", "cute", "cycle", "dad", "damage", "damp", "dance", "danger", "daring", "dash", "daughter", "dawn", "day", "deal", "debate", "debris", "decade", "december", "decide", "decline", "decorate", "decrease", "deer", "defense", "define", "defy", "degree", "delay", "deliver", "demand", "demise", "denial", "dentist", "deny", "depart", "depend", "deposit", "depth", "deputy", "derive", "describe", "desert", "design", "desk", "despair", "destroy", "detail", "detect", "develop", "device", "devote", "diagram", "dial", "diamond", "diary", "dice", "diesel", "diet", "differ", "digital", "dignity", "dilemma", "dinner", "dinosaur", "direct", "dirt", "disagree", "discover", "disease", "dish", "dismiss", "disorder", "display", "distance", "divert", "divide", "divorce", "dizzy", "doctor", "document", "dog", "doll", "dolphin", "domain", "donate", "donkey", "donor", "door", "dose", "double", "dove", "draft", "dragon", "drama", "drastic", "draw", "dream", "dress", "drift", "drill", "drink", "drip", "drive", "drop", "drum", "dry", "duck", "dumb", "dune", "during", "dust", "dutch", "duty", "dwarf", "dynamic", "eager", "eagle", "early", "earn", "earth", "easily", "east", "easy", "echo", "ecology", "economy", "edge", "edit", "educate", "effort", "egg", "eight", "either", "elbow", "elder", "electric", "elegant", "element", "elephant", "elevator", "elite", "else", "embark", "embody", "embrace", "emerge", "emotion", "employ", "empower", "empty", "enable", "enact", "end", "endless", "endorse", "enemy", "energy", "enforce", "engage", "engine", "enhance", "enjoy", "enlist", "enough", "enrich", "enroll", "ensure", "enter", "entire", "entry", "envelope", "episode", "equal", "equip", "era", "erase", "erode", "erosion", "error", "erupt", "escape", "essay", "essence", "estate", "eternal", "ethics", "evidence", "evil", "evoke", "evolve", "exact", "example", "excess", "exchange", "excite", "exclude", "excuse", "execute", "exercise", "exhaust", "exhibit", "exile", "exist", "exit", "exotic", "expand", "expect", "expire", "explain", "expose", "express", "extend", "extra", "eye", "eyebrow", "fabric", "face", "faculty", "fade", "faint", "faith", "fall", "false", "fame", "family", "famous", "fan", "fancy", "fantasy", "farm", "fashion", "fat", "fatal", "father", "fatigue", "fault", "favorite", "feature", "february", "federal", "fee", "feed", "feel", "female", "fence", "festival", "fetch", "fever", "few", "fiber", "fiction", "field", "figure", "file", "film", "filter", "final", "find", "fine", "finger", "finish", "fire", "firm", "first", "fiscal", "fish", "fit", "fitness", "fix", "flag", "flame", "flash", "flat", "flavor", "flee", "flight", "flip", "float", "flock", "floor", "flower", "fluid", "flush", "fly", "foam", "focus", "fog", "foil", "fold", "follow", "food", "foot", "force", "forest", "forget", "fork", "fortune", "forum", "forward", "fossil", "foster", "found", "fox", "fragile", "frame", "frequent", "fresh", "friend", "fringe", "frog", "front", "frost", "frown", "frozen", "fruit", "fuel", "fun", "funny", "furnace", "fury", "future", "gadget", "gain", "galaxy", "gallery", "game", "gap", "garage", "garbage", "garden", "garlic", "garment", "gas", "gasp", "gate", "gather", "gauge", "gaze", "general", "genius", "genre", "gentle", "genuine", "gesture", "ghost", "giant", "gift", "giggle", "ginger", "giraffe", "girl", "give", "glad", "glance", "glare", "glass", "glide", "glimpse", "globe", "gloom", "glory", "glove", "glow", "glue", "goat", "goddess", "gold", "good", "goose", "gorilla", "gospel", "gossip", "govern", "gown", "grab", "grace", "grain", "grant", "grape", "grass", "gravity", "great", "green", "grid", "grief", "grit", "grocery", "group", "grow", "grunt", "guard", "guess", "guide", "guilt", "guitar", "gun", "gym", "habit", "hair", "half", "hammer", "hamster", "hand", "happy", "harbor", "hard", "harsh", "harvest", "hat", "have", "hawk", "hazard", "head", "health", "heart", "heavy", "hedgehog", "height", "hello", "helmet", "help", "hen", "hero", "hidden", "high", "hill", "hint", "hip", "hire", "history", "hobby", "hockey", "hold", "hole", "holiday", "hollow", "home", "honey", "hood", "hope", "horn", "horror", "horse", "hospital", "host", "hotel", "hour", "hover", "hub", "huge", "human", "humble", "humor", "hundred", "hungry", "hunt", "hurdle", "hurry", "hurt", "husband", "hybrid", "ice", "icon", "idea", "identify", "idle", "ignore", "ill", "illegal", "illness", "image", "imitate", "immense", "immune", "impact", "impose", "improve", "impulse", "inch", "include", "income", "increase", "index", "indicate", "indoor", "industry", "infant", "inflict", "inform", "inhale", "inherit", "initial", "inject", "injury", "inmate", "inner", "innocent", "input", "inquiry", "insane", "insect", "inside", "inspire", "install", "intact", "interest", "into", "invest", "invite", "involve", "iron", "island", "isolate", "issue", "item", "ivory", "jacket", "jaguar", "jar", "jazz", "jealous", "jeans", "jelly", "jewel", "job", "join", "joke", "journey", "joy", "judge", "juice", "jump", "jungle", "junior", "junk", "just", "kangaroo", "keen", "keep", "ketchup", "key", "kick", "kid", "kidney", "kind", "kingdom", "kiss", "kit", "kitchen", "kite", "kitten", "kiwi", "knee", "knife", "knock", "know", "lab", "label", "labor", "ladder", "lady", "lake", "lamp", "language", "laptop", "large", "later", "latin", "laugh", "laundry", "lava", "law", "lawn", "lawsuit", "layer", "lazy", "leader", "leaf", "learn", "leave", "lecture", "left", "leg", "legal", "legend", "leisure", "lemon", "lend", "length", "lens", "leopard", "lesson", "letter", "level", "liar", "liberty", "library", "license", "life", "lift", "light", "like", "limb", "limit", "link", "lion", "liquid", "list", "little", "live", "lizard", "load", "loan", "lobster", "local", "lock", "logic", "lonely", "long", "loop", "lottery", "loud", "lounge", "love", "loyal", "lucky", "luggage", "lumber", "lunar", "lunch", "luxury", "lyrics", "machine", "mad", "magic", "magnet", "maid", "mail", "main", "major", "make", "mammal", "man", "manage", "mandate", "mango", "mansion", "manual", "maple", "marble", "march", "margin", "marine", "market", "marriage", "mask", "mass", "master", "match", "material", "math", "matrix", "matter", "maximum", "maze", "meadow", "mean", "measure", "meat", "mechanic", "medal", "media", "melody", "melt", "member", "memory", "mention", "menu", "mercy", "merge", "merit", "merry", "mesh", "message", "metal", "method", "middle", "midnight", "milk", "million", "mimic", "mind", "minimum", "minor", "minute", "miracle", "mirror", "misery", "miss", "mistake", "mix", "mixed", "mixture", "mobile", "model", "modify", "mom", "moment", "monitor", "monkey", "monster", "month", "moon", "moral", "more", "morning", "mosquito", "mother", "motion", "motor", "mountain", "mouse", "move", "movie", "much", "muffin", "mule", "multiply", "muscle", "museum", "mushroom", "music", "must", "mutual", "myself", "mystery", "myth", "naive", "name", "napkin", "narrow", "nasty", "nation", "nature", "near", "neck", "need", "negative", "neglect", "neither", "nephew", "nerve", "nest", "net", "network", "neutral", "never", "news", "next", "nice", "night", "noble", "noise", "nominee", "noodle", "normal", "north", "nose", "notable", "note", "nothing", "notice", "novel", "now", "nuclear", "number", "nurse", "nut", "oak", "obey", "object", "oblige", "obscure", "observe", "obtain", "obvious", "occur", "ocean", "october", "odor", "off", "offer", "office", "often", "oil", "okay", "old", "olive", "olympic", "omit", "once", "one", "onion", "online", "only", "open", "opera", "opinion", "oppose", "option", "orange", "orbit", "orchard", "order", "ordinary", "organ", "orient", "original", "orphan", "ostrich", "other", "outdoor", "outer", "output", "outside", "oval", "oven", "over", "own", "owner", "oxygen", "oyster", "ozone", "pact", "paddle", "page", "pair", "palace", "palm", "panda", "panel", "panic", "panther", "paper", "parade", "parent", "park", "parrot", "party", "pass", "patch", "path", "patient", "patrol", "pattern", "pause", "pave", "payment", "peace", "peanut", "pear", "peasant", "pelican", "pen", "penalty", "pencil", "people", "pepper", "perfect", "permit", "person", "pet", "phone", "photo", "phrase", "physical", "piano", "picnic", "picture", "piece", "pig", "pigeon", "pill", "pilot", "pink", "pioneer", "pipe", "pistol", "pitch", "pizza", "place", "planet", "plastic", "plate", "play", "please", "pledge", "pluck", "plug", "plunge", "poem", "poet", "point", "polar", "pole", "police", "pond", "pony", "pool", "popular", "portion", "position", "possible", "post", "potato", "pottery", "poverty", "powder", "power", "practice", "praise", "predict", "prefer", "prepare", "present", "pretty", "prevent", "price", "pride", "primary", "print", "priority", "prison", "private", "prize", "problem", "process", "produce", "profit", "program", "project", "promote", "proof", "property", "prosper", "protect", "proud", "provide", "public", "pudding", "pull", "pulp", "pulse", "pumpkin", "punch", "pupil", "puppy", "purchase", "purity", "purpose", "purse", "push", "put", "puzzle", "pyramid", "quality", "quantum", "quarter", "question", "quick", "quit", "quiz", "quote", "rabbit", "raccoon", "race", "rack", "radar", "radio", "rail", "rain", "raise", "rally", "ramp", "ranch", "random", "range", "rapid", "rare", "rate", "rather", "raven", "raw", "razor", "ready", "real", "reason", "rebel", "rebuild", "recall", "receive", "recipe", "record", "recycle", "reduce", "reflect", "reform", "refuse", "region", "regret", "regular", "reject", "relax", "release", "relief", "rely", "remain", "remember", "remind", "remove", "render", "renew", "rent", "reopen", "repair", "repeat", "replace", "report", "require", "rescue", "resemble", "resist", "resource", "response", "result", "retire", "retreat", "return", "reunion", "reveal", "review", "reward", "rhythm", "rib", "ribbon", "rice", "rich", "ride", "ridge", "rifle", "right", "rigid", "ring", "riot", "ripple", "risk", "ritual", "rival", "river", "road", "roast", "robot", "robust", "rocket", "romance", "roof", "rookie", "room", "rose", "rotate", "rough", "round", "route", "royal", "rubber", "rude", "rug", "rule", "run", "runway", "rural", "sad", "saddle", "sadness", "safe", "sail", "salad", "salmon", "salon", "salt", "salute", "same", "sample", "sand", "satisfy", "satoshi", "sauce", "sausage", "save", "say", "scale", "scan", "scare", "scatter", "scene", "scheme", "school", "science", "scissors", "scorpion", "scout", "scrap", "screen", "script", "scrub", "sea", "search", "season", "seat", "second", "secret", "section", "security", "seed", "seek", "segment", "select", "sell", "seminar", "senior", "sense", "sentence", "series", "service", "session", "settle", "setup", "seven", "shadow", "shaft", "shallow", "share", "shed", "shell", "sheriff", "shield", "shift", "shine", "ship", "shiver", "shock", "shoe", "shoot", "shop", "short", "shoulder", "shove", "shrimp", "shrug", "shuffle", "shy", "sibling", "sick", "side", "siege", "sight", "sign", "silent", "silk", "silly", "silver", "similar", "simple", "since", "sing", "siren", "sister", "situate", "six", "size", "skate", "sketch", "ski", "skill", "skin", "skirt", "skull", "slab", "slam", "sleep", "slender", "slice", "slide", "slight", "slim", "slogan", "slot", "slow", "slush", "small", "smart", "smile", "smoke", "smooth", "snack", "snake", "snap", "sniff", "snow", "soap", "soccer", "social", "sock", "soda", "soft", "solar", "soldier", "solid", "solution", "solve", "someone", "song", "soon", "sorry", "sort", "soul", "sound", "soup", "source", "south", "space", "spare", "spatial", "spawn", "speak", "special", "speed", "spell", "spend", "sphere", "spice", "spider", "spike", "spin", "spirit", "split", "spoil", "sponsor", "spoon", "sport", "spot", "spray", "spread", "spring", "spy", "square", "squeeze", "squirrel", "stable", "stadium", "staff", "stage", "stairs", "stamp", "stand", "start", "state", "stay", "steak", "steel", "stem", "step", "stereo", "stick", "still", "sting", "stock", "stomach", "stone", "stool", "story", "stove", "strategy", "street", "strike", "strong", "struggle", "student", "stuff", "stumble", "style", "subject", "submit", "subway", "success", "such", "sudden", "suffer", "sugar", "suggest", "suit", "summer", "sun", "sunny", "sunset", "super", "supply", "supreme", "sure", "surface", "surge", "surprise", "surround", "survey", "suspect", "sustain", "swallow", "swamp", "swap", "swarm", "swear", "sweet", "swift", "swim", "swing", "switch", "sword", "symbol", "symptom", "syrup", "system", "table", "tackle", "tag", "tail", "talent", "talk", "tank", "tape", "target", "task", "taste", "tattoo", "taxi", "teach", "team", "tell", "ten", "tenant", "tennis", "tent", "term", "test", "text", "thank", "that", "theme", "then", "theory", "there", "they", "thing", "this", "thought", "three", "thrive", "throw", "thumb", "thunder", "ticket", "tide", "tiger", "tilt", "timber", "time", "tiny", "tip", "tired", "tissue", "title", "toast", "tobacco", "today", "toddler", "toe", "together", "toilet", "token", "tomato", "tomorrow", "tone", "tongue", "tonight", "tool", "tooth", "top", "topic", "topple", "torch", "tornado", "tortoise", "toss", "total", "tourist", "toward", "tower", "town", "toy", "track", "trade", "traffic", "tragic", "train", "transfer", "trap", "trash", "travel", "tray", "treat", "tree", "trend", "trial", "tribe", "trick", "trigger", "trim", "trip", "trophy", "trouble", "truck", "true", "truly", "trumpet", "trust", "truth", "try", "tube", "tuition", "tumble", "tuna", "tunnel", "turkey", "turn", "turtle", "twelve", "twenty", "twice", "twin", "twist", "two", "type", "typical", "ugly", "umbrella", "unable", "unaware", "uncle", "uncover", "under", "undo", "unfair", "unfold", "unhappy", "uniform", "unique", "unit", "universe", "unknown", "unlock", "until", "unusual", "unveil", "update", "upgrade", "uphold", "upon", "upper", "upset", "urban", "urge", "usage", "use", "used", "useful", "useless", "usual", "utility", "vacant", "vacuum", "vague", "valid", "valley", "valve", "van", "vanish", "vapor", "various", "vast", "vault", "vehicle", "velvet", "vendor", "venture", "venue", "verb", "verify", "version", "very", "vessel", "veteran", "viable", "vibrant", "vicious", "victory", "video", "view", "village", "vintage", "violin", "virtual", "virus", "visa", "visit", "visual", "vital", "vivid", "vocal", "voice", "void", "volcano", "volume", "vote", "voyage", "wage", "wagon", "wait", "walk", "wall", "walnut", "want", "warfare", "warm", "warrior", "wash", "wasp", "waste", "water", "wave", "way", "wealth", "weapon", "wear", "weasel", "weather", "web", "wedding", "weekend", "weird", "welcome", "west", "wet", "whale", "what", "wheat", "wheel", "when", "where", "whip", "whisper", "wide", "width", "wife", "wild", "will", "win", "window", "wine", "wing", "wink", "winner", "winter", "wire", "wisdom", "wise", "wish", "witness", "wolf", "woman", "wonder", "wood", "wool", "word", "work", "world", "worry", "worth", "wrap", "wreck", "wrestle", "wrist", "write", "wrong", "yard", "year", "yellow", "you", "young", "youth", "zebra", "zero", "zone", "zoo" 2290 | } 2291 | 2292 | local function bin_to_any_module() 2293 | --convert binary stream to any base 2294 | local _M = {} 2295 | local bit = require("bit") 2296 | 2297 | _M.powers2 = {} 2298 | _M.alphabets = {} 2299 | 2300 | local function powers2(exp, base) 2301 | assert(exp >= 0) 2302 | if not _M.powers2[base] then 2303 | _M.powers2[base] = {[0] = {1}} 2304 | end 2305 | local cache = assert(_M.powers2[base]) 2306 | if cache[exp] then 2307 | return cache[exp] 2308 | end 2309 | local prev = powers2(exp - 1, base) 2310 | local mult = {} 2311 | local carry = 0 2312 | local nums = #prev 2313 | for i = 1, nums do 2314 | local m = prev[i] * 2 + carry 2315 | if m < base then 2316 | mult[i] = m 2317 | carry = 0 2318 | else 2319 | mult[i] = m - base 2320 | carry = 1 2321 | end 2322 | end 2323 | if carry == 1 then 2324 | mult[nums + 1] = 1 2325 | end 2326 | cache[exp] = mult 2327 | return mult 2328 | end 2329 | 2330 | local function display(num, alphabet0, pad) 2331 | --print("pad", pad) 2332 | local digits = #num 2333 | local alph = _M.alphabets[alphabet0] 2334 | if not alph then 2335 | alph = {} 2336 | assert(#alphabet0 >= 2) 2337 | for i = 1, #alphabet0 do 2338 | alph[i-1] = alphabet0:sub(i,i) 2339 | end 2340 | _M.alphabets[alphabet0] = alph 2341 | end 2342 | local res = {} 2343 | if pad and (digits < pad) then 2344 | for i = 1, pad - digits do 2345 | res[i] = assert(alph[0]) 2346 | end 2347 | end 2348 | 2349 | for i = digits, 1, -1 do 2350 | table.insert(res,assert(alph[num[i]])) 2351 | end 2352 | return table.concat(res) 2353 | end 2354 | 2355 | function _M.convert(generator_or_chars, base_or_alphabet, maybe_pad) 2356 | local base, alphabet 2357 | if type(base_or_alphabet) == "number" then 2358 | base = base_or_alphabet 2359 | assert(base > 2) 2360 | else 2361 | base = #base_or_alphabet 2362 | alphabet = base_or_alphabet 2363 | end 2364 | local generator = generator_or_chars 2365 | if type(generator) == "string" then 2366 | local str = generator_or_chars 2367 | generator = coroutine.wrap(function() 2368 | for ind = #str, 1, -1 do 2369 | local byte = string.byte(str:sub(ind)) 2370 | --print("byte", string.format("%02x", byte)) 2371 | for bitn = 1, 8 do 2372 | coroutine.yield(bit.band(byte,1)) 2373 | byte = bit.rshift(byte,1) 2374 | end 2375 | end 2376 | end) 2377 | end 2378 | local acc = {0} 2379 | local exp = 0 2380 | while true do 2381 | local next = generator() 2382 | if not next then 2383 | break 2384 | end 2385 | if next == 1 then --add it 2386 | local pow = powers2(exp, base) 2387 | local digits = #pow 2388 | local carry = 0 2389 | for i = 1, digits do 2390 | local a = (acc[i] or 0) + pow[i] + carry 2391 | if a < base then 2392 | acc[i] = a 2393 | carry = 0 2394 | else 2395 | acc[i] = a - base 2396 | carry = 1 2397 | end 2398 | end 2399 | if carry == 1 then 2400 | acc[digits + 1] = 1 2401 | end 2402 | end 2403 | exp = exp + 1 2404 | end 2405 | if not alphabet then 2406 | return acc 2407 | else 2408 | return display(acc, alphabet, maybe_pad), acc 2409 | end 2410 | end 2411 | 2412 | return _M 2413 | end 2414 | 2415 | local function dwords_to_chars(ns) 2416 | local res = {} 2417 | for ndw, dword in ipairs(ns) do 2418 | for i = 1,4 do 2419 | dword = rol(dword,8) 2420 | table.insert(res, string.char(band(0xff, dword))) 2421 | end 2422 | end 2423 | return table.concat(res) 2424 | end 2425 | 2426 | local function chars_to_dwords(str) 2427 | while #str == 0 or (#str % 4 ~= 0) do 2428 | str = string.char(0)..str 2429 | end 2430 | local result = {} 2431 | for idwrd = 1, #str, 4 do 2432 | local dword = 0 2433 | for j = 0, 3 do 2434 | dword = bor(rol(dword,8), string.byte(str:sub(idwrd + j))) 2435 | end 2436 | table.insert(result, dword) 2437 | end 2438 | return result 2439 | end 2440 | 2441 | local function dwords_to_password(dwords,fives) 2442 | fives = fives or 8 2443 | local chars = "$*23456789abcdef@hijk(mnop)rstuvwxyzABCDEFGH=JKLMN#PQRSTUVWXYZ!?" 2444 | assert(#dwords == 8) 2445 | local result = {} 2446 | for i = 1, fives do 2447 | local dword = assert(dwords[i]) 2448 | for j = 1, 5 do 2449 | dword = rol(dword,6) 2450 | local num = band(dword, 63) + 1 2451 | table.insert(result,string.sub(chars,num,num)) 2452 | end 2453 | end 2454 | return table.concat(result) 2455 | end 2456 | 2457 | local function get256bits(rand) 2458 | local dwords = {} 2459 | for i = 1, 8 do 2460 | local dword = 0 2461 | for j = 1, 32 do 2462 | local got = rand() 2463 | local bitsel = band(got, 0xf) --bit 0-15 2464 | dword = rol(dword,1) 2465 | dword = bor(dword, band(1,ror(got, bitsel + 8))) 2466 | end 2467 | dwords[i] = dword 2468 | end 2469 | return dwords 2470 | end 2471 | 2472 | local function to_base58(dwords_or_chars) 2473 | if type(dwords_or_chars) == "table" then 2474 | dwords_or_chars = dwords_to_chars(dwords_or_chars) 2475 | end 2476 | return (BIN_TO_ANY.convert(dwords_or_chars,"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")) 2477 | end 2478 | 2479 | local function to_bin(dwords) 2480 | if type(dwords) == "number" then 2481 | dwords = {dwords} 2482 | end 2483 | local res = {} 2484 | for dwi, dword in ipairs(dwords) do 2485 | for i = 1,32 do 2486 | dword = rol(dword,1) 2487 | table.insert(res, band(dword, 1)) 2488 | end 2489 | end 2490 | assert(#res == 32 * #dwords) 2491 | return (res) 2492 | end 2493 | 2494 | local function to_binstr(n) 2495 | return table.concat(to_bin(n)) 2496 | end 2497 | 2498 | local bitstream = function(rem_bits) 2499 | return (function (take) 2500 | assert(take <= 32) 2501 | local result = 0 2502 | for i = 1, take do 2503 | result = rol(result, 1) 2504 | result = bor(result, table.remove(rem_bits, 1)) 2505 | end 2506 | return result 2507 | end) 2508 | end 2509 | 2510 | local function ripemd160(input, format) 2511 | local function swap_endian(dw) 2512 | local n = 0 2513 | for j = 1, 4 do 2514 | n = bor(lshift(n, 8), band(0xff, dw)) 2515 | dw = rshift(dw, 8) 2516 | end 2517 | return n 2518 | end 2519 | local len = #input 2520 | input = input .. "\128" 2521 | while #input % 64 ~= 56 do 2522 | input = input .. "\000" 2523 | end 2524 | input = input .. dwords_to_chars({swap_endian(len * 8)}) 2525 | input = input .. "\000\000\000\000" --LOL, not likely to exceed 32bit length 2526 | assert(#input % 64 == 0) 2527 | 2528 | local funs = {} 2529 | local funs = { 2530 | [0] = function(x, y, z) return bxor(x, y, z) end, 2531 | function(x, y, z) return bor(band(x, y), band(bnot(x), z)) end, 2532 | function(x, y, z) return bxor(bor(x, bnot(y)), z) end, 2533 | function(x, y, z) return bor(band(x, z), band(y, bnot(z))) end, 2534 | function(x, y, z) return bxor(x, bor(y, bnot(z))) end 2535 | } 2536 | 2537 | local K = {[0] = 0, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E} 2538 | local K2 = {[0] = 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0} 2539 | local r = { 2540 | [0] = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 2541 | 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 2542 | 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 2543 | 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 2544 | 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 2545 | } 2546 | local r2 = { 2547 | [0] = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 2548 | 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 2549 | 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 2550 | 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 2551 | 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 2552 | } 2553 | local s = { 2554 | [0] = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 2555 | 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 2556 | 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 2557 | 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 2558 | 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 2559 | } 2560 | local s2 = { 2561 | [0] = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 2562 | 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 2563 | 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 2564 | 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 2565 | 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 2566 | } 2567 | local function f(j, x, y, z) 2568 | local res = funs[rshift(j,4)](x, y, z) 2569 | --print("f result", tohex(res)) 2570 | return res 2571 | end 2572 | local h0, h1, h2, h3, h4 = 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 2573 | for blk in input:gmatch("(................................................................)") do 2574 | local A, B, C, D, E = h0, h1, h2, h3, h4 2575 | local A2, B2, C2, D2, E2 = h0, h1, h2, h3, h4 2576 | local X = {} 2577 | for i = 0, 63 do 2578 | local ind = rshift(i, 2) 2579 | X[ind] = ror(bor(X[ind] or 0, string.byte(blk:sub(i+1))), 8) 2580 | end 2581 | 2582 | for j = 0, 79 do 2583 | local jsh = rshift(j, 4) 2584 | --print("A f X K s E", tohex(A), tohex(f(j,B,C,D)), tohex (X[r[j]]), tohex(K[jsh]), s[j], tohex(E)) 2585 | local T = tobit(rol (tobit(A + f(j, B, C, D) + X[r[j]] + K[jsh]), s[j]) + E) 2586 | --print("T1", tohex(T)) 2587 | A = E; E = D; D = rol(C, 10); C = B; B = T 2588 | T = tobit(rol(tobit(A2 + f(79-j, B2, C2, D2) + X[r2[j]] + K2[jsh]), s2[j]) + E2) 2589 | A2 = E2; E2 = D2; D2 = rol(C2, 10); C2 = B2; B2 = T 2590 | end 2591 | local T = bit.tobit(h1 + C + D2) 2592 | h1 = bit.tobit(h2 + D + E2) 2593 | h2 = bit.tobit(h3 + E + A2) 2594 | h3 = bit.tobit(h4 + A + B2) 2595 | h4 = bit.tobit(h0 + B + C2) 2596 | h0 = T 2597 | --print ("h0-4:",tohex(h0), tohex(h1), tohex(h2), tohex(h3), tohex(h4)) 2598 | end 2599 | local result = {h0, h1, h2, h3, h4} 2600 | for i = 1, 5 do 2601 | result[i] = swap_endian(result[i]) 2602 | end 2603 | if format == "dwords" then 2604 | return result 2605 | end 2606 | for i = 1, 5 do 2607 | result[i] = bit.tohex(result[i]) 2608 | end 2609 | --print(table.concat(result)) 2610 | return table.concat(result) 2611 | end 2612 | 2613 | local new_shifter = function(state) 2614 | if tobit(state) == 0 then 2615 | state = 1 2616 | end 2617 | local fun = function(arg) 2618 | if arg=="dump" then 2619 | return (state) 2620 | end 2621 | local bt = band(state,1) 2622 | state = rshift(state,1) 2623 | if bt == 1 then 2624 | state = bxor(state, 0xa3000000) 2625 | return true 2626 | end 2627 | return false 2628 | end 2629 | return fun 2630 | -- A3000000 = 1010 0011 0000 0000 0000 0000 0000 0000 - bits 32,30,26,25 2631 | end 2632 | 2633 | local new_random = function(dwords) ---Not txt... 2634 | local w,x,y,z = dwords[1],dwords[2],dwords[3],dwords[4] 2635 | local sh1, sh2, sh3, sh4 = new_shifter(dwords[5]), new_shifter(dwords[6]), new_shifter(dwords[7]), new_shifter(dwords[8]) 2636 | 2637 | if bit.bor(w,x,y,z) == 0 then --Cannot be all zeroes! 2638 | w,x,y,z = 0,0,0,1 2639 | end 2640 | local fun = function(arg) --Xorshift algorithm 2641 | if arg=="dump" then 2642 | return{w,x,y,z, sh1("dump"), sh2("dump"), sh3("dump"), sh4("dump")} 2643 | end 2644 | repeat 2645 | local t = bxor(x, lshift(x,11)) 2646 | x,y,z = y,z,w 2647 | w = bit.bxor(w, rshift(w,19), t, rshift(t,8)) 2648 | until sh1() or sh2() or sh3() or sh4() --Shifters depend on each other 2649 | return w 2650 | end 2651 | for i = 1, 10 do 2652 | fun() 2653 | end 2654 | return fun 2655 | end 2656 | 2657 | local function bip39(dwords) 2658 | assert(#dwords >= 1 and #dwords <= 8) 2659 | local chars = dwords_to_chars(dwords) 2660 | local sha = to_bin(sha256(chars, "dwords")) 2661 | local result = to_bin(dwords) 2662 | local chksum = bitstream(sha) 2663 | for i = 1, #dwords do 2664 | table.insert(result, chksum(1)) 2665 | end 2666 | assert(#result == #dwords * 33) 2667 | local resultstr = {} 2668 | local bs = bitstream(result) 2669 | for i = 1, #dwords * 3 do 2670 | table.insert(resultstr, assert(WORDLIST[bs(11)])) 2671 | end 2672 | return table.concat(resultstr, " ") 2673 | end 2674 | 2675 | local function keymaster(seedstring, difc, progress) 2676 | local prgfnc = function() end 2677 | local iterations = 0x100000 2678 | local one64 = rshift(iterations, 6) 2679 | if progress then 2680 | local prg = "012345abcdefghijklmnopqrstuvwxyz012345ABCDEFGHIJKLMNOPQRSTUVWXYZ" 2681 | local progressbar = {} 2682 | for i = 1, 64 do 2683 | progressbar[i] = prg:sub(i,i) 2684 | end 2685 | io.write("Progress: ") 2686 | local count = 1 2687 | prgfnc = function() 2688 | io.write(string.format(progressbar[count])) 2689 | io.flush() 2690 | if count == 64 then 2691 | print() 2692 | end 2693 | count = count + 1 2694 | end 2695 | end 2696 | 2697 | local rnd = new_random(sha256(seedstring, "dwords")) 2698 | local difmask = bit.rshift(0xffffffff, 32-difc) 2699 | local t0 = os.time() 2700 | for round = 1, 64 do 2701 | prgfnc() 2702 | for i = 1, one64 do 2703 | difmask = ror(difmask, band(rnd(), 31)) 2704 | local seek = band(difmask, rnd()) 2705 | -- print("looking for "..tohex(seek)..", mask: "..tohex(difmask)) 2706 | repeat 2707 | local got = band(difmask,rnd()) 2708 | until got == seek 2709 | end 2710 | end 2711 | local master = get256bits(rnd) 2712 | return master, os.time()-t0 2713 | end 2714 | 2715 | local function calibrate() 2716 | for difc = 1, MAXDIFC do 2717 | print("Trying difficulty "..difc) 2718 | local gotrnd, time = keymaster("Xuul",difc,true) 2719 | print("Seconds: "..time) 2720 | print() 2721 | if time >= 10 then 2722 | print("\nCALIBRATION RESULTS FOR THIS MACHINE:") 2723 | for d = difc, MAXDIFC do 2724 | local t = time 2725 | local ts = t.." seconds" 2726 | if t > 180 then 2727 | t = math.floor(t/60) 2728 | ts = t.. " minutes" 2729 | if t > 180 then 2730 | t = math.floor(t / 60) 2731 | ts = t.." hours" 2732 | if t > 72 then 2733 | t = math.floor( t / 24) 2734 | ts = t.." days" 2735 | if t > 1000 then 2736 | t = math.floor(t / 365) 2737 | ts = t.." years" 2738 | end 2739 | end 2740 | end 2741 | end 2742 | print("Difficulty "..d.." takes approx. "..ts..".") 2743 | 2744 | time = time * 2 2745 | end 2746 | return 2747 | end 2748 | end 2749 | end 2750 | 2751 | local function base58check(str) 2752 | local chk = (sha256(str, "dwords")) 2753 | chk = sha256(dwords_to_chars(chk),"dwords")[1] 2754 | for i = 1, 4 do 2755 | chk = rol(chk, 8) 2756 | str = str .. string.char(band(chk, 0xff)) 2757 | end 2758 | --print(#str) 2759 | local zeroes = 0 2760 | for i=1, #str do 2761 | if str:sub(i,i) == "\000" then 2762 | zeroes = zeroes + 1 2763 | else 2764 | break 2765 | end 2766 | end 2767 | return string.rep("1",zeroes)..to_base58(str) 2768 | end 2769 | 2770 | local function btc_privkey(dwords) 2771 | if (dwords[1] == 0 or dwords[1] == 0xffffffff) and (dwords[1] == dwords[2]) and (dwords[2] == dwords[3]) then 2772 | print("?!?!?!?!?! First 3 dwords are the same !?!?!?!?!?!?! BTC key very suspicious") --Hmm, LOL 2773 | end 2774 | local result = {} 2775 | for ii, typ in ipairs{"compressed", "uncompressed"} do 2776 | local str = string.char(0x80)..dwords_to_chars(dwords) 2777 | if typ == "compressed" then 2778 | str = str .. string.char(0x01) 2779 | end 2780 | result[typ] = base58check(str) 2781 | end 2782 | return result 2783 | end 2784 | 2785 | local function wif(dwpubkey, comp) 2786 | local str 2787 | if comp ~= "compressed" then 2788 | str = "\004"..dwords_to_chars(dwpubkey.x)..dwords_to_chars(dwpubkey.y) 2789 | assert(#str == 65) 2790 | else --compressed 2791 | str = dwords_to_chars(dwpubkey.x) 2792 | if bit.band(dwpubkey.y[8],1) == 0 then 2793 | str = "\002" .. str 2794 | else 2795 | str = "\003" .. str 2796 | end 2797 | assert(#str == 33) 2798 | end 2799 | local step2 = sha256(str, "dwords") 2800 | local step3 = ripemd160(dwords_to_chars(step2), "dwords") 2801 | local step4 = "\000"..dwords_to_chars(step3) 2802 | return(base58check(step4)) 2803 | end 2804 | 2805 | local function checkwords(str, howmany) 2806 | if not howmany then 2807 | howmany = 2 2808 | end 2809 | assert(howmany >= 1 and howmany <=8) 2810 | local ichksum = sha256(str.."\000checkwords", "dwords") 2811 | local result = {} 2812 | for i = 1, howmany do 2813 | result[i] = assert(WORDLIST[band(ichksum[i], 0x7ff)]) 2814 | end 2815 | return table.concat(result, " ") 2816 | end 2817 | 2818 | local function get_all_prefixes() 2819 | return {hex = true, btcc = true, btcu = true, pwd15 = true, pwd40 = true, wrd12 = true, wrd24 = true} 2820 | end 2821 | 2822 | local function test(opts) 2823 | if not opts then 2824 | opts = {} 2825 | end 2826 | print("Running self-tests.") 2827 | 2828 | assert(to_binstr(7)=="00000000000000000000000000000111") 2829 | local bs = bitstream{1,1,1,0,0,0,1,1,1,0,0,0} 2830 | assert(bs(4) == 14) 2831 | assert(bs(4) == 3) 2832 | assert(dwords_to_chars({0x41424344,0x31323334}) == "ABCD1234") 2833 | local res = chars_to_dwords("12ABCD") 2834 | assert(res[1] == 0x00003132) 2835 | assert(res[2] == 0x41424344) 2836 | assert(ripemd160("") == "9c1185a5c5e9fc54612808977ee8f548b2258d31", "RIPEMD test 1 failed") 2837 | assert(ripemd160("The quick brown fox jumps over the lazy dog") == "37f332f68db77bd9d7edd4969571ad671cf9dd3b", "RIPEMD test 2 failed") 2838 | assert(sha256("") == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") 2839 | assert(sha256("The quick brown fox jumps over the lazy dog") == "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592") 2840 | 2841 | QR.test() 2842 | if opts.test then --Show test QR code 2843 | local dwords = sha256(os.time() .. tostring({}), "dwords") 2844 | local warn = "!!!!! DO NOT USE THIS PRIVATE KEY FOR ACTUAL BTC STORAGE !!!!!" 2845 | local pkey = btc_privkey(dwords).compressed 2846 | print ("QR code of BTC private key "..pkey..":") 2847 | print (warn) 2848 | print (QR.render(pkey, 6)) 2849 | print(warn) 2850 | end 2851 | 2852 | local sh = new_shifter(0x12345678) 2853 | for i = 1, 100 do 2854 | sh() 2855 | end 2856 | assert(tobit(sh("dump")) == tobit(0x8d8aa8c3)) 2857 | 2858 | local dwords = {1,0} 2859 | assert(bip39(dwords) == "abandon abandon able abandon abandon about") 2860 | 2861 | local rnd0 = new_random{0,0,0,1,1,1,1,1} 2862 | for i = 1, 990 do 2863 | rnd0() 2864 | end 2865 | local dump = rnd0("dump") 2866 | for i,val in ipairs({0xe69e4882, 0x993ecb5d, 0xba4f982f, 0x0bafb5d9, 0x46c10ce6, 0x033a2504, 0x1e202557, 0xeb54cd93}) do 2867 | assert(tobit(val) == tobit(dump[i]), "bad "..i) 2868 | end 2869 | assert(tohex(rnd0())=="8995132f") 2870 | 2871 | local key = get256bits(rnd0) 2872 | assert(hex256(key,"-") == "e7ba2240-c5aa7fe7-584a794e-c0ab7d4b-1b74cf7b-ccbaf55d-b5e5b889-1442c646") 2873 | assert(dwords_to_password(key) == "VXEy@N)F?Vm4FVjMaJZi6TjfuPbHRnJumUy54b6h") 2874 | 2875 | assert(hex256(keymaster("Satan",2),"-") == "16784c4f-eb122684-376d1d73-375adccd-133b10cf-4ef0bac3-abe34427-a09aecd2") 2876 | assert(BIN_TO_ANY.convert(dwords_to_chars({0x12345678,0xffffffff}),"0123456789abcdef") == "12345678ffffffff") 2877 | assert(to_base58({0x80, 0x32247122, 0xF9FF8BB7, 0x8BBEFC55, 0x4E729121, 0x24410788, 0x2417AF0D, 0x77EB7A22, 0x784171F2, 0xAB079763}) == "5JCNQBno4UP562LCEXMTr72WVUe315rrXzPqAFiap8zQNjzarbL") 2878 | assert(checkwords("Homopes") == "devote asthma") 2879 | if opts.no_btc_addr then 2880 | print("Skipping BTC pubkey generation tests.") 2881 | else 2882 | BIGNUM.test() 2883 | local btckeys = btc_privkey(keymaster("Satan",1),"-") 2884 | assert(btckeys.compressed == "Ky63MMQWPEYLpG5rbbSxDbtAwfzaNDvKzH2co6QXKg7mFJHft5TS") 2885 | assert(btckeys.uncompressed == "5JEq7RZWmTdZ8Y4NCv7nb7zp7VmmGEMEpR2Gp9UXtMeL65u7vyv") 2886 | local dwpubkey = privkey_to_pubkey("0x2EE42A735AE3D0C1A7E435EF3B4731B0205A7839015E100BCC8472EE989EC887") 2887 | assert(wif(dwpubkey, "uncompressed") == "1MNQH6Xi8Ltf1TfgDWYNijZaiPdVGxPSZw") 2888 | assert(wif(dwpubkey, "compressed") == "1BMwnCKvHD9KMHa1Acb2BsisMuM1XRwjvU") 2889 | end 2890 | print("All self-tests OK") 2891 | end 2892 | 2893 | local function parse_options() 2894 | local allowed = {"difficulty", "salt", "test", "checksum", "no_btc_addr", "prefix", "calibrate", "qr_halfheight", "qr_doublewidth", "qr_character", "qr_invert"} 2895 | for i, opt in ipairs(allowed) do 2896 | allowed[opt] = true 2897 | end 2898 | 2899 | local opts = {} 2900 | for i, arg in ipairs(arg) do 2901 | if arg:match("=") then 2902 | local opt, val = arg:match("(.-)=(.+)") 2903 | assert(opt and val, "Invalid option syntax: "..arg) 2904 | assert(#opt > 0) 2905 | assert(#val > 0) 2906 | opts[opt] = val 2907 | else 2908 | opts[arg] = true 2909 | end 2910 | end 2911 | for k,v in pairs(opts) do 2912 | if not allowed[k] then 2913 | print("Invalid option: "..k.."="..tostring(v)) 2914 | table.sort(allowed) 2915 | print("Allowed options: "..table.concat(allowed,", ")) 2916 | os.exit() 2917 | end 2918 | end 2919 | 2920 | return opts 2921 | end 2922 | 2923 | local function main() 2924 | _G.BIGNUM = load_bignum() 2925 | _G.QR = load_qr() 2926 | _G.BIN_TO_ANY = bin_to_any_module() 2927 | print("KRYPTA by Fuxoft, version ".._G.VERSION) 2928 | local opts = parse_options() 2929 | 2930 | if opts.prefix then 2931 | if opts.prefix:match(":") then 2932 | error("Do NOT include the colon in prefix.") 2933 | end 2934 | if not get_all_prefixes()[opts.prefix] then 2935 | error("Unknown prefix: "..opts.prefix) 2936 | end 2937 | end 2938 | 2939 | QR.init(opts) 2940 | 2941 | if opts.test then 2942 | test(opts) 2943 | os.exit() 2944 | end 2945 | 2946 | if opts.calibrate then 2947 | print("Calibrating the difficulty...") 2948 | calibrate() 2949 | os.exit() 2950 | end 2951 | 2952 | if opts.salt then 2953 | SALT = opts.salt 2954 | end 2955 | 2956 | if opts.difficulty then 2957 | DIFFICULTY = tonumber(opts.difficulty) 2958 | end 2959 | 2960 | if DIFFICULTY == 0 then 2961 | print[[ 2962 | To run Krypta, you must supply at least the 'difficulty' option. 2963 | For detailed documentation, visit https://github.com/fuxoft/krypta 2964 | 2965 | All available options with examples: 2966 | 2967 | test 2968 | Do all self tests, print a test QR code (of random BTC private key) and quit. 2969 | 2970 | difficulty=5 2971 | Select the difficulty for master key generation (1 to 31). 2972 | Each subsequent difficulty is twice slower than the previous. 2973 | 1 is fastest. 31 takes many years. Use the "calibrate" option 2974 | to find the best difficulty. 2975 | 2976 | calibrate 2977 | Runs a calibration that shows you how much time (approximately) it takes 2978 | to generate the master key for various difficulties. 2979 | 2980 | checksum=0x123 2981 | Specify checksum for your master passphrase (0x and three hex digits). 2982 | Useful to be sure that you entered the passphrase correctly. 2983 | Using it degrades you security a tiny little bit because if the attacker 2984 | knows it, he can easily check if his master passphrase and difficulty guess 2985 | is correct or not. 2986 | 2987 | salt=00420777123456 2988 | Specify salt which is combined with your passphrase to generate master key. 2989 | Note that having passphrase "abc" and salt "def" is not the same thing 2990 | as having passphrase "abcdef" (or "defabc") without salt. 2991 | 2992 | no_btc_addr 2993 | Disables generating BTC addresses (and saves a few seconds of time). 2994 | Note that BTC private keys generation is still enabled because it's fast. 2995 | The BTC address generation algorithm is currently very naive and rather slow. 2996 | It can be significantly improved. 2997 | 2998 | prefix=pwd12 2999 | Automatically sets default prefix. Entering "xyz" as an index then 3000 | automatically selects index "pwd12:xyz". Use index "all:xyz" to show 3001 | all prefixes (the same result as entering index "xyz" when no default 3002 | prefix is set). 3003 | 3004 | The following options are for QR code generation for BTC private keys 3005 | and addresses. Use the "test" option to experiment with various QR code options. 3006 | If you have recent sane computer, you will probably want to use both "qr_invert" 3007 | and "qr_halfheight" options. 3008 | 3009 | qr_halfheight 3010 | Displays the QR code at half height using UTF graphics. Best option 3011 | if your terminal and font support these graphical characters. Using 3012 | this option automatically disables qr_doublewidth and qr_character options. 3013 | 3014 | qr_character=X 3015 | Select character to represent "full" QR code pixels. 3016 | Default is the U+2588 Unicode "full block" character. 3017 | Use this if your terminal / font don't support it. 3018 | The "empty" pixel is always represented by space. 3019 | 3020 | qr_doublewidth 3021 | Use this option to render every pixel as two characters. 3022 | Dumber alternative to "qr_halfheight". The resulting 3023 | QR code is twice as large (in both directions) 3024 | as with "qr_halfheight". 3025 | 3026 | qr_invert 3027 | Inverts the QR display so that full pixels become spaces and spaces become 3028 | full pixels. Note that this is necessary on terminals that display 3029 | white-on-black characters (i.e. most of them). 3030 | ]] 3031 | os.exit() 3032 | end 3033 | if not DIFFICULTY or (DIFFICULTY < 1 or DIFFICULTY > MAXDIFC or (DIFFICULTY ~= math.floor(DIFFICULTY))) then 3034 | error("Invalid difficulty: "..tostring(DIFFICULTY)) 3035 | end 3036 | 3037 | CHECKSUM = CHECKSUM or tonumber(opts.checksum) 3038 | 3039 | if CHECKSUM then 3040 | assert(CHECKSUM >= 0 and CHECKSUM <= 0xfff, "Invalid checksum value") 3041 | end 3042 | 3043 | print("STARTING!") 3044 | test(opts) 3045 | print("SALT='"..SALT.."' ("..#SALT.." characters)") 3046 | assert(type(SALT) == "string", "SALT is not string") 3047 | if #SALT == 0 then 3048 | print("WARNING! 'SALT' is not set. Set it to be more secure.") 3049 | end 3050 | 3051 | if not CHECKSUM then 3052 | print("Checksum not set, will display it.") 3053 | end 3054 | print("Please enter your super-secret MASTER PASSPHRASE:") 3055 | local masterpp = io.read() 3056 | -- print("Please enter it again:") 3057 | -- local masterpp2 = io.read() 3058 | -- assert(masterpp == masterpp2, "Passphrase mismatch") 3059 | for i = 1, 200 do 3060 | print("") 3061 | end 3062 | if #masterpp < 10 then 3063 | print("WARNING: Master passphrase is very short.") 3064 | end 3065 | 3066 | local zeroes = dwords_to_chars{0} 3067 | local masterseed = masterpp..zeroes..SALT 3068 | print("Calculating master key at difficulty "..DIFFICULTY) 3069 | local masterkey,time = keymaster(masterseed, DIFFICULTY, true) 3070 | print("Masterkey generated in "..time.." seconds.") 3071 | local chsum = band(0xfff,bxor(masterkey[1],masterkey[7],masterkey[8])) 3072 | print(string.format("Masterkey checksum is: 0x%03x",chsum)) 3073 | if CHECKSUM then 3074 | if tobit(CHECKSUM) ~= tobit(chsum) then 3075 | print("!!! CHECKSUM DOES NOT MATCH !!!") 3076 | error("nomatch") 3077 | else 3078 | print("Checksum matches.") 3079 | end 3080 | end 3081 | --print("-masterkey- "..hex256(masterkey," ")) 3082 | local strseed0 = dwords_to_chars(masterkey) 3083 | while true do 3084 | print("\n----------------------------------") 3085 | if opts.prefix then 3086 | print("Default prefix is '".. opts.prefix ..":' (override with 'all:')") 3087 | end 3088 | print("Enter index with optional 'prefix:' (default='')") 3089 | local ind0 = assert(io.read()) 3090 | local prefix, index = ind0:match("^(.+):(.*)$") 3091 | if opts.prefix and not prefix then 3092 | prefix = opts.prefix 3093 | index = ind0 3094 | end 3095 | if prefix == "all" then 3096 | prefix = nil 3097 | ind0 = index 3098 | end 3099 | local show = get_all_prefixes() 3100 | 3101 | if index and prefix then 3102 | if not show[prefix] then 3103 | print("Error: Prefix '"..prefix.."' is invalid.") 3104 | show = false 3105 | else 3106 | show = {[prefix] = true} 3107 | end 3108 | else 3109 | --Show everything 3110 | index = ind0 3111 | end 3112 | 3113 | if index:match(":") then 3114 | print("Error: Colon (':') detected but no valid prefix and index.") 3115 | show = false 3116 | end 3117 | 3118 | if show then 3119 | print(string.format("Entered index string: '%s' (%s chars)", index, #index)) 3120 | if index == "" then 3121 | print("WARNING. Index is empty string.") 3122 | end 3123 | local rnd = new_random(sha256(index..zeroes..strseed0,"dwords")) 3124 | local result = get256bits(rnd) 3125 | assert(#result == 8) 3126 | local ichksum = sha256(strseed0..zeroes..dwords_to_chars(result)..zeroes.."index checksum", "dwords") 3127 | local chw1, chw2 = band(ichksum[1], 0x7ff), band(ichksum[2], 0x7ff) 3128 | if prefix then 3129 | print(string.format("Checkwords for this specific master passphrase, prefix and index (%s:%s): '%s'", prefix, index, checkwords(strseed0..dwords_to_chars(result)..prefix, 3))) 3130 | else 3131 | print(string.format("Checkwords for this specific master passphrase and index (no prefix): '%s'", checkwords(strseed0..dwords_to_chars(result)))) 3132 | end 3133 | 3134 | if show.hex then 3135 | print("(hex:) 256bit hex number: "..hex256(result)) 3136 | print("(hex:) With spaces: "..hex256(result," ")) 3137 | end 3138 | local pubkey 3139 | if not opts.no_btc_addr and (show.btcc or show.btcu) then 3140 | pubkey = privkey_to_pubkey("0x"..hex256(result)) 3141 | end 3142 | local privkeys = btc_privkey(result) 3143 | for ind, typ in ipairs {"compressed", "uncompressed"} do 3144 | local key = "btcc" 3145 | if typ == "uncompressed" then 3146 | key = "btcu" 3147 | end 3148 | if show[key] then 3149 | print(string.format("(%s:) BTC WIF privkey (%s): %s", key, typ, privkeys[typ])) 3150 | if not prefix then 3151 | print(string.format("Specify the %s: prefix to display QR codes.", key)) 3152 | else 3153 | print("--- Private key QR code:") 3154 | print(QR.render(privkeys[typ], 4)) 3155 | print("--- End of private key QR code") 3156 | end 3157 | if pubkey then 3158 | local wif = wif(pubkey, typ) 3159 | print(string.format("(%s:) Corresponding BTC address (%s): %s", key, typ, wif)) 3160 | if prefix then 3161 | print("--- Public BTC address QR code:") 3162 | print(QR.render(wif, 4)) 3163 | print("--- End of public BTC address QR code") 3164 | end 3165 | else 3166 | print("("..typ.." BTC address generation disabled by 'no_btc_addr' user option)") 3167 | end 3168 | end 3169 | end 3170 | if show.pwd15 then 3171 | print("(pwd15:) 15 chars password: "..dwords_to_password(result,3)) 3172 | end 3173 | if show.pwd40 then 3174 | print("(pwd40:) 40 chars password: "..dwords_to_password(result)) 3175 | end 3176 | if show.wrd12 then 3177 | print("(wrd12:) BIP39/12: "..bip39{result[1], result[2], result[3], result[4]}) 3178 | end 3179 | if show.wrd24 then 3180 | print("(wrd24:) BIP39/24: "..bip39(result)) 3181 | end 3182 | else 3183 | print("Nothing to show. Enter valid prefix or leave the prefix out.") 3184 | end 3185 | end 3186 | end 3187 | 3188 | main() 3189 | --------------------------------------------------------------------------------