Skip to content

Instantly share code, notes, and snippets.

@levelone
Created September 18, 2024 15:15
Show Gist options
  • Save levelone/a9ea9c67d21fb948ca41d8cb96acc18d to your computer and use it in GitHub Desktop.
Save levelone/a9ea9c67d21fb948ca41d8cb96acc18d to your computer and use it in GitHub Desktop.
// 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