Skip to content

Commit ca0a541

Browse files
committed
NONCE IS BACK
1 parent 555d104 commit ca0a541

9 files changed

Lines changed: 1377 additions & 27 deletions

File tree

API/dotpipe.js

Lines changed: 153 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,11 +1349,161 @@ function parseCSVLine(line) {
13491349
});
13501350
}
13511351

1352-
// Usage example to generate a nonce
1353-
function generateNonce() {
1352+
/**
1353+
* Computes the SHA-256 hash of the given data
1354+
* @param {string|ArrayBuffer} data - The data to hash
1355+
* @returns {Promise<string>} - A promise that resolves to the hex string of the hash
1356+
*/
1357+
async function sha256(data) {
1358+
// Convert string data to ArrayBuffer if needed
1359+
const dataBuffer = (typeof data === 'string')
1360+
? new TextEncoder().encode(data)
1361+
: data;
1362+
1363+
// Use the Web Crypto API to compute the hash
1364+
const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer);
1365+
1366+
// Convert the hash to a hex string
1367+
return Array.from(new Uint8Array(hashBuffer))
1368+
.map(b => b.toString(16).padStart(2, '0'))
1369+
.join('');
1370+
}
1371+
1372+
/**
1373+
* Synchronous version of SHA-256 using a pure JavaScript implementation
1374+
* Use this only if Web Crypto API is not available
1375+
* @param {string} data - The string to hash
1376+
* @returns {string} - The hex string of the hash
1377+
*/
1378+
function sha256Sync(data) {
1379+
// Constants used in SHA-256
1380+
const K = [
1381+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
1382+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
1383+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
1384+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
1385+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
1386+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
1387+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
1388+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
1389+
];
1390+
1391+
// Initial hash values (first 32 bits of the fractional parts of the square roots of the first 8 primes)
1392+
let H = [
1393+
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
1394+
];
1395+
1396+
// Pre-processing: padding the message
1397+
let binary = '';
1398+
for (let i = 0; i < data.length; i++) {
1399+
binary += data.charCodeAt(i).toString(2).padStart(8, '0');
1400+
}
1401+
1402+
// Append the bit '1' to the message
1403+
binary += '1';
1404+
1405+
// Append k bits '0', where k is the minimum number >= 0 such that (message length + 1 + k + 64) is a multiple of 512
1406+
while (binary.length % 512 !== 448) {
1407+
binary += '0';
1408+
}
1409+
1410+
// Append the length of the original message as a 64-bit big-endian integer
1411+
const msgLength = data.length * 8;
1412+
binary += msgLength.toString(2).padStart(64, '0');
1413+
1414+
// Process the message in 512-bit chunks
1415+
for (let i = 0; i < binary.length; i += 512) {
1416+
const chunk = binary.slice(i, i + 512);
1417+
1418+
// Break chunk into sixteen 32-bit big-endian words
1419+
const words = [];
1420+
for (let j = 0; j < chunk.length; j += 32) {
1421+
words.push(parseInt(chunk.slice(j, j + 32), 2));
1422+
}
1423+
1424+
// Extend the sixteen 32-bit words into sixty-four 32-bit words
1425+
for (let j = 16; j < 64; j++) {
1426+
const s0 = rightRotate(words[j - 15], 7) ^ rightRotate(words[j - 15], 18) ^ (words[j - 15] >>> 3);
1427+
const s1 = rightRotate(words[j - 2], 17) ^ rightRotate(words[j - 2], 19) ^ (words[j - 2] >>> 10);
1428+
words[j] = (words[j - 16] + s0 + words[j - 7] + s1) >>> 0;
1429+
}
1430+
1431+
// Initialize working variables to current hash value
1432+
let [a, b, c, d, e, f, g, h] = H;
1433+
1434+
// Compression function main loop
1435+
for (let j = 0; j < 64; j++) {
1436+
const S1 = rightRotate(e, 6) ^ rightRotate(e, 11) ^ rightRotate(e, 25);
1437+
const ch = (e & f) ^ (~e & g);
1438+
const temp1 = (h + S1 + ch + K[j] + words[j]) >>> 0;
1439+
const S0 = rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22);
1440+
const maj = (a & b) ^ (a & c) ^ (b & c);
1441+
const temp2 = (S0 + maj) >>> 0;
1442+
1443+
h = g;
1444+
g = f;
1445+
f = e;
1446+
e = (d + temp1) >>> 0;
1447+
d = c;
1448+
c = b;
1449+
b = a;
1450+
a = (temp1 + temp2) >>> 0;
1451+
}
1452+
1453+
// Add the compressed chunk to the current hash value
1454+
H[0] = (H[0] + a) >>> 0;
1455+
H[1] = (H[1] + b) >>> 0;
1456+
H[2] = (H[2] + c) >>> 0;
1457+
H[3] = (H[3] + d) >>> 0;
1458+
H[4] = (H[4] + e) >>> 0;
1459+
H[5] = (H[5] + f) >>> 0;
1460+
H[6] = (H[6] + g) >>> 0;
1461+
H[7] = (H[7] + h) >>> 0;
1462+
}
1463+
1464+
// Produce the final hash value as a 256-bit number (as a hex string)
1465+
return H.map(h => h.toString(16).padStart(8, '0')).join('');
1466+
1467+
// Helper function for right rotation
1468+
function rightRotate(value, amount) {
1469+
return ((value >>> amount) | (value << (32 - amount))) >>> 0;
1470+
}
1471+
}
1472+
1473+
/**
1474+
* Generate a secure random nonce and hash it with SHA-256
1475+
* @returns {Promise<string>} - A promise that resolves to the nonce
1476+
*/
1477+
async function generateNonce() {
1478+
// Generate 16 random bytes
13541479
const randomBytes = new Uint8Array(16);
13551480
crypto.getRandomValues(randomBytes);
1356-
return sha256(randomBytes.join('')).then(hash => hash.slice(0, 16));
1481+
1482+
// Convert to string and hash
1483+
const randomString = Array.from(randomBytes).map(b => b.toString(16).padStart(2, '0')).join('');
1484+
return await sha256(randomString);
1485+
}
1486+
1487+
/**
1488+
* Generate a secure random nonce synchronously
1489+
* @returns {string} - The nonce
1490+
*/
1491+
function generateNonceSync() {
1492+
// Generate random string if crypto.getRandomValues is available
1493+
let randomString;
1494+
1495+
try {
1496+
const randomBytes = new Uint8Array(16);
1497+
crypto.getRandomValues(randomBytes);
1498+
randomString = Array.from(randomBytes).map(b => b.toString(16).padStart(2, '0')).join('');
1499+
} catch (e) {
1500+
// Fallback if crypto.getRandomValues is not available
1501+
randomString = Math.random().toString(36).substring(2, 15) +
1502+
Math.random().toString(36).substring(2, 15) +
1503+
Date.now().toString(36);
1504+
}
1505+
1506+
return sha256Sync(randomString);
13571507
}
13581508

