Spaces:
Sleeping
Sleeping
Update index.html
Browse files- index.html +116 -19
index.html
CHANGED
@@ -1,19 +1,116 @@
|
|
1 |
-
<!
|
2 |
-
<html>
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>KeyLock JS Decoder Example</title>
|
7 |
+
<style>
|
8 |
+
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; line-height: 1.6; max-width: 800px; margin: 20px auto; padding: 0 15px; color: #333; }
|
9 |
+
h1, h2 { color: #111; }
|
10 |
+
.container { display: flex; flex-direction: column; gap: 20px; }
|
11 |
+
.step { border: 1px solid #ddd; padding: 15px; border-radius: 8px; background: #fafafa; }
|
12 |
+
label { font-weight: bold; display: block; margin-bottom: 5px; }
|
13 |
+
input[type="file"] { display: block; }
|
14 |
+
textarea { width: 100%; box-sizing: border-box; padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-family: monospace; font-size: 14px; }
|
15 |
+
button { background-color: #007bff; color: white; padding: 10px 15px; border: none; border-radius: 5px; font-size: 16px; cursor: pointer; transition: background-color 0.2s; }
|
16 |
+
button:disabled { background-color: #aaa; cursor: not-allowed; }
|
17 |
+
button:hover:not(:disabled) { background-color: #0056b3; }
|
18 |
+
#image-preview { max-width: 300px; max-height: 200px; margin-top: 10px; border: 1px solid #ccc; display: none; }
|
19 |
+
#result-output { margin-top: 10px; background: #e9ecef; padding: 15px; border-radius: 5px; white-space: pre-wrap; word-wrap: break-word; font-family: monospace; min-height: 50px; }
|
20 |
+
</style>
|
21 |
+
</head>
|
22 |
+
<body>
|
23 |
+
|
24 |
+
<h1>KeyLock JS Decoder Example</h1>
|
25 |
+
<p>This page demonstrates how to use the <code>keylock-decoder.js</code> module to securely decode credentials from an image on the client-side.</p>
|
26 |
+
|
27 |
+
<div class="container">
|
28 |
+
<div class="step">
|
29 |
+
<h2>Step 1: Upload your KeyLock Auth Image</h2>
|
30 |
+
<input type="file" id="stego-image-input" accept="image/png">
|
31 |
+
<img id="image-preview" alt="Image preview for decoding">
|
32 |
+
</div>
|
33 |
+
|
34 |
+
<div class="step">
|
35 |
+
<h2>Step 2: Provide your Private Key</h2>
|
36 |
+
<textarea id="private-key-input" rows="10" placeholder="Paste your -----BEGIN PRIVATE KEY-----... here"></textarea>
|
37 |
+
</div>
|
38 |
+
|
39 |
+
<div class="step">
|
40 |
+
<h2>Step 3: Decode!</h2>
|
41 |
+
<button id="decode-button" disabled>Decode Credentials</button>
|
42 |
+
<h3>Result:</h3>
|
43 |
+
<div id="result-output">Awaiting input...</div>
|
44 |
+
</div>
|
45 |
+
</div>
|
46 |
+
|
47 |
+
<script type="module">
|
48 |
+
// Import the main function from the decoder module
|
49 |
+
import { decodeAuthFromImage } from './keylock-decoder.js';
|
50 |
+
|
51 |
+
const imageInput = document.getElementById('stego-image-input');
|
52 |
+
const imagePreview = document.getElementById('image-preview');
|
53 |
+
const keyInput = document.getElementById('private-key-input');
|
54 |
+
const decodeButton = document.getElementById('decode-button');
|
55 |
+
const resultOutput = document.getElementById('result-output');
|
56 |
+
|
57 |
+
let isImageLoaded = false;
|
58 |
+
|
59 |
+
function checkInputs() {
|
60 |
+
decodeButton.disabled = !isImageLoaded || keyInput.value.trim() === '';
|
61 |
+
}
|
62 |
+
|
63 |
+
imageInput.addEventListener('change', (event) => {
|
64 |
+
const file = event.target.files[0];
|
65 |
+
if (file) {
|
66 |
+
const reader = new FileReader();
|
67 |
+
reader.onload = (e) => {
|
68 |
+
imagePreview.src = e.target.result;
|
69 |
+
imagePreview.style.display = 'block';
|
70 |
+
// The 'load' event on the image ensures it's fully rendered before we might use it
|
71 |
+
imagePreview.onload = () => {
|
72 |
+
isImageLoaded = true;
|
73 |
+
checkInputs();
|
74 |
+
};
|
75 |
+
};
|
76 |
+
reader.readAsDataURL(file);
|
77 |
+
} else {
|
78 |
+
isImageLoaded = false;
|
79 |
+
imagePreview.style.display = 'none';
|
80 |
+
checkInputs();
|
81 |
+
}
|
82 |
+
});
|
83 |
+
|
84 |
+
keyInput.addEventListener('input', checkInputs);
|
85 |
+
|
86 |
+
decodeButton.addEventListener('click', async () => {
|
87 |
+
decodeButton.disabled = true;
|
88 |
+
decodeButton.textContent = 'Processing...';
|
89 |
+
resultOutput.textContent = 'Decoding... please wait.';
|
90 |
+
|
91 |
+
try {
|
92 |
+
// The image must be loaded and available in the DOM
|
93 |
+
const credentials = await decodeAuthFromImage(imagePreview, keyInput.value);
|
94 |
+
|
95 |
+
// Success! Display the credentials and do something with them.
|
96 |
+
resultOutput.style.color = 'green';
|
97 |
+
resultOutput.textContent = `✅ Success!\n\n${JSON.stringify(credentials, null, 2)}`;
|
98 |
+
|
99 |
+
// In a real app, you would now use these credentials:
|
100 |
+
// e.g., make an authenticated API call.
|
101 |
+
console.log("Decoded Credentials:", credentials);
|
102 |
+
alert(`Successfully decoded user: ${credentials.USERNAME || 'N/A'}`);
|
103 |
+
|
104 |
+
} catch (error) {
|
105 |
+
console.error("Decoding failed:", error);
|
106 |
+
resultOutput.style.color = 'red';
|
107 |
+
resultOutput.textContent = `❌ Error: ${error.message}`;
|
108 |
+
} finally {
|
109 |
+
decodeButton.textContent = 'Decode Credentials';
|
110 |
+
checkInputs(); // Re-enable button if inputs are still valid
|
111 |
+
}
|
112 |
+
});
|
113 |
+
</script>
|
114 |
+
|
115 |
+
</body>
|
116 |
+
</html>
|