diff --git a/app/src/components/HelpBot.jsx b/app/src/components/HelpBot.jsx index dfa87c0..a6fe185 100644 --- a/app/src/components/HelpBot.jsx +++ b/app/src/components/HelpBot.jsx @@ -4,7 +4,129 @@ import alluArjun from "../assets/alluArjun.png"; import ohMyGoddo from "../assets/ohMyGoddo.png"; import { useNavigate } from 'react-router-dom'; + +function sha256(ascii) { + function rightRotate(value, amount) { + return (value >>> amount) | (value << (32 - amount)); + }; + + + var mathPow = Math.pow; + var maxWord = mathPow(2, 32); + var lengthProperty = 'length' + var i, j; // Used as a counter across the whole file + var result = '' + + var words = []; + var asciiBitLength = ascii[lengthProperty] * 8; + + //* caching results is optional - remove/add slash from front of this line to toggle + // Initial hash value: first 32 bits of the fractional parts of the square roots of the first 8 primes + // (we actually calculate the first 64, but extra values are just ignored) + var hash = sha256.h = sha256.h || []; + // Round constants: first 32 bits of the fractional parts of the cube roots of the first 64 primes + var k = sha256.k = sha256.k || []; + var primeCounter = k[lengthProperty]; + /*/ + var hash = [], k = []; + var primeCounter = 0; + //*/ + + var isComposite = {}; + for (var candidate = 2; primeCounter < 64; candidate++) { + if (!isComposite[candidate]) { + for (i = 0; i < 313; i += candidate) { + isComposite[i] = candidate; + } + hash[primeCounter] = (mathPow(candidate, .5) * maxWord) | 0; + k[primeCounter++] = (mathPow(candidate, 1 / 3) * maxWord) | 0; + } + } + + ascii += '\x80' // Append Ƈ' bit (plus zero padding) + while (ascii[lengthProperty] % 64 - 56) ascii += '\x00' // More zero padding + for (i = 0; i < ascii[lengthProperty]; i++) { + j = ascii.charCodeAt(i); + if (j >> 8) return; // ASCII check: only accept characters in range 0-255 + words[i >> 2] |= j << ((3 - i) % 4) * 8; + } + words[words[lengthProperty]] = ((asciiBitLength / maxWord) | 0); + words[words[lengthProperty]] = (asciiBitLength) + + // process each chunk + for (j = 0; j < words[lengthProperty];) { + var w = words.slice(j, j += 16); // The message is expanded into 64 words as part of the iteration + var oldHash = hash; + // This is now the undefinedworking hash", often labelled as variables a...g + // (we have to truncate as well, otherwise extra entries at the end accumulate + hash = hash.slice(0, 8); + + for (i = 0; i < 64; i++) { + var i2 = i + j; + // Expand the message into 64 words + // Used below if + var w15 = w[i - 15], w2 = w[i - 2]; + + // Iterate + var a = hash[0], e = hash[4]; + var temp1 = hash[7] + + (rightRotate(e, 6) ^ rightRotate(e, 11) ^ rightRotate(e, 25)) // S1 + + ((e & hash[5]) ^ ((~e) & hash[6])) // ch + + k[i] + // Expand the message schedule if needed + + (w[i] = (i < 16) ? w[i] : ( + w[i - 16] + + (rightRotate(w15, 7) ^ rightRotate(w15, 18) ^ (w15 >>> 3)) // s0 + + w[i - 7] + + (rightRotate(w2, 17) ^ rightRotate(w2, 19) ^ (w2 >>> 10)) // s1 + ) | 0 + ); + // This is only used once, so *could* be moved below, but it only saves 4 bytes and makes things unreadble + var temp2 = (rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22)) // S0 + + ((a & hash[1]) ^ (a & hash[2]) ^ (hash[1] & hash[2])); // maj + + hash = [(temp1 + temp2) | 0].concat(hash); // We don't bother trimming off the extra ones, they're harmless as long as we're truncating when we do the slice() + hash[4] = (hash[4] + temp1) | 0; + } + + for (i = 0; i < 8; i++) { + hash[i] = (hash[i] + oldHash[i]) | 0; + } + } + + for (i = 0; i < 8; i++) { + for (j = 3; j + 1; j--) { + var b = (hash[i] >> (j * 8)) & 255; + result += ((b < 16) ? 0 : '') + b.toString(16); + } + } + return result; +}; + +function caeserCipher(str, num) { + num = num % 26; + let lowerCaseString = str.toLowerCase(); + let alphabet = 'abcdefghijklmnopqrstuvwxyz'.split(''); + let newString = ''; + for (let i = 0; i < lowerCaseString.length; i++) { + let currentLetter = lowerCaseString[i]; + if (currentLetter === ' ') { + newString += currentLetter; + continue; + } + let currentIndex = alphabet.indexOf(currentLetter); + let newIndex = currentIndex + num; + if (newIndex > 25) newIndex = newIndex - 26; + if (newIndex < 0) newIndex = 26 + newIndex; + if (str[i] === str[i].toUpperCase()) { + newString += alphabet[newIndex].toUpperCase(); + } else newString += alphabet[newIndex]; + } + return newString; +} + const HelpBot = ({ level = 1, entryNumber, timer, setTimer }) => { + const navigate = useNavigate(); const latestTimerRef = useRef(timer); @@ -75,30 +197,8 @@ const HelpBot = ({ level = 1, entryNumber, timer, setTimer }) => { return [ { id: "1", - message: "You are on level 1. How can I assist you?", - trigger: "2", - }, - { - id: "2", - options: [ - { value: "option1", label: "Option 1", trigger: "option1-help" }, - { value: "option2", label: "Option 2", trigger: "option2-help" }, - ], - }, - { - id: "option1-help", - message: "Here is help for Option 1.", - trigger: "continue-options", - }, - { - id: "option2-help", - message: "Here is help for Option 2.", - trigger: "continue-options", - }, - { - id: "continue-options", - message: "Do you need help with anything else?", - trigger: "2", + message: "no bot required for this level", + end: true, }, ]; } else if (level === 2) { @@ -164,14 +264,13 @@ const HelpBot = ({ level = 1, entryNumber, timer, setTimer }) => { }, { id: "hacker-input", - user: true, - trigger: (inputValue) => { - if (inputValue.value === 'bad') { - return 'congo-msg'; - } else { - return 'wrong-ans'; - } - }, + user: true, + trigger: (inputValue) => { + if (inputValue.value === 'bad') { + return 'congo-msg'; + } else { + return 'wrong-ans'; + } }, { id: "congo-msg", @@ -191,7 +290,149 @@ const HelpBot = ({ level = 1, entryNumber, timer, setTimer }) => { trigger: 2, }, ]; - } else { + } else if (level === 3){ + return [ + { + id: 1, + message: "Welcome to Noncence!", + trigger: 2, + }, + { + id: 2, + message: "You should have your public key by now. Here are the steps to generate your private key:", + trigger: 3, + }, + { + id: 3, + message: '1. First, replace the letters by their number equivalent such that "A=1, B=2, ...".', + trigger: 4 + }, + { + id: '3-extra', + message: 'For example: k1a7fk2a9 -> 11117611219', + trigger: 'choice-msg' + }, + { + id: 4, + message: '2. Next, multiply by 1729. You can use your calculator for this.', + trigger: 5 + }, + { + id: '4-extra', + message: 'For example: 11117611219 -> 19222349797651', + trigger: 'choice-msg' + }, + { + id: 5, + message: '3. Take the last 9 digits of the result.', + trigger: 6 + }, + { + id: '5-extra', + message: 'For example: 19222349797651 -> 349797651', + trigger: 'choice-msg' + }, + { + id: 6, + message: '4. Convert every odd number to its letter equivalent.', + trigger: 7 + }, + { + id: '6-extra', + message: 'For example: 349797651 -> c4igi6ea', + trigger: 'choice-msg' + }, + { + id: 7, + message: 'Done! You have your private key. Use it to mine your block.', + trigger: 'choice-msg' + }, + { + id: 'choice-msg', + message: 'Any specific step you need help with?', + trigger: 'choice', + }, + { + id: 'choice', + options: [ + { value: 1, label: "1st", trigger: '3-extra' }, + { value: 2, label: "2nd", trigger: '4-extra' }, + { value: 3, label: "3rd", trigger: '5-extra' }, + { value: 4, label: "4th", trigger: '6-extra' }, + ], + }, + + ]; + } else if (level === 'blockmine'){ + return [ + { + id: 1, + message: "You are ready to mine your block. To get block nonce, you will require sha256 and caeser cipher encryption methods. Let's start!", + trigger: 'choice-msg' + }, + { + id: 'choice-msg', + message: 'Choose the encryption method you want to use:', + trigger: 'choice', + }, + { + id: 'choice', + options: [ + { value: "SHA-256", label: "SHA-256", trigger: 'sha256-msg' }, + { value: "Caeser Cipher", label: "Caeser Cipher", trigger: 'caeser-string-msg' }, + ], + }, + { + id: 'sha256-msg', + message: 'Enter the string to encrypt with sha256:', + trigger: 'sha256', + }, + { + id: 'sha256', + user: true, + trigger: 'sha256-response', + }, + { + id: 'sha256-response', + component: , + asMessage: true, + trigger: 'choice-msg', + }, + { + id: 'caeser-string-msg', + message: 'Enter the string to encrypt with Caesar Cipher:', + trigger: 'caeser-string-input', + }, + { + id: 'caeser-string-input', + user: true, + trigger: 'caeser-shift-msg', + }, + { + id: 'caeser-shift-msg', + message: 'Enter the shift number:', + trigger: 'caeser-shift-input', + }, + { + id: 'caeser-shift-input', + user: true, + validator: (value) => { + if (isNaN(value)) { + return 'Please enter a valid number.'; + } + return true; + }, + trigger: 'caeser-computation', + }, + { + id: 'caeser-computation', + component: , + asMessage: true, + trigger: 'choice-msg', + }, + ]; + } + else { return [ { id: 1, @@ -235,6 +476,25 @@ const HelpBot = ({ level = 1, entryNumber, timer, setTimer }) => { ); }; + +const CaeserCipherComponent = ({ steps }) => { + const caeserString = caeserCipher(steps['caeser-string-input'].value, parseInt(steps['caeser-shift-input'].value, 10)); + return ( +
+ Caesar Cipher Encrypted String: {caeserString} +
+ ); +}; + +const SHA256Component = ({ previousStep }) => { + const encryptedString = sha256(previousStep.message); + return ( +
+ SHA-256 Encrypted String: {encryptedString} +
+ ); +}; + // const RedirectComponent = ({ navigate, entryNumber, timer, setTimer }) => { // let timeTaken = 0 // useEffect(() => { diff --git a/app/src/components/blockchain/blockMine.jsx b/app/src/components/blockchain/blockMine.jsx index 26a3ebc..e59ae45 100644 --- a/app/src/components/blockchain/blockMine.jsx +++ b/app/src/components/blockchain/blockMine.jsx @@ -1,6 +1,7 @@ import React, { useEffect, useState } from 'react'; import "./Blockchain.css"; import AnimatedPage from '../AnimatedPage'; +import HelpBot from '../HelpBot'; function sha256(ascii) { function rightRotate(value, amount) { @@ -431,7 +432,9 @@ const BlockMine = ({ timer, setTimer, entryNumber }) => { )} + + ) } diff --git a/app/src/components/blockchain/transactionMine.jsx b/app/src/components/blockchain/transactionMine.jsx index 63d56d3..c1b3d13 100644 --- a/app/src/components/blockchain/transactionMine.jsx +++ b/app/src/components/blockchain/transactionMine.jsx @@ -1,6 +1,7 @@ import React, { useEffect, useState } from 'react'; import "./Blockchain.css"; import AnimatedPage from '../AnimatedPage'; +import HelpBot from '../HelpBot'; const TransactionMine = ({ timer, setTimer, goToNextStep }) => { @@ -201,6 +202,8 @@ const TransactionMine = ({ timer, setTimer, goToNextStep }) => { )} + )