13591509
function copyContentById(id) {

activeMenu/dotpipe.js

Lines changed: 153 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,11 +1349,161 @@ function parseCSVLine(line) {
13491349
});
13501350
}
13511351

1352-
// Usage example to generate a nonce
1353-
function generateNonce() {
1352+
/**
1353+
* Computes the SHA-256 hash of the given data
1354+
* @param {string|ArrayBuffer} data - The data to hash
1355+
* @returns {Promise<string>} - A promise that resolves to the hex string of the hash
1356+
*/
1357+
async function sha256(data) {
1358+
// Convert string data to ArrayBuffer if needed
1359+
const dataBuffer = (typeof data === 'string')
1360+
? new TextEncoder().encode(data)
1361+
: data;
1362+
1363+
// Use the Web Crypto API to compute the hash
1364+
const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer);
1365+
1366+
// Convert the hash to a hex string
1367+
return Array.from(new Uint8Array(hashBuffer))
1368+
.map(b => b.toString(16).padStart(2, '0'))
1369+
.join('');
1370+
}
1371+
1372+
/**
1373+
* Synchronous version of SHA-256 using a pure JavaScript implementation
1374+
* Use this only if Web Crypto API is not available
1375+
* @param {string} data - The string to hash
1376+
* @returns {string} - The hex string of the hash
1377+
*/
1378+
function sha256Sync(data) {
1379+
// Constants used in SHA-256
1380+
const K = [
1381+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
1382+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
1383+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
1384+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
1385+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
1386+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
1387+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
1388+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
1389+
];
1390+
1391+
// Initial hash values (first 32 bits of the fractional parts of the square roots of the first 8 primes)
1392+
let H = [
1393+
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
1394+
];
1395+
1396+
// Pre-processing: padding the message
1397+
let binary = '';
1398+
for (let i = 0; i < data.length; i++) {
1399+
binary += data.charCodeAt(i).toString(2).padStart(8, '0');
1400+
}
1401+
1402+
// Append the bit '1' to the message
1403+
binary += '1';
1404+
1405+
// Append k bits '0', where k is the minimum number >= 0 such that (message length + 1 + k + 64) is a multiple of 512
1406+
while (binary.length % 512 !== 448) {
1407+
binary += '0';
1408+
}
1409+
1410+
// Append the length of the original message as a 64-bit big-endian integer
1411+
const msgLength = data.length * 8;
1412+
binary += msgLength.toString(2).padStart(64, '0');
1413+
1414+
// Process the message in 512-bit chunks
1415+
for (let i = 0; i < binary.length; i += 512) {
1416+
const chunk = binary.slice(i, i + 512);
1417+
1418+
// Break chunk into sixteen 32-bit big-endian words
1419+
const words = [];
1420+
for (let j = 0; j < chunk.length; j += 32) {
1421+
words.push(parseInt(chunk.slice(j, j + 32), 2));
1422+
}
1423+
1424+
// Extend the sixteen 32-bit words into sixty-four 32-bit words
1425+
for (let j = 16; j < 64; j++) {
1426+
const s0 = rightRotate(words[j - 15], 7) ^ rightRotate(words[j - 15], 18) ^ (words[j - 15] >>> 3);
1427+
const s1 = rightRotate(words[j - 2], 17) ^ rightRotate(words[j - 2], 19) ^ (words[j - 2] >>> 10);
1428+
words[j] = (words[j - 16] + s0 + words[j - 7] + s1) >>> 0;
1429+
}
1430+
1431+
// Initialize working variables to current hash value
1432+
let [a, b, c, d, e, f, g, h] = H;
1433+
1434+
// Compression function main loop
1435+
for (let j = 0; j < 64; j++) {
1436+
const S1 = rightRotate(e, 6) ^ rightRotate(e, 11) ^ rightRotate(e, 25);
1437+
const ch = (e & f) ^ (~e & g);
1438+
const temp1 = (h + S1 + ch + K[j] + words[j]) >>> 0;
1439+
const S0 = rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22);
1440+
const maj = (a & b) ^ (a & c) ^ (b & c);
1441+
const temp2 = (S0 + maj) >>> 0;
1442+
1443+
h = g;
1444+
g = f;
1445+
f = e;
1446+
e = (d + temp1) >>> 0;
1447+
d = c;
1448+
c = b;
1449+
b = a;
1450+
a = (temp1 + temp2) >>> 0;
1451+
}
1452+
1453+
// Add the compressed chunk to the current hash value
1454+
H[0] = (H[0] + a) >>> 0;
1455+
H[1] = (H[1] + b) >>> 0;
1456+
H[2] = (H[2] + c) >>> 0;
1457+
H[3] = (H[3] + d) >>> 0;
1458+
H[4] = (H[4] + e) >>> 0;
1459+
H[5] = (H[5] + f) >>> 0;
1460+
H[6] = (H[6] + g) >>> 0;
1461+
H[7] = (H[7] + h) >>> 0;
1462+
}
1463+
1464+
// Produce the final hash value as a 256-bit number (as a hex string)
1465+
return H.map(h => h.toString(16).padStart(8, '0')).join('');
1466+
1467+
// Helper function for right rotation
1468+
function rightRotate(value, amount) {
1469+
return ((value >>> amount) | (value << (32 - amount))) >>> 0;
1470+
}
1471+
}
1472+
1473+
/**
1474+
* Generate a secure random nonce and hash it with SHA-256
1475+
* @returns {Promise<string>} - A promise that resolves to the nonce
1476+
*/
1477+
async function generateNonce() {
1478+
// Generate 16 random bytes
13541479
const randomBytes = new Uint8Array(16);
13551480
crypto.getRandomValues(randomBytes);
1356-
return sha256(randomBytes.join('')).then(hash => hash.slice(0, 16));
1481+
1482+
// Convert to string and hash
1483+
const randomString = Array.from(randomBytes).map(b => b.toString(16).padStart(2, '0')).join('');
1484+
return await sha256(randomString);
1485+
}
1486+
1487+
/**
1488+
* Generate a secure random nonce synchronously
1489+
* @returns {string} - The nonce
1490+
*/
1491+
function generateNonceSync() {
1492+
// Generate random string if crypto.getRandomValues is available
1493+
let randomString;
1494+
1495+
try {
1496+
const randomBytes = new Uint8Array(16);
1497+
crypto.getRandomValues(randomBytes);
1498+
randomString = Array.from(randomBytes).map(b => b.toString(16).padStart(2, '0')).join('');
1499+
} catch (e) {
1500+
// Fallback if crypto.getRandomValues is not available
1501+
randomString = Math.random().toString(36).substring(2, 15) +
1502+
Math.random().toString(36).substring(2, 15) +
1503+
Date.now().toString(36);
1504+
}
1505+
1506+
return sha256Sync(randomString);
13571507
}
13581508

13591509
function copyContentById(id) {

0 commit comments

Comments
 (0)