broadfield-dev commited on
Commit
06ed56c
·
verified ·
1 Parent(s): 30cc34f

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +55 -154
index.html CHANGED
@@ -1,167 +1,68 @@
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 Client-Side Decoder Demo</title>
7
- <style>
8
- :root {
9
- --primary-color: #007bff;
10
- --primary-hover: #0056b3;
11
- --border-color: #ddd;
12
- --background-color: #fafafa;
13
- --text-color: #333;
14
- --error-color: #dc3545;
15
- --success-color: #28a745;
16
- }
17
- body {
18
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
19
- line-height: 1.6;
20
- max-width: 800px;
21
- margin: 20px auto;
22
- padding: 0 15px;
23
- color: var(--text-color);
24
- }
25
- main { display: flex; flex-direction: column; gap: 25px; }
26
- h1 { color: #111; text-align: center; }
27
- .step { border: 1px solid var(--border-color); padding: 20px; border-radius: 8px; background: var(--background-color); }
28
- label { font-weight: bold; display: block; margin-bottom: 8px; font-size: 1.1rem; }
29
- input[type="file"] { display: block; }
30
- textarea { width: 100%; box-sizing: border-box; padding: 10px; border: 1px solid #ccc; border-radius: 4px; font-family: monospace; font-size: 14px; min-height: 160px; }
31
- button {
32
- background-color: var(--primary-color);
33
- color: white;
34
- padding: 12px 20px;
35
- border: none;
36
- border-radius: 5px;
37
- font-size: 1.1rem;
38
- font-weight: bold;
39
- cursor: pointer;
40
- transition: background-color 0.2s, transform 0.1s;
41
- width: 100%;
42
- }
43
- button:disabled { background-color: #aaa; cursor: not-allowed; }
44
- button:hover:not(:disabled) { background-color: var(--primary-hover); }
45
- button:active:not(:disabled) { transform: translateY(1px); }
46
- #image-preview {
47
- max-width: 100%;
48
- height: auto;
49
- max-height: 250px;
50
- margin-top: 15px;
51
- border: 2px dashed var(--border-color);
52
- display: none;
53
- object-fit: contain;
54
- background: #f0f0f0;
55
- }
56
- #result-output {
57
- margin-top: 10px;
58
- background: #e9ecef;
59
- padding: 15px;
60
- border-radius: 5px;
61
- white-space: pre-wrap;
62
- word-wrap: break-word;
63
- font-family: monospace;
64
- min-height: 50px;
65
- border: 1px solid var(--border-color);
66
- }
67
- .result-error { color: var(--error-color); border-left: 5px solid var(--error-color); }
68
- .result-success { color: var(--success-color); border-left: 5px solid var(--success-color); }
69
- </style>
70
  </head>
71
  <body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
- <h1>🔐 KeyLock Client-Side Decoder</h1>
74
- <p style="text-align:center;">This demo shows how an application can decode a KeyLock image entirely in the user's browser, using their private key. No data is sent to a server.</p>
75
-
76
- <main>
77
- <section class="step">
78
- <label for="stego-image-input">1. Upload your KeyLock Auth Image</label>
79
- <input type="file" id="stego-image-input" accept="image/png">
80
- <img id="image-preview" alt="Uploaded image preview for decoding">
81
- </section>
82
 
83
- <section class="step">
84
- <label for="private-key-input">2. Provide your Private Key</label>
85
- <textarea id="private-key-input" placeholder="Paste your -----BEGIN PRIVATE KEY-----... here. The key never leaves your browser."></textarea>
86
- </section>
87
 
88
- <section class="step">
89
- <label>3. Decode the Image</label>
90
- <button id="decode-button" disabled>Decode Credentials</button>
91
- <h3>Result:</h3>
92
- <div id="result-output">Awaiting input...</div>
93
- </section>
94
- </main>
95
 
96
- <script type="module">
97
- // Import the main function from the decoder module
98
- import { decodeAuthFromImage } from './keylock-decoder.js';
99
 
100
- const imageInput = document.getElementById('stego-image-input');
101
- const imagePreview = document.getElementById('image-preview');
102
- const keyInput = document.getElementById('private-key-input');
103
- const decodeButton = document.getElementById('decode-button');
104
- const resultOutput = document.getElementById('result-output');
105
-
106
- let isImageLoaded = false;
107
-
108
- function checkInputs() {
109
- decodeButton.disabled = !isImageLoaded || keyInput.value.trim() === '';
110
- }
111
-
112
- imageInput.addEventListener('change', (event) => {
113
- const file = event.target.files[0];
114
- if (file) {
115
- const reader = new FileReader();
116
- reader.onload = (e) => {
117
- imagePreview.src = e.target.result;
118
- imagePreview.style.display = 'block';
119
- // The 'load' event ensures the image is fully rendered on the page
120
- imagePreview.onload = () => {
121
- isImageLoaded = true;
122
- checkInputs();
123
- };
124
- imagePreview.onerror = () => {
125
- isImageLoaded = false;
126
- checkInputs();
127
- alert("Error loading image file.");
128
- }
129
- };
130
- reader.readAsDataURL(file);
131
- } else {
132
- isImageLoaded = false;
133
- imagePreview.style.display = 'none';
134
- checkInputs();
135
- }
136
- });
137
-
138
- keyInput.addEventListener('input', checkInputs);
139
-
140
- decodeButton.addEventListener('click', async () => {
141
- decodeButton.disabled = true;
142
- decodeButton.textContent = 'Processing...';
143
- resultOutput.textContent = 'Decoding... please wait.';
144
- resultOutput.className = ''; // Reset result styles
145
-
146
- try {
147
- const credentials = await decodeAuthFromImage(imagePreview, keyInput.value);
148
-
149
- resultOutput.classList.add('result-success');
150
- resultOutput.textContent = `✅ Success!\n\n${JSON.stringify(credentials, null, 2)}`;
151
-
152
- // In a real app, you would now use the 'credentials' object
153
- console.log("Decoded Credentials:", credentials);
154
-
155
- } catch (error) {
156
- console.error("Decoding failed:", error);
157
- resultOutput.classList.add('result-error');
158
- resultOutput.textContent = `❌ Error: ${error.message}`;
159
- } finally {
160
- decodeButton.textContent = 'Decode Credentials';
161
- checkInputs(); // Re-evaluate if the button should be enabled
162
- }
163
- });
164
- </script>
165
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  </body>
167
  </html>
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
+ <meta charset="UTF-8">
5
+ <title>Secure Decoder Client Demo</title>
6
+ <style>
7
+ body { font-family: sans-serif; max-width: 700px; margin: 2rem auto; }
8
+ .container { display: flex; flex-direction: column; gap: 1rem; border: 1px solid #ccc; padding: 1.5rem; border-radius: 8px; }
9
+ button { font-size: 1rem; padding: 0.5rem 1rem; cursor: pointer; }
10
+ #result { background: #f0f0f0; padding: 1rem; border-radius: 5px; white-space: pre-wrap; font-family: monospace; }
11
+ input[type="text"] { width: 100%; box-sizing: border-box; padding: 8px; }
12
+ </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  </head>
14
  <body>
15
+ <h1>Client for Secure Decoder Plugin</h1>
16
+ <p>This demo sends an encrypted image to a secure backend API. The backend holds the private key and returns the decrypted data.</p>
17
+
18
+ <div class="container">
19
+ <div>
20
+ <label for="api-url"><b>Your Deployed API Endpoint URL:</b></label>
21
+ <input type="text" id="api-url" placeholder="e.g., https://your-plugin.vercel.app/api/decode">
22
+ </div>
23
+ <div>
24
+ <label for="image-upload"><b>Upload Image (Encrypted with Plugin's Public Key):</b></label>
25
+ <input type="file" id="image-upload" accept="image/png">
26
+ </div>
27
+ <button id="submit-button">Send to Plugin for Decoding</button>
28
+ <div>
29
+ <h3>Result from Server:</h3>
30
+ <div id="result">...</div>
31
+ </div>
32
+ </div>
33
 
34
+ <script>
35
+ const apiUrlInput = document.getElementById('api-url');
36
+ const imageInput = document.getElementById('image-upload');
37
+ const submitButton = document.getElementById('submit-button');
38
+ const resultDiv = document.getElementById('result');
 
 
 
 
39
 
40
+ submitButton.addEventListener('click', async () => {
41
+ const file = imageInput.files[0];
42
+ const apiUrl = apiUrlInput.value.trim();
 
43
 
44
+ if (!file) { resultDiv.textContent = 'Please select an image file.'; return; }
45
+ if (!apiUrl) { resultDiv.textContent = 'Please provide the API endpoint URL.'; return; }
 
 
 
 
 
46
 
47
+ resultDiv.textContent = 'Uploading and decoding...';
48
+ submitButton.disabled = true;
 
49
 
50
+ const formData = new FormData();
51
+ formData.append('authImage', file);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
+ try {
54
+ const response = await fetch(apiUrl, { method: 'POST', body: formData });
55
+ const result = await response.json();
56
+ if (!response.ok) throw new Error(result.error);
57
+ resultDiv.style.color = 'green';
58
+ resultDiv.textContent = JSON.stringify(result.data, null, 2);
59
+ } catch (error) {
60
+ resultDiv.style.color = 'red';
61
+ resultDiv.textContent = `Error: ${error.message}`;
62
+ } finally {
63
+ submitButton.disabled = false;
64
+ }
65
+ });
66
+ </script>
67
  </body>
68
  </html>