1743 lines
35 KiB
HTML
1743 lines
35 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html>
|
||
|
<body>
|
||
|
<script>
|
||
|
"use strict"
|
||
|
// Set the header of the page.
|
||
|
document.title = "Lume Web: Login"
|
||
|
const HASH_SIZE = 64
|
||
|
var K = [
|
||
|
0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, 0x3956c25b,
|
||
|
0xf348b538, 0x59f111f1, 0xb605d019, 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, 0xd807aa98, 0xa3030242,
|
||
|
0x12835b01, 0x45706fbe, 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, 0x72be5d74, 0xf27b896f, 0x80deb1fe,
|
||
|
0x3b1696b1, 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
|
||
|
0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, 0x5cb0a9dc,
|
||
|
0xbd41fbd4, 0x76f988da, 0x831153b5, 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, 0xb00327c8, 0x98fb213f,
|
||
|
0xbf597fc7, 0xbeef0ee4, 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, 0x06ca6351, 0xe003826f, 0x14292967,
|
||
|
0x0a0e6e70, 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
|
||
|
0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, 0xa2bfe8a1,
|
||
|
0x4cf10364, 0xa81a664b, 0xbc423001, 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, 0xd192e819, 0xd6ef5218,
|
||
|
0xd6990624, 0x5565a910, 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, 0x19a4c116, 0xb8d2d0c8, 0x1e376c08,
|
||
|
0x5141ab53, 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
|
||
|
0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, 0x84c87814,
|
||
|
0xa1f0ab72, 0x8cc70208, 0x1a6439ec, 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, 0xbef9a3f7, 0xb2c67915,
|
||
|
0xc67178f2, 0xe372532b, 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f,
|
||
|
0xee6ed178, 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
|
||
|
0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, 0x4cc5d4be,
|
||
|
0xcb3e42b6, 0x597f299c, 0xfc657e2a, 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817,
|
||
|
]
|
||
|
function ts64(x, i, h, l) {
|
||
|
x[i] = (h >> 24) & 0xff
|
||
|
x[i + 1] = (h >> 16) & 0xff
|
||
|
x[i + 2] = (h >> 8) & 0xff
|
||
|
x[i + 3] = h & 0xff
|
||
|
x[i + 4] = (l >> 24) & 0xff
|
||
|
x[i + 5] = (l >> 16) & 0xff
|
||
|
x[i + 6] = (l >> 8) & 0xff
|
||
|
x[i + 7] = l & 0xff
|
||
|
}
|
||
|
function crypto_hashblocks_hl(hh, hl, m, n) {
|
||
|
var wh = new Int32Array(16),
|
||
|
wl = new Int32Array(16),
|
||
|
bh0,
|
||
|
bh1,
|
||
|
bh2,
|
||
|
bh3,
|
||
|
bh4,
|
||
|
bh5,
|
||
|
bh6,
|
||
|
bh7,
|
||
|
bl0,
|
||
|
bl1,
|
||
|
bl2,
|
||
|
bl3,
|
||
|
bl4,
|
||
|
bl5,
|
||
|
bl6,
|
||
|
bl7,
|
||
|
th,
|
||
|
tl,
|
||
|
i,
|
||
|
j,
|
||
|
h,
|
||
|
l,
|
||
|
a,
|
||
|
b,
|
||
|
c,
|
||
|
d
|
||
|
var ah0 = hh[0],
|
||
|
ah1 = hh[1],
|
||
|
ah2 = hh[2],
|
||
|
ah3 = hh[3],
|
||
|
ah4 = hh[4],
|
||
|
ah5 = hh[5],
|
||
|
ah6 = hh[6],
|
||
|
ah7 = hh[7],
|
||
|
al0 = hl[0],
|
||
|
al1 = hl[1],
|
||
|
al2 = hl[2],
|
||
|
al3 = hl[3],
|
||
|
al4 = hl[4],
|
||
|
al5 = hl[5],
|
||
|
al6 = hl[6],
|
||
|
al7 = hl[7]
|
||
|
var pos = 0
|
||
|
while (n >= 128) {
|
||
|
for (i = 0; i < 16; i++) {
|
||
|
j = 8 * i + pos
|
||
|
wh[i] = (m[j + 0] << 24) | (m[j + 1] << 16) | (m[j + 2] << 8) | m[j + 3]
|
||
|
wl[i] = (m[j + 4] << 24) | (m[j + 5] << 16) | (m[j + 6] << 8) | m[j + 7]
|
||
|
}
|
||
|
for (i = 0; i < 80; i++) {
|
||
|
bh0 = ah0
|
||
|
bh1 = ah1
|
||
|
bh2 = ah2
|
||
|
bh3 = ah3
|
||
|
bh4 = ah4
|
||
|
bh5 = ah5
|
||
|
bh6 = ah6
|
||
|
bh7 = ah7
|
||
|
bl0 = al0
|
||
|
bl1 = al1
|
||
|
bl2 = al2
|
||
|
bl3 = al3
|
||
|
bl4 = al4
|
||
|
bl5 = al5
|
||
|
bl6 = al6
|
||
|
bl7 = al7
|
||
|
// add
|
||
|
h = ah7
|
||
|
l = al7
|
||
|
a = l & 0xffff
|
||
|
b = l >>> 16
|
||
|
c = h & 0xffff
|
||
|
d = h >>> 16
|
||
|
// Sigma1
|
||
|
h =
|
||
|
((ah4 >>> 14) | (al4 << (32 - 14))) ^
|
||
|
((ah4 >>> 18) | (al4 << (32 - 18))) ^
|
||
|
((al4 >>> (41 - 32)) | (ah4 << (32 - (41 - 32))))
|
||
|
l =
|
||
|
((al4 >>> 14) | (ah4 << (32 - 14))) ^
|
||
|
((al4 >>> 18) | (ah4 << (32 - 18))) ^
|
||
|
((ah4 >>> (41 - 32)) | (al4 << (32 - (41 - 32))))
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
// Ch
|
||
|
h = (ah4 & ah5) ^ (~ah4 & ah6)
|
||
|
l = (al4 & al5) ^ (~al4 & al6)
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
// K
|
||
|
h = K[i * 2]
|
||
|
l = K[i * 2 + 1]
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
// w
|
||
|
h = wh[i % 16]
|
||
|
l = wl[i % 16]
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
b += a >>> 16
|
||
|
c += b >>> 16
|
||
|
d += c >>> 16
|
||
|
th = (c & 0xffff) | (d << 16)
|
||
|
tl = (a & 0xffff) | (b << 16)
|
||
|
// add
|
||
|
h = th
|
||
|
l = tl
|
||
|
a = l & 0xffff
|
||
|
b = l >>> 16
|
||
|
c = h & 0xffff
|
||
|
d = h >>> 16
|
||
|
// Sigma0
|
||
|
h =
|
||
|
((ah0 >>> 28) | (al0 << (32 - 28))) ^
|
||
|
((al0 >>> (34 - 32)) | (ah0 << (32 - (34 - 32)))) ^
|
||
|
((al0 >>> (39 - 32)) | (ah0 << (32 - (39 - 32))))
|
||
|
l =
|
||
|
((al0 >>> 28) | (ah0 << (32 - 28))) ^
|
||
|
((ah0 >>> (34 - 32)) | (al0 << (32 - (34 - 32)))) ^
|
||
|
((ah0 >>> (39 - 32)) | (al0 << (32 - (39 - 32))))
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
// Maj
|
||
|
h = (ah0 & ah1) ^ (ah0 & ah2) ^ (ah1 & ah2)
|
||
|
l = (al0 & al1) ^ (al0 & al2) ^ (al1 & al2)
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
b += a >>> 16
|
||
|
c += b >>> 16
|
||
|
d += c >>> 16
|
||
|
bh7 = (c & 0xffff) | (d << 16)
|
||
|
bl7 = (a & 0xffff) | (b << 16)
|
||
|
// add
|
||
|
h = bh3
|
||
|
l = bl3
|
||
|
a = l & 0xffff
|
||
|
b = l >>> 16
|
||
|
c = h & 0xffff
|
||
|
d = h >>> 16
|
||
|
h = th
|
||
|
l = tl
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
b += a >>> 16
|
||
|
c += b >>> 16
|
||
|
d += c >>> 16
|
||
|
bh3 = (c & 0xffff) | (d << 16)
|
||
|
bl3 = (a & 0xffff) | (b << 16)
|
||
|
ah1 = bh0
|
||
|
ah2 = bh1
|
||
|
ah3 = bh2
|
||
|
ah4 = bh3
|
||
|
ah5 = bh4
|
||
|
ah6 = bh5
|
||
|
ah7 = bh6
|
||
|
ah0 = bh7
|
||
|
al1 = bl0
|
||
|
al2 = bl1
|
||
|
al3 = bl2
|
||
|
al4 = bl3
|
||
|
al5 = bl4
|
||
|
al6 = bl5
|
||
|
al7 = bl6
|
||
|
al0 = bl7
|
||
|
if (i % 16 === 15) {
|
||
|
for (j = 0; j < 16; j++) {
|
||
|
// add
|
||
|
h = wh[j]
|
||
|
l = wl[j]
|
||
|
a = l & 0xffff
|
||
|
b = l >>> 16
|
||
|
c = h & 0xffff
|
||
|
d = h >>> 16
|
||
|
h = wh[(j + 9) % 16]
|
||
|
l = wl[(j + 9) % 16]
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
// sigma0
|
||
|
th = wh[(j + 1) % 16]
|
||
|
tl = wl[(j + 1) % 16]
|
||
|
h = ((th >>> 1) | (tl << (32 - 1))) ^ ((th >>> 8) | (tl << (32 - 8))) ^ (th >>> 7)
|
||
|
l = ((tl >>> 1) | (th << (32 - 1))) ^ ((tl >>> 8) | (th << (32 - 8))) ^ ((tl >>> 7) | (th << (32 - 7)))
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
// sigma1
|
||
|
th = wh[(j + 14) % 16]
|
||
|
tl = wl[(j + 14) % 16]
|
||
|
h = ((th >>> 19) | (tl << (32 - 19))) ^ ((tl >>> (61 - 32)) | (th << (32 - (61 - 32)))) ^ (th >>> 6)
|
||
|
l =
|
||
|
((tl >>> 19) | (th << (32 - 19))) ^
|
||
|
((th >>> (61 - 32)) | (tl << (32 - (61 - 32)))) ^
|
||
|
((tl >>> 6) | (th << (32 - 6)))
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
b += a >>> 16
|
||
|
c += b >>> 16
|
||
|
d += c >>> 16
|
||
|
wh[j] = (c & 0xffff) | (d << 16)
|
||
|
wl[j] = (a & 0xffff) | (b << 16)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// add
|
||
|
h = ah0
|
||
|
l = al0
|
||
|
a = l & 0xffff
|
||
|
b = l >>> 16
|
||
|
c = h & 0xffff
|
||
|
d = h >>> 16
|
||
|
h = hh[0]
|
||
|
l = hl[0]
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
b += a >>> 16
|
||
|
c += b >>> 16
|
||
|
d += c >>> 16
|
||
|
hh[0] = ah0 = (c & 0xffff) | (d << 16)
|
||
|
hl[0] = al0 = (a & 0xffff) | (b << 16)
|
||
|
h = ah1
|
||
|
l = al1
|
||
|
a = l & 0xffff
|
||
|
b = l >>> 16
|
||
|
c = h & 0xffff
|
||
|
d = h >>> 16
|
||
|
h = hh[1]
|
||
|
l = hl[1]
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
b += a >>> 16
|
||
|
c += b >>> 16
|
||
|
d += c >>> 16
|
||
|
hh[1] = ah1 = (c & 0xffff) | (d << 16)
|
||
|
hl[1] = al1 = (a & 0xffff) | (b << 16)
|
||
|
h = ah2
|
||
|
l = al2
|
||
|
a = l & 0xffff
|
||
|
b = l >>> 16
|
||
|
c = h & 0xffff
|
||
|
d = h >>> 16
|
||
|
h = hh[2]
|
||
|
l = hl[2]
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
b += a >>> 16
|
||
|
c += b >>> 16
|
||
|
d += c >>> 16
|
||
|
hh[2] = ah2 = (c & 0xffff) | (d << 16)
|
||
|
hl[2] = al2 = (a & 0xffff) | (b << 16)
|
||
|
h = ah3
|
||
|
l = al3
|
||
|
a = l & 0xffff
|
||
|
b = l >>> 16
|
||
|
c = h & 0xffff
|
||
|
d = h >>> 16
|
||
|
h = hh[3]
|
||
|
l = hl[3]
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
b += a >>> 16
|
||
|
c += b >>> 16
|
||
|
d += c >>> 16
|
||
|
hh[3] = ah3 = (c & 0xffff) | (d << 16)
|
||
|
hl[3] = al3 = (a & 0xffff) | (b << 16)
|
||
|
h = ah4
|
||
|
l = al4
|
||
|
a = l & 0xffff
|
||
|
b = l >>> 16
|
||
|
c = h & 0xffff
|
||
|
d = h >>> 16
|
||
|
h = hh[4]
|
||
|
l = hl[4]
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
b += a >>> 16
|
||
|
c += b >>> 16
|
||
|
d += c >>> 16
|
||
|
hh[4] = ah4 = (c & 0xffff) | (d << 16)
|
||
|
hl[4] = al4 = (a & 0xffff) | (b << 16)
|
||
|
h = ah5
|
||
|
l = al5
|
||
|
a = l & 0xffff
|
||
|
b = l >>> 16
|
||
|
c = h & 0xffff
|
||
|
d = h >>> 16
|
||
|
h = hh[5]
|
||
|
l = hl[5]
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
b += a >>> 16
|
||
|
c += b >>> 16
|
||
|
d += c >>> 16
|
||
|
hh[5] = ah5 = (c & 0xffff) | (d << 16)
|
||
|
hl[5] = al5 = (a & 0xffff) | (b << 16)
|
||
|
h = ah6
|
||
|
l = al6
|
||
|
a = l & 0xffff
|
||
|
b = l >>> 16
|
||
|
c = h & 0xffff
|
||
|
d = h >>> 16
|
||
|
h = hh[6]
|
||
|
l = hl[6]
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
b += a >>> 16
|
||
|
c += b >>> 16
|
||
|
d += c >>> 16
|
||
|
hh[6] = ah6 = (c & 0xffff) | (d << 16)
|
||
|
hl[6] = al6 = (a & 0xffff) | (b << 16)
|
||
|
h = ah7
|
||
|
l = al7
|
||
|
a = l & 0xffff
|
||
|
b = l >>> 16
|
||
|
c = h & 0xffff
|
||
|
d = h >>> 16
|
||
|
h = hh[7]
|
||
|
l = hl[7]
|
||
|
a += l & 0xffff
|
||
|
b += l >>> 16
|
||
|
c += h & 0xffff
|
||
|
d += h >>> 16
|
||
|
b += a >>> 16
|
||
|
c += b >>> 16
|
||
|
d += c >>> 16
|
||
|
hh[7] = ah7 = (c & 0xffff) | (d << 16)
|
||
|
hl[7] = al7 = (a & 0xffff) | (b << 16)
|
||
|
pos += 128
|
||
|
n -= 128
|
||
|
}
|
||
|
return n
|
||
|
}
|
||
|
var sha512internal = function (out, m, n) {
|
||
|
var hh = new Int32Array(8),
|
||
|
hl = new Int32Array(8),
|
||
|
x = new Uint8Array(256),
|
||
|
i,
|
||
|
b = n
|
||
|
hh[0] = 0x6a09e667
|
||
|
hh[1] = 0xbb67ae85
|
||
|
hh[2] = 0x3c6ef372
|
||
|
hh[3] = 0xa54ff53a
|
||
|
hh[4] = 0x510e527f
|
||
|
hh[5] = 0x9b05688c
|
||
|
hh[6] = 0x1f83d9ab
|
||
|
hh[7] = 0x5be0cd19
|
||
|
hl[0] = 0xf3bcc908
|
||
|
hl[1] = 0x84caa73b
|
||
|
hl[2] = 0xfe94f82b
|
||
|
hl[3] = 0x5f1d36f1
|
||
|
hl[4] = 0xade682d1
|
||
|
hl[5] = 0x2b3e6c1f
|
||
|
hl[6] = 0xfb41bd6b
|
||
|
hl[7] = 0x137e2179
|
||
|
crypto_hashblocks_hl(hh, hl, m, n)
|
||
|
n %= 128
|
||
|
for (i = 0; i < n; i++) x[i] = m[b - n + i]
|
||
|
x[n] = 128
|
||
|
n = 256 - 128 * (n < 112 ? 1 : 0)
|
||
|
x[n - 9] = 0
|
||
|
ts64(x, n - 8, (b / 0x20000000) | 0, b << 3)
|
||
|
crypto_hashblocks_hl(hh, hl, x, n)
|
||
|
for (i = 0; i < 8; i++) ts64(out, 8 * i, hh[i], hl[i])
|
||
|
return 0
|
||
|
}
|
||
|
// sha512 is the standard sha512 cryptographic hash function. This is the
|
||
|
// default choice for Skynet operations, though many of the Sia protocol
|
||
|
// standards use blake2b instead, so you will see both.
|
||
|
var sha512 = function (m) {
|
||
|
let out = new Uint8Array(64)
|
||
|
sha512internal(out, m, m.length)
|
||
|
return out
|
||
|
}
|
||
|
// addContextToErr is a helper function that standardizes the formatting of
|
||
|
// adding context to an error. Within the world of go we discovered that being
|
||
|
// very persistent about layering context onto errors is incredibly helpful
|
||
|
// when debugging, even though it often creates comically verbose error
|
||
|
// messages. Trust me, it's well worth the tradeoff.
|
||
|
var addContextToErr = function (err, context) {
|
||
|
return new Error(context + ": " + err.message)
|
||
|
}
|
||
|
// DICTIONARY_UNIQUE_PREFIX defines the number of characters that are
|
||
|
// guaranteed to be unique for each word in the dictionary. The seed code only
|
||
|
// looks at these three characters when parsing a word, allowing users to make
|
||
|
// substitutions for words if they prefer or find it easier to memorize.
|
||
|
const DICTIONARY_UNIQUE_PREFIX = 3
|
||
|
// Define the number of entropy words used when generating the seed.
|
||
|
const SEED_ENTROPY_WORDS = 13
|
||
|
const SEED_CHECKSUM_WORDS = 2 // Not used, but left as documentation.
|
||
|
const SEED_BYTES = 16
|
||
|
// dictionary contains the word list for the mysky seed.
|
||
|
const dictionary = [
|
||
|
"abbey",
|
||
|
"ablaze",
|
||
|
"abort",
|
||
|
"absorb",
|
||
|
"abyss",
|
||
|
"aces",
|
||
|
"aching",
|
||
|
"acidic",
|
||
|
"across",
|
||
|
"acumen",
|
||
|
"adapt",
|
||
|
"adept",
|
||
|
"adjust",
|
||
|
"adopt",
|
||
|
"adult",
|
||
|
"aerial",
|
||
|
"afar",
|
||
|
"affair",
|
||
|
"afield",
|
||
|
"afloat",
|
||
|
"afoot",
|
||
|
"afraid",
|
||
|
"after",
|
||
|
"agenda",
|
||
|
"agile",
|
||
|
"aglow",
|
||
|
"agony",
|
||
|
"agreed",
|
||
|
"ahead",
|
||
|
"aided",
|
||
|
"aisle",
|
||
|
"ajar",
|
||
|
"akin",
|
||
|
"alarms",
|
||
|
"album",
|
||
|
"alerts",
|
||
|
"alley",
|
||
|
"almost",
|
||
|
"aloof",
|
||
|
"alpine",
|
||
|
"also",
|
||
|
"alumni",
|
||
|
"always",
|
||
|
"amaze",
|
||
|
"ambush",
|
||
|
"amidst",
|
||
|
"ammo",
|
||
|
"among",
|
||
|
"amply",
|
||
|
"amused",
|
||
|
"anchor",
|
||
|
"angled",
|
||
|
"ankle",
|
||
|
"antics",
|
||
|
"anvil",
|
||
|
"apart",
|
||
|
"apex",
|
||
|
"aphid",
|
||
|
"aplomb",
|
||
|
"apply",
|
||
|
"archer",
|
||
|
"ardent",
|
||
|
"arena",
|
||
|
"argue",
|
||
|
"arises",
|
||
|
"army",
|
||
|
"around",
|
||
|
"arrow",
|
||
|
"ascend",
|
||
|
"aside",
|
||
|
"asked",
|
||
|
"asleep",
|
||
|
"aspire",
|
||
|
"asylum",
|
||
|
"atlas",
|
||
|
"atom",
|
||
|
"atrium",
|
||
|
"attire",
|
||
|
"auburn",
|
||
|
"audio",
|
||
|
"august",
|
||
|
"aunt",
|
||
|
"autumn",
|
||
|
"avatar",
|
||
|
"avidly",
|
||
|
"avoid",
|
||
|
"awful",
|
||
|
"awning",
|
||
|
"awoken",
|
||
|
"axes",
|
||
|
"axis",
|
||
|
"axle",
|
||
|
"aztec",
|
||
|
"azure",
|
||
|
"baby",
|
||
|
"bacon",
|
||
|
"badge",
|
||
|
"bailed",
|
||
|
"bakery",
|
||
|
"bamboo",
|
||
|
"banjo",
|
||
|
"basin",
|
||
|
"batch",
|
||
|
"bawled",
|
||
|
"bays",
|
||
|
"beer",
|
||
|
"befit",
|
||
|
"begun",
|
||
|
"behind",
|
||
|
"being",
|
||
|
"below",
|
||
|
"bested",
|
||
|
"bevel",
|
||
|
"beware",
|
||
|
"beyond",
|
||
|
"bias",
|
||
|
"bids",
|
||
|
"bikini",
|
||
|
"birth",
|
||
|
"bite",
|
||
|
"blip",
|
||
|
"boat",
|
||
|
"bodies",
|
||
|
"bogeys",
|
||
|
"boil",
|
||
|
"boldly",
|
||
|
"bomb",
|
||
|
"border",
|
||
|
"boss",
|
||
|
"both",
|
||
|
"bovine",
|
||
|
"boxes",
|
||
|
"broken",
|
||
|
"brunt",
|
||
|
"bubble",
|
||
|
"budget",
|
||
|
"buffet",
|
||
|
"bugs",
|
||
|
"bulb",
|
||
|
"bumper",
|
||
|
"bunch",
|
||
|
"butter",
|
||
|
"buying",
|
||
|
"buzzer",
|
||
|
"byline",
|
||
|
"bypass",
|
||
|
"cabin",
|
||
|
"cactus",
|
||
|
"cadets",
|
||
|
"cafe",
|
||
|
"cage",
|
||
|
"cajun",
|
||
|
"cake",
|
||
|
"camp",
|
||
|
"candy",
|
||
|
"casket",
|
||
|
"catch",
|
||
|
"cause",
|
||
|
"cease",
|
||
|
"cedar",
|
||
|
"cell",
|
||
|
"cement",
|
||
|
"cent",
|
||
|
"chrome",
|
||
|
"cider",
|
||
|
"cigar",
|
||
|
"cinema",
|
||
|
"circle",
|
||
|
"claim",
|
||
|
"click",
|
||
|
"clue",
|
||
|
"coal",
|
||
|
"cobra",
|
||
|
"cocoa",
|
||
|
"code",
|
||
|
"coffee",
|
||
|
"cogs",
|
||
|
"coils",
|
||
|
"colony",
|
||
|
"comb",
|
||
|
"cool",
|
||
|
"copy",
|
||
|
"cousin",
|
||
|
"cowl",
|
||
|
"cube",
|
||
|
"cuffs",
|
||
|
"custom",
|
||
|
"dads",
|
||
|
"daft",
|
||
|
"dagger",
|
||
|
"daily",
|
||
|
"damp",
|
||
|
"dapper",
|
||
|
"darted",
|
||
|
"dash",
|
||
|
"dating",
|
||
|
"dawn",
|
||
|
"dazed",
|
||
|
"debut",
|
||
|
"decay",
|
||
|
"deftly",
|
||
|
"deity",
|
||
|
"dented",
|
||
|
"depth",
|
||
|
"desk",
|
||
|
"devoid",
|
||
|
"dice",
|
||
|
"diet",
|
||
|
"digit",
|
||
|
"dilute",
|
||
|
"dime",
|
||
|
"dinner",
|
||
|
"diode",
|
||
|
"ditch",
|
||
|
"divers",
|
||
|
"dizzy",
|
||
|
"doctor",
|
||
|
"dodge",
|
||
|
"does",
|
||
|
"dogs",
|
||
|
"doing",
|
||
|
"donuts",
|
||
|
"dosage",
|
||
|
"dotted",
|
||
|
"double",
|
||
|
"dove",
|
||
|
"down",
|
||
|
"dozen",
|
||
|
"dreams",
|
||
|
"drinks",
|
||
|
"drunk",
|
||
|
"drying",
|
||
|
"dual",
|
||
|
"dubbed",
|
||
|
"dude",
|
||
|
"duets",
|
||
|
"duke",
|
||
|
"dummy",
|
||
|
"dunes",
|
||
|
"duplex",
|
||
|
"dusted",
|
||
|
"duties",
|
||
|
"dwarf",
|
||
|
"dwelt",
|
||
|
"dying",
|
||
|
"each",
|
||
|
"eagle",
|
||
|
"earth",
|
||
|
"easy",
|
||
|
"eating",
|
||
|
"echo",
|
||
|
"eden",
|
||
|
"edgy",
|
||
|
"edited",
|
||
|
"eels",
|
||
|
"eggs",
|
||
|
"eight",
|
||
|
"either",
|
||
|
"eject",
|
||
|
"elapse",
|
||
|
"elbow",
|
||
|
"eldest",
|
||
|
"eleven",
|
||
|
"elite",
|
||
|
"elope",
|
||
|
"else",
|
||
|
"eluded",
|
||
|
"emails",
|
||
|
"ember",
|
||
|
"emerge",
|
||
|
"emit",
|
||
|
"empty",
|
||
|
"energy",
|
||
|
"enigma",
|
||
|
"enjoy",
|
||
|
"enlist",
|
||
|
"enmity",
|
||
|
"enough",
|
||
|
"ensign",
|
||
|
"envy",
|
||
|
"epoxy",
|
||
|
"equip",
|
||
|
"erase",
|
||
|
"error",
|
||
|
"estate",
|
||
|
"etched",
|
||
|
"ethics",
|
||
|
"excess",
|
||
|
"exhale",
|
||
|
"exit",
|
||
|
"exotic",
|
||
|
"extra",
|
||
|
"exult",
|
||
|
"fading",
|
||
|
"faked",
|
||
|
"fall",
|
||
|
"family",
|
||
|
"fancy",
|
||
|
"fatal",
|
||
|
"faulty",
|
||
|
"fawns",
|
||
|
"faxed",
|
||
|
"fazed",
|
||
|
"feast",
|
||
|
"feel",
|
||
|
"feline",
|
||
|
"fences",
|
||
|
"ferry",
|
||
|
"fever",
|
||
|
"fewest",
|
||
|
"fiat",
|
||
|
"fibula",
|
||
|
"fidget",
|
||
|
"fierce",
|
||
|
"fight",
|
||
|
"films",
|
||
|
"firm",
|
||
|
"five",
|
||
|
"fixate",
|
||
|
"fizzle",
|
||
|
"fleet",
|
||
|
"flying",
|
||
|
"foamy",
|
||
|
"focus",
|
||
|
"foes",
|
||
|
"foggy",
|
||
|
"foiled",
|
||
|
"fonts",
|
||
|
"fossil",
|
||
|
"fowls",
|
||
|
"foxes",
|
||
|
"foyer",
|
||
|
"framed",
|
||
|
"frown",
|
||
|
"fruit",
|
||
|
"frying",
|
||
|
"fudge",
|
||
|
"fuel",
|
||
|
"fully",
|
||
|
"fuming",
|
||
|
"fungal",
|
||
|
"future",
|
||
|
"fuzzy",
|
||
|
"gables",
|
||
|
"gadget",
|
||
|
"gags",
|
||
|
"gained",
|
||
|
"galaxy",
|
||
|
"gambit",
|
||
|
"gang",
|
||
|
"gasp",
|
||
|
"gather",
|
||
|
"gauze",
|
||
|
"gave",
|
||
|
"gawk",
|
||
|
"gaze",
|
||
|
"gecko",
|
||
|
"geek",
|
||
|
"gels",
|
||
|
"germs",
|
||
|
"geyser",
|
||
|
"ghetto",
|
||
|
"ghost",
|
||
|
"giant",
|
||
|
"giddy",
|
||
|
"gifts",
|
||
|
"gills",
|
||
|
"ginger",
|
||
|
"girth",
|
||
|
"giving",
|
||
|
"glass",
|
||
|
"glide",
|
||
|
"gnaw",
|
||
|
"gnome",
|
||
|
"goat",
|
||
|
"goblet",
|
||
|
"goes",
|
||
|
"going",
|
||
|
"gone",
|
||
|
"gopher",
|
||
|
"gossip",
|
||
|
"gotten",
|
||
|
"gown",
|
||
|
"grunt",
|
||
|
"guest",
|
||
|
"guide",
|
||
|
"gulp",
|
||
|
"guru",
|
||
|
"gusts",
|
||
|
"gutter",
|
||
|
"guys",
|
||
|
"gypsy",
|
||
|
"gyrate",
|
||
|
"hairy",
|
||
|
"having",
|
||
|
"hawk",
|
||
|
"hazard",
|
||
|
"heels",
|
||
|
"hefty",
|
||
|
"height",
|
||
|
"hence",
|
||
|
"heron",
|
||
|
"hiding",
|
||
|
"hijack",
|
||
|
"hiker",
|
||
|
"hills",
|
||
|
"hinder",
|
||
|
"hippo",
|
||
|
"hire",
|
||
|
"hive",
|
||
|
"hoax",
|
||
|
"hobby",
|
||
|
"hockey",
|
||
|
"hold",
|
||
|
"honked",
|
||
|
"hookup",
|
||
|
"hope",
|
||
|
"hornet",
|
||
|
"hotel",
|
||
|
"hover",
|
||
|
"howls",
|
||
|
"huddle",
|
||
|
"huge",
|
||
|
"hull",
|
||
|
"humid",
|
||
|
"hunter",
|
||
|
"huts",
|
||
|
"hybrid",
|
||
|
"hyper",
|
||
|
"icing",
|
||
|
"icon",
|
||
|
"idiom",
|
||
|
"idled",
|
||
|
"idols",
|
||
|
"igloo",
|
||
|
"ignore",
|
||
|
"iguana",
|
||
|
"impel",
|
||
|
"incur",
|
||
|
"injury",
|
||
|
"inline",
|
||
|
"inmate",
|
||
|
"input",
|
||
|
"insult",
|
||
|
"invoke",
|
||
|
"ionic",
|
||
|
"irate",
|
||
|
"iris",
|
||
|
"irony",
|
||
|
"island",
|
||
|
"issued",
|
||
|
"itches",
|
||
|
"items",
|
||
|
"itself",
|
||
|
"ivory",
|
||
|
"jabbed",
|
||
|
"jaded",
|
||
|
"jagged",
|
||
|
"jailed",
|
||
|
"jargon",
|
||
|
"jaunt",
|
||
|
"jaws",
|
||
|
"jazz",
|
||
|
"jeans",
|
||
|
"jeers",
|
||
|
"jester",
|
||
|
"jewels",
|
||
|
"jigsaw",
|
||
|
"jingle",
|
||
|
"jive",
|
||
|
"jobs",
|
||
|
"jockey",
|
||
|
"jogger",
|
||
|
"joking",
|
||
|
"jolted",
|
||
|
"jostle",
|
||
|
"joyous",
|
||
|
"judge",
|
||
|
"juicy",
|
||
|
"july",
|
||
|
"jump",
|
||
|
"junk",
|
||
|
"jury",
|
||
|
"karate",
|
||
|
"keep",
|
||
|
"kennel",
|
||
|
"kept",
|
||
|
"kettle",
|
||
|
"king",
|
||
|
"kiosk",
|
||
|
"kisses",
|
||
|
"kiwi",
|
||
|
"knee",
|
||
|
"knife",
|
||
|
"koala",
|
||
|
"ladder",
|
||
|
"lagoon",
|
||
|
"lair",
|
||
|
"lakes",
|
||
|
"lamb",
|
||
|
"laptop",
|
||
|
"large",
|
||
|
"last",
|
||
|
"later",
|
||
|
"lava",
|
||
|
"layout",
|
||
|
"lazy",
|
||
|
"ledge",
|
||
|
"leech",
|
||
|
"left",
|
||
|
"legion",
|
||
|
"lemon",
|
||
|
"lesson",
|
||
|
"liar",
|
||
|
"licks",
|
||
|
"lids",
|
||
|
"lied",
|
||
|
"light",
|
||
|
"lilac",
|
||
|
"limits",
|
||
|
"linen",
|
||
|
"lion",
|
||
|
"liquid",
|
||
|
"listen",
|
||
|
"lively",
|
||
|
"loaded",
|
||
|
"locker",
|
||
|
"lodge",
|
||
|
"lofty",
|
||
|
"logic",
|
||
|
"long",
|
||
|
"lopped",
|
||
|
"losing",
|
||
|
"loudly",
|
||
|
"love",
|
||
|
"lower",
|
||
|
"loyal",
|
||
|
"lucky",
|
||
|
"lumber",
|
||
|
"lunar",
|
||
|
"lurk",
|
||
|
"lush",
|
||
|
"luxury",
|
||
|
"lymph",
|
||
|
"lynx",
|
||
|
"lyrics",
|
||
|
"macro",
|
||
|
"mailed",
|
||
|
"major",
|
||
|
"makeup",
|
||
|
"malady",
|
||
|
"mammal",
|
||
|
"maps",
|
||
|
"match",
|
||
|
"maul",
|
||
|
"mayor",
|
||
|
"maze",
|
||
|
"meant",
|
||
|
"memoir",
|
||
|
"menu",
|
||
|
"merger",
|
||
|
"mesh",
|
||
|
"metro",
|
||
|
"mews",
|
||
|
"mice",
|
||
|
"midst",
|
||
|
"mighty",
|
||
|
"mime",
|
||
|
"mirror",
|
||
|
"misery",
|
||
|
"moat",
|
||
|
"mobile",
|
||
|
"mocked",
|
||
|
"mohawk",
|
||
|
"molten",
|
||
|
"moment",
|
||
|
"money",
|
||
|
"moon",
|
||
|
"mops",
|
||
|
"morsel",
|
||
|
"mostly",
|
||
|
"mouth",
|
||
|
"mowing",
|
||
|
"much",
|
||
|
"muddy",
|
||
|
"muffin",
|
||
|
"mugged",
|
||
|
"mullet",
|
||
|
"mumble",
|
||
|
"muppet",
|
||
|
"mural",
|
||
|
"muzzle",
|
||
|
"myriad",
|
||
|
"myth",
|
||
|
"nagged",
|
||
|
"nail",
|
||
|
"names",
|
||
|
"nanny",
|
||
|
"napkin",
|
||
|
"nasty",
|
||
|
"navy",
|
||
|
"nearby",
|
||
|
"needed",
|
||
|
"neon",
|
||
|
"nephew",
|
||
|
"nerves",
|
||
|
"nestle",
|
||
|
"never",
|
||
|
"newt",
|
||
|
"nexus",
|
||
|
"nibs",
|
||
|
"niche",
|
||
|
"niece",
|
||
|
"nifty",
|
||
|
"nimbly",
|
||
|
"nobody",
|
||
|
"nodes",
|
||
|
"noises",
|
||
|
"nomad",
|
||
|
"noted",
|
||
|
"nouns",
|
||
|
"nozzle",
|
||
|
"nuance",
|
||
|
"nudged",
|
||
|
"nugget",
|
||
|
"null",
|
||
|
"number",
|
||
|
"nuns",
|
||
|
"nurse",
|
||
|
"nylon",
|
||
|
"oaks",
|
||
|
"oars",
|
||
|
"oasis",
|
||
|
"object",
|
||
|
"occur",
|
||
|
"ocean",
|
||
|
"odds",
|
||
|
"offend",
|
||
|
"often",
|
||
|
"okay",
|
||
|
"older",
|
||
|
"olive",
|
||
|
"omega",
|
||
|
"onion",
|
||
|
"online",
|
||
|
"onto",
|
||
|
"onward",
|
||
|
"oozed",
|
||
|
"opened",
|
||
|
"opus",
|
||
|
"orange",
|
||
|
"orbit",
|
||
|
"orchid",
|
||
|
"orders",
|
||
|
"organs",
|
||
|
"origin",
|
||
|
"oscar",
|
||
|
"otter",
|
||
|
"ouch",
|
||
|
"ought",
|
||
|
"ounce",
|
||
|
"oust",
|
||
|
"oval",
|
||
|
"oven",
|
||
|
"owed",
|
||
|
"owls",
|
||
|
"owner",
|
||
|
"oxygen",
|
||
|
"oyster",
|
||
|
"ozone",
|
||
|
"pact",
|
||
|
"pager",
|
||
|
"palace",
|
||
|
"paper",
|
||
|
"pastry",
|
||
|
"patio",
|
||
|
"pause",
|
||
|
"peeled",
|
||
|
"pegs",
|
||
|
"pencil",
|
||
|
"people",
|
||
|
"pepper",
|
||
|
"pests",
|
||
|
"petals",
|
||
|
"phase",
|
||
|
"phone",
|
||
|
"piano",
|
||
|
"picked",
|
||
|
"pierce",
|
||
|
"pimple",
|
||
|
"pirate",
|
||
|
"pivot",
|
||
|
"pixels",
|
||
|
"pizza",
|
||
|
"pledge",
|
||
|
"pliers",
|
||
|
"plus",
|
||
|
"poetry",
|
||
|
"point",
|
||
|
"poker",
|
||
|
"polar",
|
||
|
"ponies",
|
||
|
"pool",
|
||
|
"potato",
|
||
|
"pouch",
|
||
|
"powder",
|
||
|
"pram",
|
||
|
"pride",
|
||
|
"pruned",
|
||
|
"prying",
|
||
|
"public",
|
||
|
"puck",
|
||
|
"puddle",
|
||
|
"puffin",
|
||
|
"pulp",
|
||
|
"punch",
|
||
|
"puppy",
|
||
|
"purged",
|
||
|
"push",
|
||
|
"putty",
|
||
|
"pylons",
|
||
|
"python",
|
||
|
"queen",
|
||
|
"quick",
|
||
|
"quote",
|
||
|
"radar",
|
||
|
"rafts",
|
||
|
"rage",
|
||
|
"raking",
|
||
|
"rally",
|
||
|
"ramped",
|
||
|
"rapid",
|
||
|
"rarest",
|
||
|
"rash",
|
||
|
"rated",
|
||
|
"ravine",
|
||
|
"rays",
|
||
|
"razor",
|
||
|
"react",
|
||
|
"rebel",
|
||
|
"recipe",
|
||
|
"reduce",
|
||
|
"reef",
|
||
|
"refer",
|
||
|
"reheat",
|
||
|
"relic",
|
||
|
"remedy",
|
||
|
"repent",
|
||
|
"reruns",
|
||
|
"rest",
|
||
|
"return",
|
||
|
"revamp",
|
||
|
"rewind",
|
||
|
"rhino",
|
||
|
"rhythm",
|
||
|
"ribbon",
|
||
|
"richly",
|
||
|
"ridges",
|
||
|
"rift",
|
||
|
"rigid",
|
||
|
"rims",
|
||
|
"riots",
|
||
|
"ripped",
|
||
|
"rising",
|
||
|
"ritual",
|
||
|
"river",
|
||
|
"roared",
|
||
|
"robot",
|
||
|
"rodent",
|
||
|
"rogue",
|
||
|
"roles",
|
||
|
"roomy",
|
||
|
"roped",
|
||
|
"roster",
|
||
|
"rotate",
|
||
|
"rover",
|
||
|
"royal",
|
||
|
"ruby",
|
||
|
"rudely",
|
||
|
"rugged",
|
||
|
"ruined",
|
||
|
"ruling",
|
||
|
"rumble",
|
||
|
"runway",
|
||
|
"rural",
|
||
|
"sack",
|
||
|
"safety",
|
||
|
"saga",
|
||
|
"sailor",
|
||
|
"sake",
|
||
|
"salads",
|
||
|
"sample",
|
||
|
"sanity",
|
||
|
"sash",
|
||
|
"satin",
|
||
|
"saved",
|
||
|
"scenic",
|
||
|
"school",
|
||
|
"scoop",
|
||
|
"scrub",
|
||
|
"scuba",
|
||
|
"second",
|
||
|
"sedan",
|
||
|
"seeded",
|
||
|
"setup",
|
||
|
"sewage",
|
||
|
"sieve",
|
||
|
"silk",
|
||
|
"sipped",
|
||
|
"siren",
|
||
|
"sizes",
|
||
|
"skater",
|
||
|
"skew",
|
||
|
"skulls",
|
||
|
"slid",
|
||
|
"slower",
|
||
|
"slug",
|
||
|
"smash",
|
||
|
"smog",
|
||
|
"snake",
|
||
|
"sneeze",
|
||
|
"sniff",
|
||
|
"snout",
|
||
|
"snug",
|
||
|
"soapy",
|
||
|
"sober",
|
||
|
"soccer",
|
||
|
"soda",
|
||
|
"soggy",
|
||
|
"soil",
|
||
|
"solved",
|
||
|
"sonic",
|
||
|
"soothe",
|
||
|
"sorry",
|
||
|
"sowed",
|
||
|
"soya",
|
||
|
"space",
|
||
|
"speedy",
|
||
|
"sphere",
|
||
|
"spout",
|
||
|
"sprig",
|
||
|
"spud",
|
||
|
"spying",
|
||
|
"square",
|
||
|
"stick",
|
||
|
"subtly",
|
||
|
"suede",
|
||
|
"sugar",
|
||
|
"summon",
|
||
|
"sunken",
|
||
|
"surfer",
|
||
|
"sushi",
|
||
|
"suture",
|
||
|
"swept",
|
||
|
"sword",
|
||
|
"swung",
|
||
|
"system",
|
||
|
"taboo",
|
||
|
"tacit",
|
||
|
"tagged",
|
||
|
"tail",
|
||
|
"taken",
|
||
|
"talent",
|
||
|
"tamper",
|
||
|
"tanks",
|
||
|
"tasked",
|
||
|
"tattoo",
|
||
|
"taunts",
|
||
|
"tavern",
|
||
|
"tawny",
|
||
|
"taxi",
|
||
|
"tell",
|
||
|
"tender",
|
||
|
"tepid",
|
||
|
"tether",
|
||
|
"thaw",
|
||
|
"thorn",
|
||
|
"thumbs",
|
||
|
"thwart",
|
||
|
"ticket",
|
||
|
"tidy",
|
||
|
"tiers",
|
||
|
"tiger",
|
||
|
"tilt",
|
||
|
"timber",
|
||
|
"tinted",
|
||
|
"tipsy",
|
||
|
"tirade",
|
||
|
"tissue",
|
||
|
"titans",
|
||
|
"today",
|
||
|
"toffee",
|
||
|
"toilet",
|
||
|
"token",
|
||
|
"tonic",
|
||
|
"topic",
|
||
|
"torch",
|
||
|
"tossed",
|
||
|
"total",
|
||
|
"touchy",
|
||
|
"towel",
|
||
|
"toxic",
|
||
|
"toyed",
|
||
|
"trash",
|
||
|
"trendy",
|
||
|
"tribal",
|
||
|
"truth",
|
||
|
"trying",
|
||
|
"tubes",
|
||
|
"tucks",
|
||
|
"tudor",
|
||
|
"tufts",
|
||
|
"tugs",
|
||
|
"tulips",
|
||
|
"tunnel",
|
||
|
"turnip",
|
||
|
"tusks",
|
||
|
"tutor",
|
||
|
"tuxedo",
|
||
|
"twang",
|
||
|
"twice",
|
||
|
"tycoon",
|
||
|
"typist",
|
||
|
"tyrant",
|
||
|
"ugly",
|
||
|
"ulcers",
|
||
|
"umpire",
|
||
|
"uncle",
|
||
|
"under",
|
||
|
"uneven",
|
||
|
"unfit",
|
||
|
"union",
|
||
|
"unmask",
|
||
|
"unrest",
|
||
|
"unsafe",
|
||
|
"until",
|
||
|
"unveil",
|
||
|
"unwind",
|
||
|
"unzip",
|
||
|
"upbeat",
|
||
|
"update",
|
||
|
"uphill",
|
||
|
"upkeep",
|
||
|
"upload",
|
||
|
"upon",
|
||
|
"upper",
|
||
|
"urban",
|
||
|
"urgent",
|
||
|
"usage",
|
||
|
"useful",
|
||
|
"usher",
|
||
|
"using",
|
||
|
"usual",
|
||
|
"utmost",
|
||
|
"utopia",
|
||
|
"vague",
|
||
|
"vain",
|
||
|
"value",
|
||
|
"vane",
|
||
|
"vary",
|
||
|
"vats",
|
||
|
"vaults",
|
||
|
"vector",
|
||
|
"veered",
|
||
|
"vegan",
|
||
|
"vein",
|
||
|
"velvet",
|
||
|
"vessel",
|
||
|
"vexed",
|
||
|
"vials",
|
||
|
"victim",
|
||
|
"video",
|
||
|
"viking",
|
||
|
"violin",
|
||
|
"vipers",
|
||
|
"vitals",
|
||
|
"vivid",
|
||
|
"vixen",
|
||
|
"vocal",
|
||
|
"vogue",
|
||
|
"voice",
|
||
|
"vortex",
|
||
|
"voted",
|
||
|
"vowels",
|
||
|
"voyage",
|
||
|
"wade",
|
||
|
"waffle",
|
||
|
"waist",
|
||
|
"waking",
|
||
|
"wanted",
|
||
|
"warped",
|
||
|
"water",
|
||
|
"waxing",
|
||
|
"wedge",
|
||
|
"weird",
|
||
|
"went",
|
||
|
"wept",
|
||
|
"were",
|
||
|
"whale",
|
||
|
"when",
|
||
|
"whole",
|
||
|
"width",
|
||
|
"wield",
|
||
|
"wife",
|
||
|
"wiggle",
|
||
|
"wildly",
|
||
|
"winter",
|
||
|
"wiring",
|
||
|
"wise",
|
||
|
"wives",
|
||
|
"wizard",
|
||
|
"wobbly",
|
||
|
"woes",
|
||
|
"woken",
|
||
|
"wolf",
|
||
|
"woozy",
|
||
|
"worry",
|
||
|
"woven",
|
||
|
"wrap",
|
||
|
"wrist",
|
||
|
"wrong",
|
||
|
"yacht",
|
||
|
"yahoo",
|
||
|
"yanks",
|
||
|
]
|
||
|
// seedToChecksumWords will compute the two checksum words for the provided
|
||
|
// seed. The two return values are the two checksum words.
|
||
|
var seedToChecksumWords = function (seed) {
|
||
|
// Input validation.
|
||
|
if (seed.length !== SEED_BYTES) {
|
||
|
return [null, null, new Error(`seed has the wrong length: ${seed.length}`)]
|
||
|
}
|
||
|
// Get the hash.
|
||
|
let h = sha512(seed)
|
||
|
// Turn the hash into two words.
|
||
|
let word1 = h[0] << 8
|
||
|
word1 += h[1]
|
||
|
word1 >>= 6
|
||
|
let word2 = h[1] << 10
|
||
|
word2 &= 0xffff
|
||
|
word2 += h[2] << 2
|
||
|
word2 >>= 6
|
||
|
return [dictionary[word1], dictionary[word2], null]
|
||
|
}
|
||
|
// validSeedPhrase checks whether the provided seed phrase is valid, returning
|
||
|
// an error if not. If the seed phrase is valid, the full seed will be returned
|
||
|
// as a Uint8Array.
|
||
|
var validSeedPhrase = function (seedPhrase) {
|
||
|
// Create a helper function to make the below code more readable.
|
||
|
let prefix = function (s) {
|
||
|
return s.slice(0, DICTIONARY_UNIQUE_PREFIX)
|
||
|
}
|
||
|
// Pull the seed into its respective parts.
|
||
|
let seedWordsAndChecksum = seedPhrase.split(" ")
|
||
|
let seedWords = seedWordsAndChecksum.slice(0, SEED_ENTROPY_WORDS)
|
||
|
let checksumOne = seedWordsAndChecksum[SEED_ENTROPY_WORDS]
|
||
|
let checksumTwo = seedWordsAndChecksum[SEED_ENTROPY_WORDS + 1]
|
||
|
// Convert the seedWords to a seed.
|
||
|
let [seed, err1] = seedWordsToSeed(seedWords)
|
||
|
if (err1 !== null) {
|
||
|
return [null, addContextToErr(err1, "unable to parse seed phrase")]
|
||
|
}
|
||
|
let [checksumOneVerify, checksumTwoVerify, err2] = seedToChecksumWords(seed)
|
||
|
if (err2 !== null) {
|
||
|
return [null, addContextToErr(err2, "could not compute checksum words")]
|
||
|
}
|
||
|
if (prefix(checksumOne) !== prefix(checksumOneVerify)) {
|
||
|
return [null, new Error("first checksum word is invalid")]
|
||
|
}
|
||
|
if (prefix(checksumTwo) !== prefix(checksumTwoVerify)) {
|
||
|
return [null, new Error("second checksum word is invalid")]
|
||
|
}
|
||
|
return [seed, null]
|
||
|
}
|
||
|
// seedWordsToSeed will convert a provided seed phrase to to a Uint8Array that
|
||
|
// represents the cryptographic seed in bytes.
|
||
|
var seedWordsToSeed = function (seedWords) {
|
||
|
// Input checking.
|
||
|
if (seedWords.length !== SEED_ENTROPY_WORDS) {
|
||
|
return [
|
||
|
null,
|
||
|
new Error(`Seed words should have length ${SEED_ENTROPY_WORDS} but has length ${seedWords.length}`),
|
||
|
]
|
||
|
}
|
||
|
// We are getting 16 bytes of entropy.
|
||
|
const bytes = new Uint8Array(SEED_BYTES)
|
||
|
let curByte = 0
|
||
|
let curBit = 0
|
||
|
for (let i = 0; i < SEED_ENTROPY_WORDS; i++) {
|
||
|
// Determine which number corresponds to the next word.
|
||
|
let word = -1
|
||
|
for (let j = 0; j < dictionary.length; j++) {
|
||
|
if (seedWords[i].slice(0, DICTIONARY_UNIQUE_PREFIX) === dictionary[j].slice(0, DICTIONARY_UNIQUE_PREFIX)) {
|
||
|
word = j
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if (word === -1) {
|
||
|
return [null, new Error(`word '${seedWords[i]}' at index ${i} not found in dictionary`)]
|
||
|
}
|
||
|
let wordBits = 10
|
||
|
if (i === SEED_ENTROPY_WORDS - 1) {
|
||
|
wordBits = 8
|
||
|
}
|
||
|
// Iterate over the bits of the 10- or 8-bit word.
|
||
|
for (let j = 0; j < wordBits; j++) {
|
||
|
const bitSet = (word & (1 << (wordBits - j - 1))) > 0
|
||
|
if (bitSet) {
|
||
|
bytes[curByte] |= 1 << (8 - curBit - 1)
|
||
|
}
|
||
|
curBit += 1
|
||
|
if (curBit >= 8) {
|
||
|
// Current byte has 8 bits, go to the next byte.
|
||
|
curByte += 1
|
||
|
curBit = 0
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return [bytes, null]
|
||
|
}
|
||
|
// setErrorText sets the errorText item in the DOM. This function is mainly
|
||
|
// used for readability.
|
||
|
var setErrorText = function (t) {
|
||
|
document.getElementById("errorText").textContent = t
|
||
|
}
|
||
|
// generateSeedPhrase will generate and verify a seed phrase for the user.
|
||
|
var generateSeedPhrase = function () {
|
||
|
// Get the random numbers for the seed phrase. Typically, you need to
|
||
|
// have code that avoids bias by checking the random results and
|
||
|
// re-rolling the random numbers if the result is outside of the range
|
||
|
// of numbers that would produce no bias. Because the search space
|
||
|
// (1024) evenly divides the random number space (2^16), we can skip
|
||
|
// this step and just use a modulus instead. The result will have no
|
||
|
// bias, but only because the search space is a power of 2.
|
||
|
let randNums = new Uint16Array(SEED_ENTROPY_WORDS)
|
||
|
crypto.getRandomValues(randNums)
|
||
|
// Consistency check to verify the above statement.
|
||
|
if (dictionary.length !== 1024) {
|
||
|
setErrorText("ERROR: the dictionary is the wrong length!")
|
||
|
return
|
||
|
}
|
||
|
// Generate the seed phrase from the randNums.
|
||
|
let seedWords = []
|
||
|
for (let i = 0; i < SEED_ENTROPY_WORDS; i++) {
|
||
|
let wordIndex = randNums[i] % dictionary.length
|
||
|
if (i === 12) {
|
||
|
wordIndex = randNums[i] % (dictionary.length / 4)
|
||
|
}
|
||
|
seedWords.push(dictionary[wordIndex])
|
||
|
}
|
||
|
// Convert the seedWords to a seed.
|
||
|
let [seed, err1] = seedWordsToSeed(seedWords)
|
||
|
if (err1 !== null) {
|
||
|
setErrorText("ERROR: Unable to parse generated seed: " + err1)
|
||
|
return
|
||
|
}
|
||
|
// Compute the checksum.
|
||
|
let [checksumOne, checksumTwo, err2] = seedToChecksumWords(seed)
|
||
|
if (err2 !== null) {
|
||
|
setErrorText("ERROR: Unable to compute checksum: " + err2)
|
||
|
return
|
||
|
}
|
||
|
// Assemble the final seed phrase and set the text field.
|
||
|
let allWords = [...seedWords, checksumOne, checksumTwo]
|
||
|
let seedPhrase = allWords.join(" ")
|
||
|
document.getElementById("seedText").textContent = seedPhrase
|
||
|
return
|
||
|
}
|
||
|
function bufToHex(buf) {
|
||
|
return [...buf].map((x) => x.toString(16).padStart(2, "0")).join("")
|
||
|
}
|
||
|
// authUser is a function which will inspect the value of the input field to
|
||
|
// find the seed, and then will set the user's local seed to that value.
|
||
|
var authUser = function () {
|
||
|
// Check that the user has provided a seed.
|
||
|
var userSeed = document.getElementById("seedInput")
|
||
|
if (userSeed === null) {
|
||
|
setErrorText("ERROR: user seed field not found")
|
||
|
return
|
||
|
}
|
||
|
// Validate the seed.
|
||
|
let [seed, errVSP] = validSeedPhrase(userSeed.value)
|
||
|
if (errVSP !== null) {
|
||
|
setErrorText("Seed is not valid: " + errVSP)
|
||
|
return
|
||
|
}
|
||
|
// Take the seed and store it in localStorage.
|
||
|
let seedStr = bufToHex(seed)
|
||
|
window.localStorage.setItem("v1-seed", seedStr)
|
||
|
// If there was a window opener, we should send a message to
|
||
|
// the opener indicating that auth was successful, and then close
|
||
|
// this window. Otherwise, we should just refresh the page.
|
||
|
if (window.opener) {
|
||
|
// Send a postmessage back to the caller that auth was successful. This
|
||
|
// is one of the few places where a wildcard can be used by the
|
||
|
// postMessage because we are comfortable declaring to all pages that
|
||
|
// the user has logged into the kernel.
|
||
|
try {
|
||
|
window.opener.postMessage({ kernelMethod: "authCompleted" }, "*")
|
||
|
window.close()
|
||
|
} catch (errC) {
|
||
|
setErrorText("Unable to report that authentication suceeded: " + errC)
|
||
|
}
|
||
|
} else {
|
||
|
location.reload()
|
||
|
}
|
||
|
}
|
||
|
var logOut = function () {
|
||
|
// Log out by clearing localstorage.
|
||
|
window.localStorage.clear()
|
||
|
// If there was a window opener, we should send a message to
|
||
|
// the opener indicating that auth was successful, and then close
|
||
|
// this window. Otherwise, we should just refresh the page.
|
||
|
if (window.opener) {
|
||
|
// Send a postmessage back to the caller that auth was successful. This
|
||
|
// is one of the few places where a wildcard can be used by the
|
||
|
// postMessage because we are comfortable declaring to all pages that
|
||
|
// the user has logged into the kernel.
|
||
|
try {
|
||
|
window.opener.postMessage({ kernelMethod: "logOutSucces" }, "*")
|
||
|
window.close()
|
||
|
} catch (errC) {
|
||
|
setErrorText("Unable to report that authentication suceeded: " + errC)
|
||
|
}
|
||
|
} else {
|
||
|
location.reload()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Check localStorage for the user seed.
|
||
|
let userSeedStr = window.localStorage.getItem("v1-seed")
|
||
|
if (userSeedStr === null) {
|
||
|
// Create the auth form and perform authentication.
|
||
|
var banner = document.createElement("h1")
|
||
|
banner.textContent = "Login to Lume Web"
|
||
|
var seedInput = document.createElement("input")
|
||
|
seedInput.type = "text"
|
||
|
seedInput.placeholder = "Enter seed phrase here"
|
||
|
seedInput.id = "seedInput"
|
||
|
var submitButton = document.createElement("input")
|
||
|
submitButton.type = "button"
|
||
|
submitButton.value = "Submit"
|
||
|
submitButton.onclick = authUser
|
||
|
var errorText = document.createElement("p")
|
||
|
errorText.id = "errorText"
|
||
|
errorText.textContent = ""
|
||
|
var generateSeedButton = document.createElement("input")
|
||
|
generateSeedButton.type = "button"
|
||
|
generateSeedButton.value = "Generate Seed"
|
||
|
generateSeedButton.onclick = generateSeedPhrase
|
||
|
var seedText = document.createElement("p")
|
||
|
seedText.id = "seedText"
|
||
|
seedText.textContent = ""
|
||
|
document.body.appendChild(banner)
|
||
|
document.body.appendChild(seedInput)
|
||
|
document.body.appendChild(submitButton)
|
||
|
document.body.appendChild(errorText)
|
||
|
document.body.appendChild(generateSeedButton)
|
||
|
document.body.appendChild(seedText)
|
||
|
} else {
|
||
|
// Create the logout button.
|
||
|
var banner = document.createElement("h1")
|
||
|
banner.textContent = "You are logged into Lume Web"
|
||
|
var logOutButton = document.createElement("input")
|
||
|
logOutButton.type = "button"
|
||
|
logOutButton.value = "Log Out"
|
||
|
logOutButton.onclick = logOut
|
||
|
var errorText = document.createElement("p")
|
||
|
errorText.id = "errorText"
|
||
|
errorText.textContent = ""
|
||
|
document.body.appendChild(banner)
|
||
|
document.body.appendChild(logOutButton)
|
||
|
document.body.appendChild(errorText)
|
||
|
}
|
||
|
</script>
|
||
|
</body>
|
||
|
</html>
|