Added new codebook page

This commit is contained in:
2026-04-06 15:17:25 -04:00
parent 3cb34a226a
commit b245ae63e6
4 changed files with 522 additions and 155 deletions

View File

@@ -127,11 +127,11 @@
<!-- Page 1: Key & ASCII -->
<div>
<div class="key-section">
<h2>Encryption Key</h2>
<h2 style="margin-top: 0;">Encryption Key</h2>
<div class="key-value" id="print-key"></div>
</div>
<h2>ASCII Reference Table</h2>
<h1>ASCII REFERENCE TABLE</h1>
<div id="ascii-print"></div>
</div>
@@ -162,12 +162,13 @@
}
function renderASCIITable() {
let html = '<table class="ascii-table">';
html += '<tr><th>Dec</th><th>Hex</th><th>Char</th><th>Dec</th><th>Hex</th><th>Char</th><th>Dec</th><th>Hex</th><th>Char</th><th>Dec</th><th>Hex</th><th>Char</th></tr>';
let html = '<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem;">';
for (let row = 0; row < 32; row++) {
html += '<tr>';
for (let col = 0; col < 4; col++) {
for (let col = 0; col < 4; col++) {
html += '<table class="ascii-table">';
html += '<tr><th>Char</th><th>Hex</th><th>Dec</th></tr>';
for (let row = 0; row < 32; row++) {
const code = row + (col * 32);
if (code < 128) {
const hex = code.toString(16).toUpperCase().padStart(2, '0');
@@ -183,26 +184,36 @@
char = 'DEL';
}
html += `<td>${code}</td><td>${hex}</td><td><b>${char}</b></td>`;
html += `<tr><td><b>${char}</b></td><td>${hex}</td><td>${code}</td></tr>`;
}
}
html += '</tr>';
html += '</table>';
}
html += '</table>';
html += '</div>';
document.getElementById('ascii-print').innerHTML = html;
}
function renderOTPPairs(key) {
const columns = [[], [], [], [], []];
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const pairs = [];
const used = new Set();
for (let i = 0; i < 250; i++) {
const nonce = i.toString().padStart(3, '0');
const code = generateHOTP(key, nonce);
const pair = `${nonce} ${code}`;
columns[Math.floor(i / 50)].push(pair);
}
let nonce;
do {
nonce = chars[Math.floor(Math.random() * chars.length)] + chars[Math.floor(Math.random() * chars.length)];
} while (used.has(nonce));
used.add(nonce);
const code = generateHOTP(key, nonce);
pairs.push(`${nonce} ${code}`);
}
pairs.sort();
const columns = [[], [], [], [], []];
for (let i = 0; i < pairs.length; i++) {
columns[Math.floor(i / 50)].push(pairs[i]);
}
let html = '';
for (let col of columns) {
html += '<div class="otp-column">';
@@ -211,7 +222,6 @@
}
html += '</div>';
}
document.getElementById('otp-grid').innerHTML = html;
}
@@ -219,10 +229,8 @@
let html = '';
const rows = 'NOPQRSTUVWXYZ'.split('');
const cols = 'ABCDEFGHIJKLM'.split('');
for (let tableIndex = 0; tableIndex < 26; tableIndex++) {
const table = generateAuthTable(key, tableIndex);
html += '<div class="auth-table-wrapper">';
html += `<h3>${PHONETIC[tableIndex]}</h3>`;
html += '<table>';
@@ -231,7 +239,6 @@
html += `<th>${col}</th>`;
}
html += '</tr>';
for (let i = 0; i < rows.length; i++) {
html += `<tr><th>${rows[i]}</th>`;
for (let j = 0; j < cols.length; j++) {
@@ -242,23 +249,19 @@
html += '</table>';
html += '</div>';
}
document.getElementById('auth-tables').innerHTML = html;
}
function renderPadKeys(key) {
let html = '';
for (let i = 0; i < 50; i++) {
for (let i = 0; i < 100; i++) {
const padKey = (i * 1000).toString().padStart(5, '0');
const cipher = generatePadDisplay(key, padKey);
html += '<div class="pad-item">';
html += `<div><b>Key: ${padKey}</b></div>`;
html += `<div class="pad-cipher">${cipher}</div>`;
html += '</div>';
}
document.getElementById('pad-list').innerHTML = html;
}
@@ -273,11 +276,7 @@
renderOTPPairs(key);
renderAuthTables(key);
renderPadKeys(key);
// Auto-print after everything loads
setTimeout(() => {
window.print();
}, 500);
setTimeout(() => {window.print();}, 500);
}
</script>
</body>

View File

