-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
158 lines (134 loc) · 4.48 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
const container = document.getElementById('container')
const canvas = document.getElementById('canvas')
const context = canvas.getContext('2d')
const qrdataEl = document.getElementById('qrdata')
const saltEl = document.getElementById('salt')
const nonceEl = document.getElementById('nonce')
const encryptedEl = document.getElementById('encrypted')
const tagEl = document.getElementById('tag')
const oneEl = document.getElementById('one')
const twoEl = document.getElementById('two')
const threeEl = document.getElementById('three')
const fourEl = document.getElementById('four')
const keyEl = document.getElementById('key')
const decryptedEl = document.getElementById('decrypted')
const button = document.getElementById('button')
button.innerHTML = "Start"
button.onclick = startVideo
let qrworker = null
let video = null
function startVideo() {
button.innerHTML = "Stop"
button.onclick = stopVideo
qrworker = new Worker(new URL('./qrworker.js', import.meta.url),
{type: 'module'})
qrworker.onmessage = (message) => {
stopVideo()
startDecrypt(message.data)
}
video = document.createElement('video')
navigator.mediaDevices.getUserMedia({
audio: false,
video: {facingMode: 'environment'}
}).then(stream => {
video.srcObject = stream
video.setAttribute('playsinline', 'true')
video.play()
requestAnimationFrame(tick)
})
}
function stopVideo() {
qrworker.terminate()
video.pause()
video.srcObject.getVideoTracks().forEach(track => track.stop())
video.srcObject = null
button.innerHTML = "Start"
button.onclick = startVideo
}
let oldTime = 0
function tick(time) {
if (video.readyState === video.HAVE_ENOUGH_DATA) {
canvas.width = Math.min(container.clientWidth, video.videoWidth)
canvas.height = Math.min(container.clientWidth, video.videoHeight)
const sx = (canvas.width - 360) / 2
const sy = (canvas.height - 360) / 2
context.drawImage(video, 0, 0)
context.fillStyle = 'black'
context.globalAlpha = 0.6
context.fillRect(0, 0, canvas.width, canvas.height)
context.drawImage(video, sx, sy, 360, 360, sx, sy, 360, 360)
if (time - oldTime > 600) {
oldTime = time
let imageData = context.getImageData(sx, sy, 360, 360)
qrworker.postMessage({
data: imageData.data,
width: imageData.width,
height: imageData.height,
})
}
}
requestAnimationFrame(tick)
}
let pinworker = null
function startDecrypt(qrdata) {
button.innerHTML = "Stop"
button.onclick = stopDecrypt
pinworker = new Worker(new URL('./pinworker.js', import.meta.url),
{type: 'module'})
pinworker.onmessage = (message) => {
const {pin, key, decrypted} = message.data
if (decrypted) {
stopDecrypt()
decryptedEl.innerHTML = decrypted
}
oneEl.innerHTML = pin[0]
twoEl.innerHTML = pin[1]
threeEl.innerHTML = pin[2]
fourEl.innerHTML = pin[3]
keyEl.innerHTML = key
}
qrdataEl.innerHTML = qrdata
if (qrdata.length !== 218) {
const message = "<QR data has wrong length!>"
saltEl.innerHTML = message
nonceEl.innerHTML = message
encryptedEl.innerHTML = message
tagEl.innerHTML = message
stopDecrypt()
return
}
if (qrdata.substring(0, 2) !== '01') {
const message = "<Invalid protocol in QR data!>"
saltEl.innerHTML = message
nonceEl.innerHTML = message
encryptedEl.innerHTML = message
tagEl.innerHTML = message
stopDecrypt()
return
}
const salt = qrdata.substring(2, 34)
saltEl.innerHTML = salt
const nonce = qrdata.substring(34, 58)
nonceEl.innerHTML = nonce
const encrypted = qrdata.substring(58, 186)
encryptedEl.innerHTML = encrypted
const tag = qrdata.substring(186, 218)
tagEl.innerHTML = tag
oneEl.innerHTML = "0"
twoEl.innerHTML = "0"
threeEl.innerHTML = "0"
fourEl.innerHTML = "0"
keyEl.innerHTML = "<No data from derivation>"
decryptedEl.innerHTML = "<No data from decryption>"
pinworker.postMessage({
salt: salt,
nonce: nonce,
encrypted: encrypted,
tag: tag,
})
}
function stopDecrypt() {
pinworker.terminate()
button.innerHTML = "Start"
button.onclick = startVideo
}