@@ -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
13591509function copyContentById ( id ) {
0 commit comments