@@ -28,7 +28,7 @@
.header {
background: rgba(15, 23, 42, 0.95);
backdrop-filter: blur(10px);
padding: 1.5rem 2rem;
padding: 1rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
position: sticky;
top: 0;
@@ -50,12 +50,12 @@
}
.logo-section img {
height: 3rem;
height: 2.5rem;
width: auto;
}
.logo {
font-size: 1.5rem;
font-size: 1.25rem;
font-weight: 700;
letter-spacing: 0.05rem;
}
@@ -63,21 +63,32 @@
.container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
padding: 1rem;
}
.key-section {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 2rem;
padding: 1rem;
margin-bottom: 1.5rem;
}
.key-input-group {
display: flex;
gap: 1rem;
margin-bottom: 1rem;
gap: 0.5rem;
align-items: flex-end;
flex-wrap: wrap;
}
.key-input-group .input-wrapper {
flex: 1;
min-width: 200px;
}
.key-input-group button {
flex: 0 0 auto;
white-space: nowrap;
}
.input-wrapper {
@@ -133,6 +144,7 @@
font-size: 0.9rem;
cursor: pointer;
transition: all 0.2s ease;
white-space: nowrap;
}
button:hover {
@@ -165,8 +177,8 @@
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 2rem;
padding: 1rem;
margin-bottom: 1.5rem;
}
.tool-title {
@@ -183,17 +195,35 @@
.hotp-row {
display: flex;
gap: 1rem;
align-items: center;
gap: 0.5rem;
align-items: flex-end;
flex-wrap: wrap;
}
.hotp-row button {
flex: 0 0 auto;
}
.hotp-row > div {
flex: 1;
min-width: 100px;
}
.hotp-challenge-response {
display: flex;
gap: 0.5rem;
flex: 1;
min-width: 0;
}
.hotp-challenge-response > div {
flex: 1;
min-width: 100px;
}
.hotp-row input,
.hotp-code {
flex: 1;
width: 100%;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
@@ -211,14 +241,16 @@
.auth-table {
font-family: 'Courier New', monospace;
font-size: 0.9rem;
font-size: 0.75rem;
margin: 1rem 0;
width: 100%;
overflow-x: auto;
}
.auth-table table {
border-collapse: collapse;
width: 100%;
min-width: 500px;
}
.auth-table th,
@@ -227,6 +259,7 @@
padding: 0.5rem;
text-align: center;
transition: background-color 0.15s ease;
cursor: pointer;
}
.auth-table th {
@@ -234,19 +267,33 @@
font-weight: 600;
}
.auth-table td.highlight {
.auth-table td.highlight,
.auth-table th.highlight {
background: rgba(255, 255, 255, 0.25);
}
.auth-table td:hover,
.auth-table th:hover {
background: rgba(255, 255, 255, 0.15);
}
.auth-table th.highlight {
background: rgba(255, 255, 255, 0.2);
.ascii-search-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.5rem;
margin-bottom: 1rem;
}
.ascii-tables-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
margin: 1rem 0;
}
.ascii-table {
font-family: 'Courier New', monospace;
font-size: 0.85rem;
margin: 1rem 0;
width: 100%;
font-size: 0.75rem;
}
.ascii-table table {
@@ -266,16 +313,46 @@
font-weight: 600;
}
.ascii-table tr:hover {
background: rgba(255, 255, 255, 0.1);
}
.ascii-table tr.highlight {
background: rgba(255, 255, 255, 0.15);
}
.ascii-table tr.search-match {
background: rgba(16, 185, 129, 0.2);
}
.pad-list {
font-family: 'Courier New', monospace;
font-size: 0.95rem;
font-size: 0.85rem;
line-height: 1.8;
word-break: break-all;
}
.pad-item {
margin: 0.5rem 0;
}
.pad-controls {
display: flex;
gap: 0.5rem;
align-items: center;
flex-wrap: wrap;
margin-bottom: 1rem;
}
.pad-controls button {
flex: 0 0 auto;
}
.pad-controls input {
width: 100px;
flex: 0 0 auto;
}
textarea {
width: 100%;
min-height: 100px;
@@ -284,22 +361,23 @@
border-radius: 8px;
padding: 0.75rem;
color: #fff;
font-size: 1rem;
font-size: 0.9rem;
font-family: 'Courier New', monospace;
resize: vertical;
}
.button-group {
display: flex;
gap: 1rem;
gap: 0.5rem;
margin-top: 1rem;
flex-wrap: wrap;
}
.checkbox-wrapper {
display: flex;
align-items: center;
gap: 0.5rem;
margin-top: 1rem;
margin-top: 0;
}
.checkbox-wrapper input[type="checkbox"] {
@@ -320,6 +398,173 @@
padding: 1rem;
margin: 0.75rem 0;
font-family: 'Courier New', monospace;
font-size: 0.85rem;
overflow-x: auto;
}
.example-box pre {
overflow-x: auto;
white-space: pre;
}
.textarea-wrapper {
position: relative;
}
.copy-button {
position: absolute;
top: 0.5rem;
right: 0.5rem;
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 6px;
padding: 0.5rem;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
}
.copy-button:hover {
background: rgba(255, 255, 255, 0.2);
}
.copy-button svg {
width: 16px;
height: 16px;
fill: #fff;
}
/* Mobile Responsive */
@media (max-width: 768px) {
.header {
padding: 0.75rem;
}
.logo-section img {
height: 2rem;
}
.logo {
font-size: 1rem;
}
.container {
padding: 0.75rem;
}
.tool-section,
.key-section {
padding: 0.75rem;
margin-bottom: 1rem;
}
.tool-title {
font-size: 1.1rem;
}
.key-input-group {
flex-wrap: wrap;
}
.key-input-group .input-wrapper {
flex: 1 1 100%;
min-width: 100%;
}
.key-input-group button {
flex: 1;
}
.hotp-row {
flex-wrap: wrap;
}
.hotp-row button {
flex: 1 1 100%;
}
.hotp-challenge-response {
flex: 1 1 100%;
flex-wrap: nowrap;
}
.ascii-search-grid {
grid-template-columns: 1fr;
}
.ascii-tables-grid {
grid-template-columns: repeat(2, 1fr);
gap: 0.75rem;
}
.auth-table {
font-size: 0.65rem;
}
.ascii-table {
font-size: 0.7rem;
}
.ascii-table th,
.ascii-table td {
padding: 0.3rem;
}
button {
padding: 0.65rem 1rem;
font-size: 0.85rem;
}
.example-box {
font-size: 0.75rem;
padding: 0.75rem;
}
}
@media (max-width: 480px) {
.ascii-tables-grid {
grid-template-columns: 1fr;
}
.auth-table th,
.auth-table td {
padding: 0.3rem;
}
textarea {
font-size: 0.85rem;
}
.pad-list {
font-size: 0.8rem;
}
.hotp-challenge-response {
gap: 0.25rem;
}
.hotp-challenge-response button {
padding: 0.65rem 0.75rem;
font-size: 0.8rem;
}
}
@media (min-width: 769px) {
.ascii-tables-grid {
grid-template-columns: repeat(4, 1fr);
}
}
@media (min-width: 1200px) {
.key-input-group {
flex-wrap: nowrap;
}
.key-input-group .input-wrapper {
min-width: 200px;
}
}
</style>
</head>
@@ -328,7 +573,7 @@
<div class="header-content">
<div class="logo-section">
<img src="/favicon.png" alt="Logo">
<div class="logo">ENCRYPTION TOOLS</div>
<div class="logo">CODE BOOK</div>
</div>
</div>
</div>
@@ -338,7 +583,9 @@
<div class="input-wrapper">
<label>Encryption Key</label>
<div class="key-input-group">
<input type="text" id="master-key" placeholder="Enter encryption key">
<div class="input-wrapper">
<input type="text" id="master-key" placeholder="Enter encryption key">
</div>
<button onclick="generateNewKey()" class="danger">Random</button>
<button onclick="save()" class="save">Save</button>
</div>
@@ -347,36 +594,39 @@
<!-- HOTP Section -->
<div class="tool-section">
<div class="tool-title">One Time Password (HOTP)</div>
<div class="tool-title">One-Time Password (HOTP)</div>
<details style="margin: 1rem 0; color: #888;">
<summary>Description</summary>
<summary style="font-weight: bolder">Description</summary>
<div style="padding-top: 0.5rem;">
<p>Use a 3-digit challenge to generate & verify a corresponding 3-letter response.</p>
<p>Provides higher entropy and security than authentication tables while being easier to use.</p>
<p>Use a 2-character alphanumeric challenge to generate & verify with a corresponding 2-character response.</p>
<p>Provides higher entropy (security) than authentication tables while using less bandwidth & being easier to use.</p>
<div style="margin-top: 0.75rem;">
<strong>Pre-Authenticate:</strong>
<div class="example-box">
<p><strong>A->B:</strong> AUTH 123 ABC</p>
<p><strong>B->A:</strong> ACK. AUTH 456 DEF</p>
</div>
</div>
<div style="margin-top: 0.75rem;">
<strong>Challenge-Response:</strong>
<div class="example-box">
<p><strong>A->B:</strong> CONFIRM <span style="text-decoration: underline;">123</span></p>
<p><strong>B->A:</strong> ACK <span style="text-decoration: underline;">ABC</span>. CONFIRM <span style="text-decoration: underline;">456</span></p>
<p><strong>A->B:</strong> ACK <span style="text-decoration: underline;">DEF</span></p>
</div>
<div style="margin-top: 0.75rem;">
<strong>Challenge-Response:</strong>
<div class="example-box">
<p><strong>A->B:</strong> AUTH AA</p>
<p style="font-style: italic; color: #656565;">(B inputs AA and sends response with new challenge)</p>
<p><strong>B->A:</strong> ANS BB. AUTH CC</p>
<p style="font-style: italic; color: #656565;">(A verifies response; provides response to new challenge)</p>
<p><strong>A->B:</strong> ANS DD</p>
<p style="font-style: italic; color: #656565;">(B verifies response)</p>
</div>
</div>
</div>
</details>
<div class="hotp-row">
<button onclick="randomHOTPNonce()">Random</button>
<input type="number" id="hotp-nonce" placeholder="000" min="0" max="999" oninput="updateHOTP()">
<div class="hotp-code" id="hotp-display">---</div>
<div class="hotp-challenge-response">
<div>
<label>Challenge</label>
<input type="text" id="hotp-nonce" placeholder="A1" maxlength="2" oninput="updateHOTP()" style="text-transform: uppercase;">
</div>
<div>
<label>Response</label>
<div class="hotp-code" id="hotp-display">--</div>
</div>
</div>
</div>
</div>
@@ -384,17 +634,20 @@
<div class="tool-section">
<div class="tool-title">Authentication Tables</div>
<details style="margin: 1rem 0; color: #888;">
<summary>Description</summary>
<summary style="font-weight: bolder">Description</summary>
<div style="padding-top: 0.5rem;">
<p>Challenge-response tables for authentication.</p>
<div style="margin-top: 0.75rem;">
<strong>Example:</strong>
<strong>Challenge-Response:</strong>
<div class="example-box">
<p><strong>A->B:</strong> CONFIRM <span style="text-decoration: underline;">CEY</span> <span style="font-style: italic">(Table: Charlie, Column: E, Row: Y)</span></p>
<p><strong>B->A:</strong> ACK <span style="text-decoration: underline;">7</span>. CONFIRM <span style="text-decoration: underline;">AIT</span> <span style="font-style: italic">(Table: Alpha, Column: I, Row: T)</span></p>
<p><strong>A->B:</strong> ACK <span style="text-decoration: underline;">T</span></p>
<p><strong>A->B:</strong> AUTH CEY</p>
<p style="font-style: italic; color: #656565;">(B look up response for table: Charlie, column: E, row: Y; sends new challenge)</p>
<p><strong>B->A:</strong> ANS 7. AUTH AIT</p>
<p style="font-style: italic; color: #656565;">(A verifies response; sends response for new challenge, table: Alpha, column: I, row: T)</p>
<p><strong>A->B:</strong> ANS T</p>
<p style="font-style: italic; color: #656565;">(B verifies response)</p>
</div>
</div>
</div>
@@ -410,45 +663,48 @@
<div class="tool-section">
<div class="tool-title">One-Time Pad</div>
<details style="margin: 1rem 0; color: #888;">
<summary>Description</summary>
<summary style="font-weight: bolder">Description</summary>
<div style="padding-top: 0.5rem;">
<p>Use a 5-digit key to generate a corresponding fixed (paper friendly) or streamed (more secure) cipher.</p>
<p>Cipher values are added to the ASCII encoded message to create encrypted message.</p>
<p>Use a 5-digit key to generate a fixed (paper friendly) or streamed (more secure) cipher.</p>
<p>Cipher values are added to ASCII encoded message to create encrypted message. All values are 3-digit for manual calculations.</p>
<p>When encoding exceeds 999, only keep the last 3 digits. When decoding goes negative, add 1000.</p>
<div style="margin-top: 0.75rem;">
<strong>Encoding:</strong>
<strong>Encoding (with overflow example):</strong>
<div class="example-box">
Message: "HI"<br>
Pad Key: 12345<br>
Cipher: 42 85 28 71 14 ...<br><br>
<pre>Key: 12345
234 967 890 112 314...
H = ASCII 72 → 72 + 42 = 114 → Hex 72<br>
I = ASCII 73 → 73 + 85 = 158 → Hex 9E<br><br>
Encoded: 729E
Message: H E L L O
ASCII: 072 069 076 076 079
Cipher: + 234 967 890 112 314
─────────────────────────────
Result: 306 1036 966 188 393
Encoded: 306 036 966 188 393</pre>
</div>
</div>
<div style="margin-top: 0.75rem;">
<strong>Decoding:</strong>
<strong>Decoding (with negative handling):</strong>
<div class="example-box">
Encoded: 729E<br>
Pad Key: 12345<br>
Cipher: 42 85 28 71 14 ...<br><br>
<pre>Key: 12345
234 967 890 112 314...
72 (Hex) = 114 → 114 - 42 = 72 → ASCII 'H'<br>
9E (Hex) = 158 → 158 - 85 = 73 → ASCII 'I'<br><br>
Decoded: "HI"
Encoded: 306 036 966 188 393
Cipher: - 234 967 890 112 314
─────────────────────────────
Result: 072 -931 076 076 079
ASCII: 072 069 076 076 079
Message: H E L L O</pre>
</div>
</div>
</div>
</details>
<div class="input-wrapper">
<div class="key-input-group">
<div class="pad-controls">
<button onclick="randomPadKey()">Random</button>
<input type="text" id="pad-key" placeholder="00000" maxlength="5" oninput="updatePad()" style="max-width: 100px; text-align: center;">
<input type="text" id="pad-key" placeholder="00000" maxlength="5" oninput="updatePad()" style="text-align: center;">
<div class="checkbox-wrapper">
<input type="checkbox" id="stream-cipher" checked>
<label for="stream-cipher">Stream Cipher</label>
@@ -463,20 +719,43 @@
<button style="flex: 1 0 0;" onclick="handleEncode()">Encode</button>
<button style="flex: 1 0 0;" onclick="handleDecode()">Decode</button>
</div>
<textarea id="message-output" placeholder="Output" readonly style="margin-top: 1.5rem;"></textarea>
<div class="textarea-wrapper" style="margin-top: 1.5rem;">
<textarea id="message-output" placeholder="Output" readonly></textarea>
<button class="copy-button" onclick="copyOutput()" title="Copy to clipboard">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/>
</svg>
</button>
</div>
</div>
</div>
<!-- ASCII Table Section -->
<div class="tool-section">
<div class="tool-title">ASCII Reference Table</div>
<div class="ascii-table" id="ascii-table-display"></div>
<div class="ascii-search-grid">
<div class="input-wrapper">
<label>Character</label>
<input type="text" id="ascii-search-char" placeholder="A" maxlength="3" oninput="searchASCII()">
</div>
<div class="input-wrapper">
<label>Hex</label>
<input type="text" id="ascii-search-hex" placeholder="41" maxlength="2" oninput="searchASCII()">
</div>
<div class="input-wrapper">
<label>Decimal</label>
<input type="text" id="ascii-search-dec" placeholder="65" maxlength="3" oninput="searchASCII()">
</div>
</div>
<div class="ascii-tables-grid" id="ascii-table-display"></div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<script src="encryption.js"></script>
<script>
let authTableClickedCell = null;
function save() {
window.open('/code-book-print.html', '_blank');
}
@@ -507,7 +786,7 @@
function updateHOTP() {
const key = document.getElementById('master-key').value;
const nonce = document.getElementById('hotp-nonce').value.padStart(3, '0');
const nonce = document.getElementById('hotp-nonce').value.toUpperCase().padStart(2, '0');
if (!key) return;
const code = generateHOTP(key, nonce);
@@ -515,7 +794,8 @@
}
function randomHOTPNonce() {
const nonce = Math.floor(Math.random() * 1000).toString().padStart(3, '0');
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const nonce = chars[Math.floor(Math.random() * chars.length)] + chars[Math.floor(Math.random() * chars.length)];
document.getElementById('hotp-nonce').value = nonce;
updateHOTP();
}
@@ -546,6 +826,7 @@
html += '</table>';
document.getElementById('auth-table-display').innerHTML = html;
authTableClickedCell = null;
// Add hover listeners
const authTable = document.querySelector('#auth-table-display table');
@@ -553,6 +834,8 @@
cells.forEach(cell => {
cell.addEventListener('mouseenter', function() {
if (authTableClickedCell) return;
const col = this.getAttribute('data-col');
const row = this.getAttribute('data-row');
@@ -561,8 +844,27 @@
});
cell.addEventListener('mouseleave', function() {
if (authTableClickedCell) return;
authTable.querySelectorAll('.highlight').forEach(el => el.classList.remove('highlight'));
});
cell.addEventListener('click', function() {
const col = this.getAttribute('data-col');
const row = this.getAttribute('data-row');
// If clicking the same cell, unclick it
if (authTableClickedCell && authTableClickedCell.col === col && authTableClickedCell.row === row) {
authTable.querySelectorAll('.highlight').forEach(el => el.classList.remove('highlight'));
authTableClickedCell = null;
} else {
// Click new cell
authTable.querySelectorAll('.highlight').forEach(el => el.classList.remove('highlight'));
authTable.querySelectorAll(`[data-col="${col}"]`).forEach(el => el.classList.add('highlight'));
authTable.querySelectorAll(`[data-row="${row}"]`).forEach(el => el.classList.add('highlight'));
authTableClickedCell = { col, row };
}
});
});
}
@@ -613,22 +915,66 @@
document.getElementById('message-output').value = decoded;
}
function copyOutput() {
const output = document.getElementById('message-output');
output.select();
document.execCommand('copy');
const btn = event.currentTarget;
const originalHTML = btn.innerHTML;
btn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>';
setTimeout(() => {
btn.innerHTML = originalHTML;
}, 1500);
}
function searchASCII() {
const charQuery = document.getElementById('ascii-search-char').value.toUpperCase();
const hexQuery = document.getElementById('ascii-search-hex').value.toUpperCase();
const decQuery = document.getElementById('ascii-search-dec').value;
const tables = document.querySelectorAll('#ascii-table-display .ascii-table table');
tables.forEach(table => {
const rows = table.querySelectorAll('tr');
rows.forEach((row, index) => {
if (index === 0) return; // Skip header
row.classList.remove('search-match');
if (!charQuery && !hexQuery && !decQuery) return;
const cells = row.querySelectorAll('td');
const char = cells[0]?.textContent || '';
const hex = cells[1]?.textContent || '';
const dec = cells[2]?.textContent || '';
let match = false;
if (charQuery && char.toUpperCase().includes(charQuery)) match = true;
if (hexQuery && hex.includes(hexQuery)) match = true;
if (decQuery && dec.includes(decQuery)) match = true;
if (match) {
row.classList.add('search-match');
}
});
});
}
function renderASCIITable() {
const cols = 16;
const rows = 8;
let html = '';
let html = '<table>';
html += '<tr><th>Dec</th><th>Hex</th><th>Char</th><th>Dec</th><th>Hex</th><th>Char</th><th>Dec</th><th>Hex</th><th>Char</th><th>Dec</th><th>Hex</th><th>Char</th></tr>';
for (let col = 0; col < 4; col++) {
html += '<div class="ascii-table"><table>';
html += '<tr><th>Char</th><th>Hex</th><th>Dec</th></tr>';
for (let row = 0; row < 32; row++) {
html += '<tr>';
for (let col = 0; col < 4; col++) {
for (let row = 0; row < 32; row++) {
const code = row + (col * 32);
if (code < 128) {
const hex = code.toString(16).toUpperCase().padStart(2, '0');
let char = String.fromCharCode(code);
// Handle non-printable characters
if (code < 32) {
const controlChars = ['NUL','SOH','STX','ETX','EOT','ENQ','ACK','BEL','BS','TAB','LF','VT','FF','CR','SO','SI',
'DLE','DC1','DC2','DC3','DC4','NAK','SYN','ETB','CAN','EM','SUB','ESC','FS','GS','RS','US'];
@@ -639,14 +985,50 @@
char = 'DEL';
}
html += `<td>${code}</td><td>${hex}</td><td style="font-weight: bolder">${char}</td>`;
html += `<tr><td style="font-weight: bolder">${char}</td><td>${hex}</td><td>${code}</td></tr>`;
}
}
html += '</tr>';
html += '</table></div>';
}
html += '</table>';
document.getElementById('ascii-table-display').innerHTML = html;
// Add click/hover listeners for ASCII tables
const asciiTables = document.querySelectorAll('#ascii-table-display .ascii-table table');
asciiTables.forEach(table => {
const rows = table.querySelectorAll('tr');
rows.forEach((row, index) => {
if (index === 0) return; // Skip header
row.addEventListener('mouseenter', function() {
if (!this.classList.contains('highlight')) {
this.style.background = 'rgba(255, 255, 255, 0.1)';
}
});
row.addEventListener('mouseleave', function() {
if (!this.classList.contains('highlight')) {
this.style.background = '';
}
});
row.addEventListener('click', function() {
// Toggle highlight
const isHighlighted = this.classList.contains('highlight');
// Remove all highlights from all ASCII tables
asciiTables.forEach(t => {
t.querySelectorAll('.highlight').forEach(r => r.classList.remove('highlight'));
});
if (!isHighlighted) {
this.classList.add('highlight');
}
});
});
});
}
function initializeTools() {
@@ -657,10 +1039,8 @@
}
}
// Event listeners
document.getElementById('master-key').addEventListener('input', saveMasterKey);
// Initialize on load
loadMasterKey();
populateTableSelect();
renderASCIITable();

View File

@@ -1,15 +1,8 @@
// encryption.js
// Phonetic alphabet for table names
const PHONETIC = ['Alpha', 'Bravo', 'Charlie', 'Delta', 'Echo', 'Foxtrot', 'Golf', 'Hotel',
'India', 'Juliet', 'Kilo', 'Lima', 'Mike', 'November', 'Oscar', 'Papa',
'Quebec', 'Romeo', 'Sierra', 'Tango', 'Uniform', 'Victor', 'Whiskey',
'Xray', 'Yankee', 'Zulu'];
const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const PHONETIC = ['Alpha', 'Bravo', 'Charlie', 'Delta', 'Echo', 'Foxtrot', 'Golf', 'Hotel',
'India', 'Juliet', 'Kilo', 'Lima', 'Mike', 'November', 'Oscar', 'Papa', 'Quebec', 'Romeo',
'Sierra', 'Tango', 'Uniform', 'Victor', 'Whiskey', 'Xray', 'Yankee', 'Zulu'];
// Seeded RNG using SHA256
class SeededRandom {
constructor(seed) {
this.seed = seed;
@@ -32,17 +25,15 @@ class SeededRandom {
}
}
// HOTP Generation - 3 digit nonce -> 3 letter code
function generateHOTP(secret, nonce) {
const rng = new SeededRandom(secret + ':hotp:' + nonce);
let code = '';
for (let i = 0; i < 3; i++) {
code += rng.choice(LETTERS.split(''));
for (let i = 0; i < 2; i++) {
code += rng.choice(CHARS.split(''));
}
return code;
}
// Auth Tables
function generateAuthTable(seed, tableIndex) {
const rng = new SeededRandom(seed + ':table:' + tableIndex);
const rows = 'NOPQRSTUVWXYZ'.split('');
@@ -60,12 +51,11 @@ function generateAuthTable(seed, tableIndex) {
return table;
}
// One-Time Pad (for encode/decode)
function generatePad(seed, padKey, length = 60) {
const rng = new SeededRandom(seed + ':pad:' + padKey);
const pad = [];
for (let i = 0; i < length; i++) {
pad.push(rng.nextInt(0, 256));
pad.push(rng.nextInt(0, 1000));
}
return pad;
}
@@ -73,8 +63,8 @@ function generatePad(seed, padKey, length = 60) {
function generatePadDisplay(seed, padKey) {
const rng = new SeededRandom(seed + ':pad:' + padKey);
const groups = [];
for (let i = 0; i < 12; i++) {
const num = rng.nextInt(0, 100000).toString().padStart(5, '0');
for (let i = 0; i < 24; i++) {
const num = rng.nextInt(0, 1000).toString().padStart(3, '0');
groups.push(num);
}
return groups.join(' ');
@@ -84,30 +74,28 @@ function encodeMessage(message, key, padKey, useStream = true) {
const messageBytes = new TextEncoder().encode(message);
const padLength = useStream ? messageBytes.length : 60;
const pad = generatePad(key, padKey, padLength);
const encoded = [];
for (let i = 0; i < messageBytes.length; i++) {
const padByte = pad[i % pad.length];
encoded.push(messageBytes[i] ^ padByte);
const padValue = pad[i % pad.length];
const result = (messageBytes[i] + padValue) % 1000;
encoded.push(result.toString().padStart(3, '0'));
}
return Array.from(encoded).map(b => b.toString(16).padStart(2, '0')).join('');
return encoded.join('');
}
function decodeMessage(encoded, key, padKey, useStream = true) {
const bytes = [];
for (let i = 0; i < encoded.length; i += 2) {
bytes.push(parseInt(encoded.substr(i, 2), 16));
const values = [];
for (let i = 0; i < encoded.length; i += 3) {
values.push(parseInt(encoded.substr(i, 3), 10));
}
const padLength = useStream ? bytes.length : 60;
const padLength = useStream ? values.length : 60;
const pad = generatePad(key, padKey, padLength);
const decoded = [];
for (let i = 0; i < bytes.length; i++) {
const padByte = pad[i % pad.length];
decoded.push(bytes[i] ^ padByte);
for (let i = 0; i < values.length; i++) {
const padValue = pad[i % pad.length];
let result = (values[i] - padValue) % 1000;
if (result < 0) result += 1000;
decoded.push(result);
}
return new TextDecoder().decode(new Uint8Array(decoded));
}

View File

@@ -881,7 +881,7 @@
<a href=":1800" class="app-item" data-name="Pentesting">
<div class="app-icon-wrapper">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M267 48C230.6 48 209.2 106.3 198.7 160L168 160C154.7 160 144 170.7 144 184C144 197.3 154.7 208 168 208L192 208L192 240C192 257 195.3 273.2 201.3 288L192 288L192 288L171.5 288C156.3 288 144 300.3 144 315.5C144 318.5 144.5 321.4 145.4 324.2L174.3 410.8C136.2 443.6 112 492.1 112 546.3C112 562.7 125.3 576 141.7 576L498.3 576C514.7 576 528 562.7 528 546.3C528 492.1 503.8 443.6 465.7 410.9L494.6 324.3C495.5 321.5 496 318.6 496 315.6C496 300.4 483.7 288.1 468.5 288.1L448 288.1L448 288.1L438.7 288.1C444.7 273.3 448 257.1 448 240.1L448 208.1L472 208.1C485.3 208.1 496 197.4 496 184.1C496 170.8 485.3 160.1 472 160.1L441.3 160.1C430.9 106.4 409.4 48.1 373 48.1C363.4 48.1 354 52 345.5 56.3C337.3 60.4 327.1 64.1 320 64.1C312.9 64.1 302.7 60.4 294.5 56.3C286 51.9 276.6 48 267 48zM360.7 532.4L335.9 461.5L363.8 429C366.5 425.8 368 421.8 368 417.6C368 407.9 360.2 400.1 350.5 400.1L289.5 400.1C279.8 400.1 272 407.9 272 417.6C272 421.8 273.5 425.8 276.2 429L304.1 461.5L279.3 532.4L222.3 352L258 352C276.4 362.2 297.5 368 320 368C342.5 368 363.6 362.2 382 352L417.7 352L360.7 532.4zM320 320C285.3 320 255.8 297.9 244.7 267C250.4 270.2 257 272 264 272L276.4 272C292.9 272 307.5 261.4 312.7 245.8C315 238.8 324.9 238.8 327.2 245.8C332.4 261.4 347.1 272 363.5 272L375.9 272C382.9 272 389.5 270.2 395.2 267C384.1 297.9 354.6 320 319.9 320z"/></svg>
<svg style="fill: white; height: 50px; width: auto;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M267 48C230.6 48 209.2 106.3 198.7 160L168 160C154.7 160 144 170.7 144 184C144 197.3 154.7 208 168 208L192 208L192 240C192 257 195.3 273.2 201.3 288L192 288L192 288L171.5 288C156.3 288 144 300.3 144 315.5C144 318.5 144.5 321.4 145.4 324.2L174.3 410.8C136.2 443.6 112 492.1 112 546.3C112 562.7 125.3 576 141.7 576L498.3 576C514.7 576 528 562.7 528 546.3C528 492.1 503.8 443.6 465.7 410.9L494.6 324.3C495.5 321.5 496 318.6 496 315.6C496 300.4 483.7 288.1 468.5 288.1L448 288.1L448 288.1L438.7 288.1C444.7 273.3 448 257.1 448 240.1L448 208.1L472 208.1C485.3 208.1 496 197.4 496 184.1C496 170.8 485.3 160.1 472 160.1L441.3 160.1C430.9 106.4 409.4 48.1 373 48.1C363.4 48.1 354 52 345.5 56.3C337.3 60.4 327.1 64.1 320 64.1C312.9 64.1 302.7 60.4 294.5 56.3C286 51.9 276.6 48 267 48zM360.7 532.4L335.9 461.5L363.8 429C366.5 425.8 368 421.8 368 417.6C368 407.9 360.2 400.1 350.5 400.1L289.5 400.1C279.8 400.1 272 407.9 272 417.6C272 421.8 273.5 425.8 276.2 429L304.1 461.5L279.3 532.4L222.3 352L258 352C276.4 362.2 297.5 368 320 368C342.5 368 363.6 362.2 382 352L417.7 352L360.7 532.4zM320 320C285.3 320 255.8 297.9 244.7 267C250.4 270.2 257 272 264 272L276.4 272C292.9 272 307.5 261.4 312.7 245.8C315 238.8 324.9 238.8 327.2 245.8C332.4 261.4 347.1 272 363.5 272L375.9 272C382.9 272 389.5 270.2 395.2 267C384.1 297.9 354.6 320 319.9 320z"/></svg>
</div>
<div class="app-name">Pentesting</div>
</a>