Created
September 18, 2024 15:15
-
-
Save levelone/a9ea9c67d21fb948ca41d8cb96acc18d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// refactored | |
const rotate_left = (n, s) => { | |
let t4 = (n << s) | (n >>> (32 - s)) | |
return t4 | |
} | |
const lsb_hex = (val) => { // this doesn't seem to be used anywhere ??? | |
let str = '' | |
for (let i = 0; i <= 6; i += 2) { | |
let vh = (val >>> (i * 4 + 4)) & 0x0f | |
let vl = (val >>> (i * 4)) & 0x0f | |
str += vh.toString(16) + vl.toString(16) | |
} | |
return str | |
} | |
const cvt_hex = (val) => { | |
let str = '' | |
for (let i = 7; i >= 0; i--) { | |
let v = (val >>> (i * 4)) & 0x0f | |
str += v.toString(16) | |
} | |
return str | |
} | |
const Utf8Encode = (string) => { | |
let cleanString = string.replace(/\r\n/g, '\n') | |
let utftext = '' | |
for (let n = 0; n < cleanString.length; n++) { | |
let c = cleanString.charCodeAt(n) | |
if (c < 128) { | |
utftext += String.fromCharCode(c) | |
} else if ((c > 127) && (c < 2048)) { | |
utftext += String.fromCharCode((c >> 6) | 192) | |
utftext += String.fromCharCode((c & 63) | 128) | |
} else { | |
utftext += String.fromCharCode((c >> 12) | 224) | |
utftext += String.fromCharCode(((c >> 6) & 63) | 128) | |
utftext += String.fromCharCode((c & 63) | 128) | |
} | |
} | |
return utftext | |
} | |
const mint = (resource, bits, callback) => { | |
let stamp = new Stamp( | |
resource, | |
bits | |
) | |
return stamp.work(callback) | |
} | |
const hexSha1 = (msg) => { | |
let array = sha1(msg) | |
return cvt_hex(array[0]) + cvt_hex(array[1]) + cvt_hex(array[2]) + cvt_hex(array3) + cvt_hex(array[4]) | |
} | |
/** | |
* Secure Hash Algorithm (SHA1) | |
* http://www.webtoolkit.info/ | |
**/ | |
const sha1 = (message) => { | |
let blockstart | |
let i, j | |
let W = new Array(80) | |
let H0 = 0x67452301 | |
let H1 = 0xEFCDAB89 | |
let H2 = 0x98BADCFE | |
let H3 = 0x10325476 | |
let H4 = 0xC3D2E1F0 | |
let A, B, C, D, E | |
let temp | |
msg = Utf8Encode(message) | |
let msg_len = msg.length | |
let word_array = new Array() | |
for (i = 0; i < msg_len - 3; i += 4) { | |
j = msg.charCodeAt(i) << 24 | msg.charCodeAt(i + 1) << 16 | | |
msg.charCodeAt(i + 2) << 8 | msg.charCodeAt(i + 3) | |
word_array.push(j) | |
} | |
switch (msg_len % 4) { | |
case 0: | |
i = 0x080000000 | |
break | |
case 1: | |
i = msg.charCodeAt(msg_len - 1) << 24 | 0x0800000 | |
break | |
case 2: | |
i = msg.charCodeAt(msg_len - 2) << 24 | msg.charCodeAt(msg_len - 1) << 16 | 0x08000 | |
break | |
case 3: | |
i = msg.charCodeAt(msg_len - 3) << 24 | msg.charCodeAt(msg_len - 2) << 16 | msg.charCodeAt(msg_len - 1) << 8 | 0x80 | |
break | |
} | |
word_array.push(i) | |
while ((word_array.length % 16) != 14) | |
word_array.push(0) | |
word_array.push(msg_len >>> 29) | |
word_array.push((msg_len << 3) & 0x0ffffffff) | |
for (blockstart = 0; blockstart < word_array.length; blockstart += 16) { | |
for (i = 0; i < 16; i++) | |
W[i] = word_array[blockstart + i] | |
for (i = 16; i <= 79; i++) | |
W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1) | |
A = H0 | |
B = H1 | |
C = H2 | |
D = H3 | |
E = H4 | |
for (i = 0; i <= 19; i++) { | |
temp = (rotate_left(A, 5) + ((B & C) | (~B & D)) + E + W[i] + 0x5A827999) & 0x0ffffffff | |
E = D | |
D = C | |
C = rotate_left(B, 30) | |
B = A | |
A = temp | |
} | |
for (i = 20; i <= 39; i++) { | |
temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff | |
E = D | |
D = C | |
C = rotate_left(B, 30) | |
B = A | |
A = temp | |
} | |
for (i = 40; i <= 59; i++) { | |
temp = (rotate_left(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff | |
E = D | |
D = C | |
C = rotate_left(B, 30) | |
B = A | |
A = temp | |
} | |
for (i = 60; i <= 79; i++) { | |
temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff | |
E = D | |
D = C | |
C = rotate_left(B, 30) | |
B = A | |
A = temp | |
} | |
H0 = (H0 + A) & 0x0ffffffff | |
H1 = (H1 + B) & 0x0ffffffff | |
H2 = (H2 + C) & 0x0ffffffff | |
H3 = (H3 + D) & 0x0ffffffff | |
H4 = (H4 + E) & 0x0ffffffff | |
} | |
return [H0, H1, H2, H3, H4] | |
} | |
class Stamp { | |
constructor (resource, bits, counter = 0) { | |
this.login_email = document.querySelector('input#login_email').value | |
this.password = document.querySelector('input#password').value | |
this.resource = resource | |
this.bits = bits | |
this.counter = counter | |
} | |
toString () { | |
return [this.login_email, this.password, this.resource, this.bits, this.counter].join(':') | |
} | |
toPublicString () { | |
return [this.resource, this.bits, this.counter].join(':') | |
} | |
check () { | |
let array = sha1(this.toString()) | |
return array[0] >> (160-this.bits) == 0 | |
} | |
startClock () { | |
this.startedAt || (this.startedAt = performance.now()) | |
} | |
stopClock () { | |
this.endedAt || (this.endedAt = performance.now()) | |
let duration = this.endedAt - this.startedAt | |
let speed = Math.round(this.counter * 1000 / duration) // what is the point of this ??? | |
} | |
// Trigger the given callback when the problem is solved. | |
// In order to not freeze the page, setTimeout is called every 100ms to let some CPU to other tasks. | |
work (callback) { | |
this.startClock() | |
let timer = performance.now() | |
while (!this.check()) | |
if (this.counter++ && performance.now() - timer > 100) | |
return setTimeout(this.work.bind(this), 0, callback) | |
this.stopClock() | |
callback(this) | |
} | |
} | |
class Magic { | |
constructor (input) { | |
let options = JSON.parse(input.getAttribute('data-magic')) | |
input.dispatchEvent(new CustomEvent('magic:mint', {bubbles: true})) | |
mint(options.resource, options.bits, (stamp) => { | |
input.value = stamp.toPublicString() | |
input.dispatchEvent( | |
new CustomEvent('magic:minted', { | |
bubbles: true, detail: { stamp: stamp } | |
}) | |
) | |
input.form.submit() | |
}) | |
} | |
} | |
// end refactored | |
const setup = () => { | |
let input = document.querySelector('input#magic') | |
if (document.readyState != 'loading') { | |
input.form.onsubmit = function(event) { | |
event.preventDefault() | |
new Magic(input) | |
} | |
} else | |
document.addEventListener('DOMContentLoaded', setup ) | |
} | |
export default function () { | |
setup() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment