├── .github └── workflows │ └── blank.yml ├── .gitignore ├── .travis.yml ├── 404.html ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── _config.yml ├── _data ├── challenges.yml └── noob.yml ├── _includes ├── footer.html ├── nav-challenges.html └── nav.html ├── _layouts ├── challenges.html ├── html.html └── noob.html ├── _sass ├── styles-challenges.scss ├── styles-noob.scss └── styles.scss ├── api └── challenges.json ├── challenges ├── b64.md ├── binascii.md ├── bitshift-encrypt.md ├── caesar-decrypt.md ├── caesar-encrypt.md ├── emojigraphy.md ├── hashshift.md ├── inverse.md ├── lost.md ├── railfence-encoding.md ├── rot13.md ├── rsa.md └── xorcipher.md ├── css ├── challenges.scss ├── main.scss └── noob.scss ├── favicon.ico ├── icon.png ├── img ├── logo-black.svg └── logo-white.svg ├── index.html ├── js ├── challenges.js ├── console.js ├── editor.js ├── landing.js ├── noob.js └── shortcuts.js ├── levels.html ├── noob.html ├── noob_questions ├── b64.md ├── binascii.md ├── bitshift.md ├── box.md ├── caesar-encrypt.md ├── emojigraphy.md ├── frequencyanalysis.md ├── hashshift.md ├── inverse.md ├── railfence.md ├── randomness.md ├── rsa.md └── vernam.md └── robots.txt /.github/workflows/blank.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: CI 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the master branch 7 | on: 8 | push: 9 | branches: [ master ] 10 | pull_request: 11 | branches: [ master ] 12 | 13 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 14 | jobs: 15 | # This workflow contains a single job called "build" 16 | build: 17 | # The type of runner that the job will run on 18 | runs-on: ubuntu-latest 19 | 20 | # Steps represent a sequence of tasks that will be executed as part of the job 21 | steps: 22 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 23 | - uses: actions/checkout@v2 24 | 25 | - name: Vercel Action PR 26 | uses: amondnet/vercel-action@v19.0.1+1 27 | if: github.event_name == 'pull_request' 28 | with: 29 | vercel-token: ${{ secrets.VERCEL_TOKEN }} # Required 30 | github-token: ${{ secrets.GITHUB_TOKEN }} #Optional 31 | vercel-org-id: ${{ secrets.ORG_ID}} #Required 32 | vercel-project-id: ${{ secrets.PROJECT_ID}} #Required 33 | working-directory: ./ 34 | - name: Vercel Action Push 35 | uses: amondnet/vercel-action@v19.0.1+1 36 | if: github.event_name == 'push' 37 | with: 38 | vercel-token: ${{ secrets.VERCEL_TOKEN }} # Required 39 | github-token: ${{ secrets.GITHUB_TOKEN }} #Optional 40 | vercel-args: '--prod' #Optional 41 | vercel-org-id: ${{ secrets.ORG_ID}} #Required 42 | vercel-project-id: ${{ secrets.PROJECT_ID}} #Required 43 | working-directory: ./ 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # Created by https://www.gitignore.io/api/sass,jekyll 61 | 62 | ### Jekyll ### 63 | _site/ 64 | .sass-cache/ 65 | .jekyll-metadata 66 | docs 67 | ### Sass ### 68 | *.css.map 69 | 70 | 71 | # End of https://www.gitignore.io/api/sass,jekyll 72 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | 3 | install: 4 | # Install Jekyll and dependencies 5 | - gem install jekyll bundler 6 | - gem update --system 7 | - bundle install 8 | script: 9 | - bundle exec jekyll build 10 | 11 | deploy: 12 | provider: pages 13 | skip-cleanup: true 14 | github-token: $GITHUB_TOKEN # Set in travis-ci.org dashboard, marked secure 15 | keep-history: true 16 | local-dir: docs 17 | on: 18 | branch: master 19 | notifications: 20 | email: 21 | on_success: never # default: change 22 | on_failure: always # default: always 23 | -------------------------------------------------------------------------------- /404.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | 6 | 7 | 8 | Page Not Found 9 | 10 | 11 | 43 | 44 | 45 | 46 | 47 |

Page Not Found :(

48 |

We are sorry. The page you looked for does not exist :(

49 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | source "https://rubygems.org" 3 | 4 | gem "jekyll-babel" 5 | 6 | gem "jekyll-minifier" 7 | # gem "rails" 8 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.7.0) 5 | public_suffix (>= 2.0.2, < 5.0) 6 | babel-source (5.8.35) 7 | babel-transpiler (0.7.0) 8 | babel-source (>= 4.0, < 6) 9 | execjs (~> 2.0) 10 | colorator (1.1.0) 11 | concurrent-ruby (1.1.6) 12 | cssminify2 (2.0.1) 13 | em-websocket (0.5.1) 14 | eventmachine (>= 0.12.9) 15 | http_parser.rb (~> 0.6.0) 16 | eventmachine (1.2.7) 17 | execjs (2.7.0) 18 | ffi (1.12.2) 19 | forwardable-extended (2.6.0) 20 | htmlcompressor (0.4.0) 21 | http_parser.rb (0.6.0) 22 | i18n (0.9.5) 23 | concurrent-ruby (~> 1.0) 24 | jekyll (3.8.7) 25 | addressable (~> 2.4) 26 | colorator (~> 1.0) 27 | em-websocket (~> 0.5) 28 | i18n (~> 0.7) 29 | jekyll-sass-converter (~> 1.0) 30 | jekyll-watch (~> 2.0) 31 | kramdown (~> 1.14) 32 | liquid (~> 4.0) 33 | mercenary (~> 0.3.3) 34 | pathutil (~> 0.9) 35 | rouge (>= 1.7, < 4) 36 | safe_yaml (~> 1.0) 37 | jekyll-babel (1.1.0) 38 | babel-transpiler 39 | jekyll-minifier (0.1.5) 40 | cssminify2 (~> 2.0) 41 | htmlcompressor (~> 0.3) 42 | jekyll (~> 3.5) 43 | uglifier (~> 3.2) 44 | jekyll-sass-converter (1.5.2) 45 | sass (~> 3.4) 46 | jekyll-watch (2.2.1) 47 | listen (~> 3.0) 48 | kramdown (1.17.0) 49 | liquid (4.0.3) 50 | listen (3.2.1) 51 | rb-fsevent (~> 0.10, >= 0.10.3) 52 | rb-inotify (~> 0.9, >= 0.9.10) 53 | mercenary (0.3.6) 54 | pathutil (0.16.2) 55 | forwardable-extended (~> 2.6) 56 | public_suffix (4.0.5) 57 | rb-fsevent (0.10.4) 58 | rb-inotify (0.10.1) 59 | ffi (~> 1.0) 60 | rouge (3.19.0) 61 | safe_yaml (1.0.5) 62 | sass (3.7.4) 63 | sass-listen (~> 4.0.0) 64 | sass-listen (4.0.0) 65 | rb-fsevent (~> 0.9, >= 0.9.4) 66 | rb-inotify (~> 0.9, >= 0.9.7) 67 | uglifier (3.2.0) 68 | execjs (>= 0.3.0, < 3) 69 | 70 | PLATFORMS 71 | ruby 72 | 73 | DEPENDENCIES 74 | jekyll-babel 75 | jekyll-minifier 76 | 77 | BUNDLED WITH 78 | 2.0.2 79 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Arthur Guiot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CrypTools website 2 | 3 |

4 | 5 |

6 |

7 | 8 | 9 | 10 |

11 | 12 | ## Welcome to the best platform to learn cryptography ! 13 | 14 | > Cryptography is the art of writing and solving problems in order to prevent third parties or the public from reading private messages. And as any art, it can be taught. This was our mission by creating this platform. You'll have some challenges to complete, the first ones are easy, but don't worry, it will get much harder after some point. 15 | 16 | > \- CrypTools 17 | 18 | [This website](https://cryptools.github.io/learn) is a learning platform for cryptography, don't hesitate to visit it 😄. 19 | ## Built with 20 | 21 | - [Jekyll](https://jekyllrb.com) - website generator 22 | - [Sass](https://sass-lang.com) - stylesheets 23 | 24 | 25 | # Contributing 26 | ## Create a challenge 27 | First, choose wether you want a code based or a simple question an answer. 28 | - For JS questions, put your `.md` file in `/challenges` and use `_data/challenges.yml` 29 | - For non JS questions, put your `.md` file in `/noob_questions` and use `_data/noob.yml` 30 | 31 | ### Write the question. 32 | Try to follow the template we use in the other file (you're allowed to copy paste other questions and change the content if want). 33 | 34 | ### Write the answer 35 | In the config file (in the `_data` folder), declare your file and your answer using the small template at the top of the file. 36 | 37 | ## Do a PR 38 | You can contribute to our code, but here are some rules to follow before doing any PRs: 39 | - Make sure that your code is indented with tabs instead of spaces 40 | - For JavaScript code, use ES7, Babel will compile it to ES5. 41 | - Don't worry about building the site, [Travis Ci](https://travis-ci.org/CrypTools/learn) will do it for you. 42 | 43 | 44 | ## Authors 45 | 46 | Made with ❤️ at CrypTools. 47 | 48 | See also the list of [contributors](https://github.com/CrypTools/learn/contributors) who participated in this project. 49 | 50 | ## License 51 | 52 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details 53 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # Building docs because GH Page is built using --safe 2 | destination: docs 3 | 4 | markdown: kramdown 5 | highlighter: rouge 6 | 7 | permalink: pretty 8 | 9 | url: https://cryptools.github.io/learn 10 | 11 | plugins: 12 | - jekyll-babel 13 | - jekyll-minifier 14 | 15 | appID: 1392983460 16 | -------------------------------------------------------------------------------- /_data/challenges.yml: -------------------------------------------------------------------------------- 1 | # name: the name of the cipher (no space) 2 | # fancy: the fancy name 3 | # question: the question file 4 | # init: the default code to put in the editor 5 | # testCommand: how to execute the code. uses `` pattern. current will contain the test data. 6 | # tests: the test data 7 | 8 | 9 | # Emoji Cipher - Introduction 10 | - name: emojigraphy 11 | fancy: Emoji cipher 12 | question: emojigraphy.md 13 | init: > 14 | String.prototype.encrypt = function() { 15 | // to get the String you need to encrypt, use 'this' 16 | } 17 | testCommand: return '${current.word}'.encrypt() 18 | tests: 19 | - word: message 20 | expected: 😝😅😒😒😄😍😅 21 | 22 | # Caesar Encrypt 23 | - name: caesar-encrypt 24 | fancy: Caesar Encrypt 25 | question: caesar-encrypt.md 26 | init: > 27 | String.prototype.encrypt = function(key) { 28 | // to get the String you need to encrypt, use 'this' 29 | } 30 | testCommand: return '${current.word}'.encrypt(${current.key}) 31 | tests: 32 | - word: Hello 33 | key: 4 34 | expected: LIPPS 35 | 36 | - word: cryptools 37 | key: 2 38 | expected: ETARVQQNU 39 | - word: test 40 | key: 5 41 | expected: YJXY 42 | 43 | 44 | # ROT13 45 | - name: rot13 46 | fancy: ROT13 47 | question: rot13.md 48 | init: > 49 | String.prototype.encrypt = function() { 50 | // to get the String you need to encrypt, use 'this' 51 | } 52 | testCommand: return '${current.word}'.encrypt() 53 | tests: 54 | - word: Hello 55 | expected: URYYB 56 | 57 | - word: cryptools 58 | expected: PELCGBBYF 59 | 60 | - word: test 61 | expected: GRFG 62 | 63 | 64 | # Caesar Decrypt 65 | - name: caesar-decrypt 66 | fancy: Caesar Decrypt 67 | question: caesar-decrypt.md 68 | init: > 69 | String.prototype.decrypt = function(key) { 70 | // to get the String you need to decrypt, use 'this' 71 | } 72 | testCommand: return '${current.word}'.decrypt(${current.key}) 73 | tests: 74 | - word: LIPPS 75 | key: 4 76 | expected: HELLO 77 | 78 | - word: ETARVQQNU 79 | key: 2 80 | expected: CRYPTOOLS 81 | - word: YJXY 82 | key: 5 83 | expected: TEST 84 | - name: inverse 85 | fancy: ATBASH Cipher 86 | question: inverse.md 87 | init: > 88 | String.prototype.encrypt = function() { 89 | // to get the String you need to encrypt, use 'this' 90 | } 91 | testCommand: return '${current.word}'.encrypt() 92 | tests: 93 | - word: FIND 94 | expected: URMW 95 | - word: ME 96 | expected: NV 97 | - word: CRYPTOOLS 98 | expected: XIBKGLLOH 99 | 100 | # Railfence Encrypt 101 | - name: railfence-encrypt 102 | fancy: Rail Fence Encrypt 103 | question: railfence-encrypt.md 104 | init: > 105 | String.prototype.encrypt = function(key) { // key is the number of rails 106 | // to get the String you need to encrypt, use 'this' 107 | } 108 | testCommand: return '${current.word}'.decrypt(${current.key}) 109 | tests: 110 | - word: Hello World! 111 | key: 3 112 | expected: Horel ol!lwd 113 | 114 | # BitShift Cipher 115 | - name: bitshift-encrypt 116 | fancy: BitShift Cipher 117 | question: bitshift-encrypt.md 118 | init: > 119 | String.prototype.encrypt = function(key) { // key is the number of rails 120 | // to get the String you need to encrypt, use 'this' 121 | } 122 | testCommand: return '${current.word}'.encrypt('${current.key}') 123 | tests: 124 | - word: Hello World! 125 | key: key 126 | expected: WzM3NDQyLDUyNDg4LDU1ODc0LDU2MDcyLDU3NDEwLDE3MTYwLDQ1MTIyLDU3NjA4LDU4OTQ2LDU2MDcyLDUxNzc4XQ== 127 | 128 | # XORCipher 129 | - name: xor 130 | fancy: XOR Cipher 131 | question: xorcipher.md 132 | init: > 133 | String.prototype.encrypt = function(key) { // key is a number or an array 134 | // to get the String you need to encrypt, use 'this' 135 | } 136 | testCommand: return '${current.word}'.encrypt(${current.key}) 137 | tests: 138 | - word: Hello World! 139 | key: 134 140 | expected: Îãêêé¦Ñéôêâ§ 141 | - word: CrypTools 142 | key: 873 143 | expected: ̛̪̙̐̽̆̆̅̚ 144 | 145 | # RSA 146 | - name: rsa 147 | fancy: RSA 148 | question: rsa.md 149 | init: > 150 | function rsa() { 151 | return n // n is the answer 152 | } 153 | testCommand: return rsa() 154 | tests: 155 | - word: rsa() 156 | expected: 399788195976 157 | # BinASCII 158 | - name: binascii 159 | fancy: BinASCII 160 | question: binascii.md 161 | init: > 162 | String.prototype.decrypt = function() { 163 | // to get the String you need to encrypt, use 'this' 164 | } 165 | testCommand: return '${current.word}'.decrypt() 166 | tests: 167 | - word: "010000110111001001111001011100000101010001101111011011110110110001110011" 168 | expected: CrypTools 169 | - word: "0100001001101001011011100100000101010011010000110100100101001001" 170 | expected: BinASCII 171 | 172 | # Base64 173 | - name: b64 174 | fancy: Base64 175 | question: b64.md 176 | init: > 177 | String.prototype.decrypt = function() { 178 | // to get the String you need to encrypt, use 'this' 179 | } 180 | testCommand: return '${current.word}'.decrypt() 181 | tests: 182 | - word: SGVsbG8gV29ybGQh 183 | expected: Hello World! 184 | - word: Q3J5cFRvb2xz 185 | expected: CrypTools 186 | - word: YmFzZQ== 187 | expected: base 188 | # Forgot Password 189 | - name: lost 190 | fancy: Hashes & Passwords 191 | question: lost.md 192 | init: > 193 | String.prototype.sha256=function(){let r=this;const n=8,t=0;function e(r,n){const t=(65535&r)+(65535&n);return(r>>16)+(n>>16)+(t>>16)<<16|65535&t}function o(r,n){return r>>>n|r<<32-n}function u(r,n){return r>>>n}function c(r,n,t){return r&n^~r&t}function f(r,n,t){return r&n^r&t^n&t}function i(r){return o(r,2)^o(r,13)^o(r,22)}function a(r){return o(r,6)^o(r,11)^o(r,25)}function h(r){return o(r,7)^o(r,18)^u(r,3)}return function(r){const n=t?"0123456789ABCDEF":"0123456789abcdef";let e="";for(let t=0;t<4*r.length;t++)e+=n.charAt(r[t>>2]>>8*(3-t%4)+4&15)+n.charAt(r[t>>2]>>8*(3-t%4)&15);return e}(function(r,n){const t=new Array(1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298),C=new Array(1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225),g=new Array(64);let l,d,A,s,S,m,y,p,v,w;r[n>>5]|=128<<24-n%32,r[15+(n+64>>9<<4)]=n;for(var b=0;b>5]|=(r.charCodeAt(o/n)&e)<<24-o%32;return t}(r=function(r){r=r.replace(/\r\n/g,"\n");let n="";for(let t=0;t127&&e<2048?(n+=String.fromCharCode(e>>6|192),n+=String.fromCharCode(63&e|128)):(n+=String.fromCharCode(e>>12|224),n+=String.fromCharCode(e>>6&63|128),n+=String.fromCharCode(63&e|128))}return n}(r)),r.length*n))}; 194 | 195 | // To use SHA256, do something like: "some text".sha256() 196 | 197 | function bruteforce() { 198 | const hash = "88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589" 199 | } 200 | testCommand: return bruteforce("${current.word}") 201 | tests: 202 | - word: 88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589 203 | expected: abcd 204 | # HashShift 205 | - name: hashshift 206 | fancy: HashShift PRNG 207 | question: hashshift.md 208 | init: > 209 | String.prototype.sha256=function(){let r=this;const n=8,t=0;function e(r,n){const t=(65535&r)+(65535&n);return(r>>16)+(n>>16)+(t>>16)<<16|65535&t}function o(r,n){return r>>>n|r<<32-n}function u(r,n){return r>>>n}function c(r,n,t){return r&n^~r&t}function f(r,n,t){return r&n^r&t^n&t}function i(r){return o(r,2)^o(r,13)^o(r,22)}function a(r){return o(r,6)^o(r,11)^o(r,25)}function h(r){return o(r,7)^o(r,18)^u(r,3)}return function(r){const n=t?"0123456789ABCDEF":"0123456789abcdef";let e="";for(let t=0;t<4*r.length;t++)e+=n.charAt(r[t>>2]>>8*(3-t%4)+4&15)+n.charAt(r[t>>2]>>8*(3-t%4)&15);return e}(function(r,n){const t=new Array(1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298),C=new Array(1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225),g=new Array(64);let l,d,A,s,S,m,y,p,v,w;r[n>>5]|=128<<24-n%32,r[15+(n+64>>9<<4)]=n;for(var b=0;b>5]|=(r.charCodeAt(o/n)&e)<<24-o%32;return t}(r=function(r){r=r.replace(/\r\n/g,"\n");let n="";for(let t=0;t127&&e<2048?(n+=String.fromCharCode(e>>6|192),n+=String.fromCharCode(63&e|128)):(n+=String.fromCharCode(e>>12|224),n+=String.fromCharCode(e>>6&63|128),n+=String.fromCharCode(63&e|128))}return n}(r)),r.length*n))}; 210 | 211 | // To use SHA256, do something like: "some text".sha256() 212 | 213 | function* rand(seed) { 214 | while (true) { 215 | yield out // out is the outtputed number. 216 | } 217 | } 218 | testCommand: return rand(${current.word}).next().value 219 | tests: 220 | - word: 12 221 | expected: 0.000050316490726670756 222 | - word: 1024 223 | expected: 0.7845447867083958 224 | -------------------------------------------------------------------------------- /_data/noob.yml: -------------------------------------------------------------------------------- 1 | # name: the name of the cipher (no space) 2 | # fancy: the fancy name 3 | # question: the question file 4 | # answer: the answer 5 | 6 | - name: emojigraphy 7 | fancy: Emoji Cipher 8 | question: emojigraphy.md 9 | answer: 😅😝😳😗😚 10 | - name: caesar-encrypt 11 | fancy: Caesar Encrypt 12 | question: caesar-encrypt.md 13 | answer: LIPPS 14 | - name: box 15 | fancy: Mysterious Box 16 | question: box.md 17 | answer: WINNER 18 | - name: inverse 19 | fancy: Atbash Cipher 20 | question: inverse.md 21 | answer: XIBKGLLOH 22 | - name: vernam 23 | fancy: Vernam Cipher 24 | question: vernam.md 25 | answer: XVPCTAQTH 26 | - name: railfence 27 | fancy: Railfence 28 | question: railfence.md 29 | answer: TCth i heepta chotRnen eaer srif seulic 30 | - name: binascii 31 | fancy: BinASCII 32 | question: binascii.md 33 | answer: 01100011 01101111 01100100 01100101 34 | - name: rsa 35 | fancy: RSA 36 | question: rsa.md 37 | answer: 399788195976 38 | - name: hashshift 39 | fancy: HashShift PRNG 40 | question: hashshift.md 41 | answer: 0.3047871109 42 | - name: base64 43 | fancy: Base64 44 | question: b64.md 45 | answer: Q3J5cFRvb2xz 46 | - name: freq 47 | fancy: Frequency Analysis 48 | question: frequencyanalysis.md 49 | answer: 7 50 | - name: bitshift 51 | fancy: BitShift Cipher 52 | question: bitshift.md 53 | answer: "[17843008, 30152208, 31998784, 29627920, 22299456, 29365776, 29377344, 28579344, 30425920]" 54 | - name: randomness 55 | fancy: Randomness 56 | question: randomness.md 57 | answer: 616467 58 | -------------------------------------------------------------------------------- /_includes/footer.html: -------------------------------------------------------------------------------- 1 |
2 | 7 | 11 | 12 |
-------------------------------------------------------------------------------- /_includes/nav-challenges.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_includes/nav.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_layouts/challenges.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{page.title}} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | {% include nav-challenges.html %} 27 | {{content}} 28 | 29 | 30 | 31 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /_layouts/html.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{page.title}} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 30 | 31 | 32 | 33 | 34 | 35 | 38 | 39 | {% include nav.html %} 40 | {{content}} 41 | {% include footer.html %} 42 | 43 | 44 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /_layouts/noob.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{page.title}} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | {% include nav-challenges.html %} 27 | {{content}} 28 | 29 | 30 | 31 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /_sass/styles-challenges.scss: -------------------------------------------------------------------------------- 1 | /*==================================== 2 | Body 3 | =====================================*/ 4 | :root { 5 | color-scheme: light dark; 6 | --text-color: #000; 7 | --black: #000; 8 | --footer: #fafafa; 9 | --white: white; 10 | --background: white; 11 | --opposite: #1e1e1e; 12 | --semi-white: #eee; 13 | --blue: #0061D9; 14 | } 15 | 16 | .white { 17 | display: none; 18 | } 19 | 20 | @media (prefers-color-scheme: dark) { 21 | :root { 22 | --text-color: #fff; 23 | --black: #fff; 24 | --footer: #000; 25 | --white: #000; 26 | --background: #1e1e1e; 27 | --opposite: #fff; 28 | --semi-white: #333; 29 | } 30 | 31 | .white { 32 | display: block; 33 | } 34 | 35 | .black { 36 | display: none; 37 | } 38 | 39 | header:after { 40 | filter: invert(100%); 41 | -webkit-filter: invert(100%); 42 | } 43 | 44 | nav .logo { 45 | background: url("../img/logo-white.svg") !important; 46 | background-size: contain !important; 47 | } 48 | 49 | .markdown-body { 50 | color: var(--text-color) !important; 51 | table, pre { 52 | color: black !important; 53 | } 54 | } 55 | } 56 | 57 | html { 58 | overflow-x: hidden 59 | } 60 | 61 | body { 62 | background: var(--background); 63 | overflow-x: hidden; 64 | font-family: SF Pro Display; 65 | font-style: normal; 66 | color: var(--text-color); 67 | display: flex; 68 | flex-direction: row; 69 | justify-content: center; 70 | align-items: top; 71 | width: 100vw; 72 | height: 100vh; 73 | max-width: 100vw; 74 | a { 75 | color: inherit; 76 | } 77 | } 78 | 79 | .mono { 80 | font-family: sf_monobold; 81 | } 82 | p.magnify { 83 | font-weight: 500; 84 | font-size: 18px; 85 | line-height: 24px; 86 | } 87 | 88 | * { 89 | z-index: 10; 90 | } 91 | 92 | nav { 93 | position: fixed; 94 | top: 0; 95 | width: 100vw; 96 | height: 100px; 97 | background-color: var(--white); 98 | z-index: 100; 99 | 100 | .logo { 101 | position: relative; 102 | left: 5vw; 103 | top: 0; 104 | width: 100px; 105 | height: 100px; 106 | background: url("../img/logo-black.svg"); 107 | background-size: contain; 108 | cursor: pointer; 109 | } 110 | 111 | .menu-container { 112 | position: fixed; 113 | top: 0; 114 | left: calc(5vw + 100px); 115 | right: calc(5vw + 100px); 116 | height: 100px; 117 | display: flex; 118 | justify-content: center; 119 | align-items: center; 120 | 121 | a { 122 | margin: 50px; 123 | color: var(--text-color); 124 | text-decoration: none; 125 | font-family: sf_monobold; 126 | font-size: 13px; 127 | line-height: 16px; 128 | /* identical to box height */ 129 | text-align: center; 130 | letter-spacing: 0.3em; 131 | } 132 | } 133 | .right { 134 | position: fixed; 135 | top: 0; 136 | right: 5vw; 137 | height: 100px; 138 | display: flex; 139 | justify-content: center; 140 | align-items: center; 141 | a { 142 | margin: 50px; 143 | color: var(--text-color); 144 | text-decoration: underline; 145 | font-family: sf_monobold; 146 | font-size: 13px; 147 | line-height: 16px; 148 | /* identical to box height */ 149 | text-align: center; 150 | letter-spacing: 0.3em; 151 | } 152 | } 153 | } 154 | /*==================================== 155 | Questions / course 156 | =====================================*/ 157 | .questions { 158 | margin-top: 96px; 159 | width: 50vw; 160 | overflow: auto; 161 | padding: 40px; 162 | box-sizing: border-box; 163 | } 164 | /*==================================== 165 | Editor + console 166 | =====================================*/ 167 | .editor { 168 | margin-top: 96px; 169 | width: 50vw; 170 | height: calc(67vh - 96px); 171 | max-height: 100vh; 172 | z-index: 100; 173 | .CodeMirror { 174 | height: 100% !important; 175 | width: 100%; 176 | } 177 | } 178 | 179 | .console { 180 | width: 100%; 181 | height: 100%; 182 | max-width: calc(50vw - 40px); 183 | max-height: calc(33vh - 40px); 184 | position: absolute; 185 | bottom: 0; 186 | right: 0; 187 | background: #000; 188 | color: green; 189 | padding: 20px; 190 | overflow: auto; 191 | } 192 | 193 | 194 | /*====================================================================== 195 | Well Done section 196 | =======================================================================*/ 197 | 198 | .done { 199 | display: none; 200 | flex-direction: column; 201 | justify-content: center; 202 | align-items: center; 203 | position: absolute; 204 | top: 100vh; 205 | left: 0; 206 | width: 100vw; 207 | height: 100vh; 208 | z-index: 100; 209 | background: white; 210 | transition: all 500ms ease-in-out; 211 | &.active { 212 | transform: translateY(-100vh); 213 | } 214 | .continue { 215 | font-size: 3em; 216 | transition: font-size 100ms ease-in-out; 217 | i { 218 | font-size: inherit; 219 | } 220 | &:hover { 221 | font-size: 3.5em; 222 | } 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /_sass/styles-noob.scss: -------------------------------------------------------------------------------- 1 | /*==================================== 2 | Body 3 | =====================================*/ 4 | :root { 5 | color-scheme: light dark; 6 | --text-color: #000; 7 | --black: #000; 8 | --footer: #fafafa; 9 | --white: white; 10 | --background: white; 11 | --opposite: #1e1e1e; 12 | --semi-white: #eee; 13 | --blue: #0061D9; 14 | } 15 | 16 | .white { 17 | display: none; 18 | } 19 | 20 | @media (prefers-color-scheme: dark) { 21 | :root { 22 | --text-color: #fff; 23 | --black: #fff; 24 | --footer: #000; 25 | --white: #000; 26 | --background: #1e1e1e; 27 | --opposite: #fff; 28 | --semi-white: #333; 29 | } 30 | 31 | .white { 32 | display: block; 33 | } 34 | 35 | .black { 36 | display: none; 37 | } 38 | 39 | header:after { 40 | filter: invert(100%); 41 | -webkit-filter: invert(100%); 42 | } 43 | 44 | nav .logo { 45 | background: url("../img/logo-white.svg") !important; 46 | background-size: contain !important; 47 | } 48 | 49 | .markdown-body { 50 | color: var(--text-color) !important; 51 | table { 52 | color: black !important; 53 | } 54 | } 55 | } 56 | 57 | html { 58 | overflow-x: hidden 59 | } 60 | 61 | body { 62 | background: var(--background); 63 | overflow-x: hidden; 64 | font-family: SF Pro Display; 65 | font-style: normal; 66 | color: var(--text-color); 67 | display: flex; 68 | flex-direction: row; 69 | justify-content: center; 70 | align-items: top; 71 | width: 100vw; 72 | height: 100vh; 73 | max-width: 100vw; 74 | a { 75 | color: inherit; 76 | } 77 | } 78 | .mono { 79 | font-family: sf_monobold; 80 | } 81 | p.magnify { 82 | font-weight: 500; 83 | font-size: 18px; 84 | line-height: 24px; 85 | } 86 | 87 | * { 88 | z-index: 10; 89 | } 90 | 91 | nav { 92 | position: fixed; 93 | top: 0; 94 | width: 100vw; 95 | height: 100px; 96 | background-color: var(--white); 97 | z-index: 100; 98 | 99 | .logo { 100 | position: relative; 101 | left: 5vw; 102 | top: 0; 103 | width: 100px; 104 | height: 100px; 105 | background: url("../img/logo-black.svg"); 106 | background-size: contain; 107 | cursor: pointer; 108 | } 109 | 110 | .menu-container { 111 | position: fixed; 112 | top: 0; 113 | left: calc(5vw + 100px); 114 | right: calc(5vw + 100px); 115 | height: 100px; 116 | display: flex; 117 | justify-content: center; 118 | align-items: center; 119 | 120 | a { 121 | margin: 50px; 122 | color: var(--text-color); 123 | text-decoration: none; 124 | font-family: sf_monobold; 125 | font-size: 13px; 126 | line-height: 16px; 127 | /* identical to box height */ 128 | text-align: center; 129 | letter-spacing: 0.3em; 130 | } 131 | } 132 | #menu-toggle { 133 | display: none; 134 | width: 40px; 135 | height: 30px; 136 | position: fixed; 137 | top: 40px; 138 | right: 50px; 139 | // display: flex; 140 | justify-content: space-around; 141 | align-items: center; 142 | flex-direction: column; 143 | cursor: pointer; 144 | z-index: 100; 145 | .l { 146 | transition: all 250ms ease-in-out; 147 | width: 40px; 148 | height: 2px; 149 | background: var(--black); 150 | } 151 | &.cross { 152 | .l:nth-child(1) { 153 | transform: rotate(45deg) translate(0, calc(40px / 3)); 154 | } 155 | 156 | .l:nth-child(2) { 157 | opacity: 0; 158 | } 159 | 160 | .l:nth-child(3) { 161 | transform: rotate(-45deg) translate(0, calc(-40px / 3)); 162 | } 163 | } 164 | } 165 | } 166 | 167 | 168 | @media (max-width: 800px) { 169 | header .welcontainer { 170 | left: 50% !important; 171 | transform: translateX(-50%); 172 | text-align: center; 173 | 174 | h1.welcome { 175 | font-size: 42px; 176 | 177 | span.big { 178 | font-size: 48px; 179 | } 180 | } 181 | 182 | h3 { 183 | font-size: 18px; 184 | max-width: none !important; 185 | } 186 | } 187 | 188 | nav .menu-container { 189 | display: none; 190 | position: fixed; 191 | top: 0; 192 | left: 0; 193 | background-color: var(--white); 194 | height: auto; 195 | flex-direction: column; 196 | width: 100vw; 197 | } 198 | #menu-toggle { 199 | display: flex !important; 200 | } 201 | 202 | article { 203 | section.who, .help { 204 | h1 { 205 | font-size: 42px; 206 | } 207 | 208 | .left, 209 | .right { 210 | max-width: calc(100vw - 100px); 211 | 212 | .fusion { 213 | width: calc(100vw - 100px); 214 | } 215 | 216 | h1 { 217 | font-size: 2em; 218 | line-break: anywhere; 219 | } 220 | 221 | p { 222 | font-size: 16px; 223 | line-height: 26px; 224 | } 225 | } 226 | } 227 | 228 | .help { 229 | .right { 230 | display: none; 231 | } 232 | } 233 | } 234 | } 235 | /*==================================== 236 | Questions / course 237 | =====================================*/ 238 | .questions { 239 | margin-top: 96px; 240 | width: 50vw; 241 | overflow: auto; 242 | padding: 40px; 243 | box-sizing: border-box; 244 | height: calc(100vh - 96px); 245 | } 246 | 247 | /*=================================== 248 | Answer 249 | ====================================*/ 250 | .answer { 251 | display: flex; 252 | flex-direction: column; 253 | justify-content: center; 254 | align-items: center; 255 | margin-top: 96px; 256 | width: 50vw; 257 | .out { 258 | position: absolute; 259 | top: calc(50vh + 120px); 260 | } 261 | } 262 | 263 | @media (max-width: 1000px) { 264 | body { 265 | flex-direction: column; 266 | } 267 | .questions { 268 | width: 100vw; 269 | height: calc(50vh - 96px); 270 | } 271 | .answer { 272 | width: 100vw; 273 | height: calc(50vh - 96px); 274 | } 275 | } 276 | 277 | /*====================================================================== 278 | Well Done section 279 | =======================================================================*/ 280 | 281 | .done { 282 | display: none; 283 | flex-direction: column; 284 | justify-content: center; 285 | align-items: center; 286 | position: absolute; 287 | top: 100vh; 288 | left: 0; 289 | width: 100vw; 290 | height: 100vh; 291 | z-index: 100; 292 | background: white; 293 | transition: all 500ms ease-in-out; 294 | &.active { 295 | transform: translateY(-100vh); 296 | } 297 | .continue { 298 | font-size: 3em; 299 | transition: font-size 100ms ease-in-out; 300 | i { 301 | font-size: inherit; 302 | } 303 | &:hover { 304 | font-size: 3.5em; 305 | } 306 | } 307 | } 308 | -------------------------------------------------------------------------------- /_sass/styles.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | color-scheme: light dark; 3 | --text-color: #000; 4 | --black: #000; 5 | --footer: #fafafa; 6 | --white: white; 7 | --background: white; 8 | --opposite: #1e1e1e; 9 | --semi-white: #eee; 10 | --blue: #0061D9; 11 | } 12 | 13 | .white { 14 | display: none; 15 | } 16 | 17 | @media (prefers-color-scheme: dark) { 18 | :root { 19 | --text-color: #fff; 20 | --black: #fff; 21 | --footer: #000; 22 | --white: #000; 23 | --background: #1e1e1e; 24 | --opposite: #fff; 25 | --semi-white: #333; 26 | } 27 | 28 | .white { 29 | display: block; 30 | } 31 | 32 | .black { 33 | display: none; 34 | } 35 | 36 | header:after { 37 | filter: invert(100%); 38 | -webkit-filter: invert(100%); 39 | } 40 | 41 | nav .logo { 42 | background: url("../img/logo-white.svg") !important; 43 | background-size: contain !important; 44 | } 45 | 46 | section.who .fusion { 47 | background: url("../img/fusion.svg") !important; 48 | background-size: contain !important; 49 | background-position: center !important; 50 | background-repeat: no-repeat !important; 51 | } 52 | } 53 | 54 | html { 55 | overflow-x: hidden 56 | } 57 | 58 | body { 59 | padding-top: 100px; 60 | margin-bottom: 300px; 61 | background: var(--background); 62 | overflow-x: hidden; 63 | font-family: SF Pro Display; 64 | font-style: normal; 65 | color: var(--text-color) 66 | } 67 | 68 | .mono { 69 | font-family: sf_monobold; 70 | } 71 | p.magnify { 72 | font-weight: 500; 73 | font-size: 18px; 74 | line-height: 24px; 75 | } 76 | 77 | * { 78 | z-index: 10; 79 | } 80 | 81 | nav { 82 | position: fixed; 83 | top: 0; 84 | width: 100vw; 85 | height: 100px; 86 | background-color: var(--white); 87 | z-index: 100; 88 | 89 | .logo { 90 | position: relative; 91 | left: 5vw; 92 | top: 0; 93 | width: 100px; 94 | height: 100px; 95 | background: url("../img/logo-black.svg"); 96 | background-size: contain; 97 | cursor: pointer; 98 | } 99 | 100 | .menu-container { 101 | position: fixed; 102 | top: 0; 103 | left: calc(5vw + 100px); 104 | right: calc(5vw + 100px); 105 | height: 100px; 106 | display: flex; 107 | justify-content: center; 108 | align-items: center; 109 | 110 | a { 111 | margin: 50px; 112 | color: var(--text-color); 113 | text-decoration: none; 114 | font-family: sf_monobold; 115 | font-size: 13px; 116 | line-height: 16px; 117 | /* identical to box height */ 118 | text-align: center; 119 | letter-spacing: 0.3em; 120 | } 121 | } 122 | #menu-toggle { 123 | display: none; 124 | width: 40px; 125 | height: 30px; 126 | position: fixed; 127 | top: 40px; 128 | right: 50px; 129 | // display: flex; 130 | justify-content: space-around; 131 | align-items: center; 132 | flex-direction: column; 133 | cursor: pointer; 134 | z-index: 100; 135 | .l { 136 | transition: all 250ms ease-in-out; 137 | width: 40px; 138 | height: 2px; 139 | background: var(--black); 140 | } 141 | &.cross { 142 | .l:nth-child(1) { 143 | transform: rotate(45deg) translate(0, calc(40px / 3)); 144 | } 145 | 146 | .l:nth-child(2) { 147 | opacity: 0; 148 | } 149 | 150 | .l:nth-child(3) { 151 | transform: rotate(-45deg) translate(0, calc(-40px / 3)); 152 | } 153 | } 154 | } 155 | } 156 | 157 | footer { 158 | position: fixed; 159 | bottom: 0; 160 | z-index: -10; 161 | width: 100vw; 162 | height: 300px; 163 | background: var(--footer); 164 | font-family: sf_monomedium; 165 | display: flex; 166 | justify-content: space-around; 167 | align-items: center; 168 | flex-wrap: wrap; 169 | color: var(--text-color); 170 | 171 | ul { 172 | li { 173 | opacity: 0.6; 174 | font-size: 24px; 175 | 176 | a { 177 | color: inherit; 178 | text-decoration: none; 179 | } 180 | } 181 | } 182 | 183 | .copyright { 184 | text-align: right; 185 | 186 | small { 187 | display: block; 188 | opacity: 0.6; 189 | 190 | a { 191 | color: inherit; 192 | } 193 | } 194 | } 195 | } 196 | 197 | 198 | @media (max-width: 800px) { 199 | header .welcontainer { 200 | left: 50% !important; 201 | transform: translateX(-50%); 202 | text-align: center; 203 | 204 | h1.welcome { 205 | font-size: 42px; 206 | 207 | span.big { 208 | font-size: 48px; 209 | } 210 | } 211 | 212 | h3 { 213 | font-size: 18px; 214 | max-width: none !important; 215 | } 216 | } 217 | 218 | nav .menu-container { 219 | display: none; 220 | position: fixed; 221 | top: 0; 222 | left: 0; 223 | background-color: var(--white); 224 | height: auto; 225 | flex-direction: column; 226 | width: 100vw; 227 | } 228 | #menu-toggle { 229 | display: flex !important; 230 | } 231 | 232 | article { 233 | section.who, .help { 234 | h1 { 235 | font-size: 42px; 236 | } 237 | 238 | .left, 239 | .right { 240 | max-width: calc(100vw - 100px); 241 | 242 | .fusion { 243 | width: calc(100vw - 100px); 244 | } 245 | 246 | h1 { 247 | font-size: 2em; 248 | line-break: anywhere; 249 | } 250 | 251 | p { 252 | font-size: 16px; 253 | line-height: 26px; 254 | } 255 | } 256 | } 257 | 258 | .help { 259 | .right { 260 | display: none; 261 | } 262 | } 263 | } 264 | footer .copyright { 265 | text-align: center; 266 | } 267 | } 268 | @media (max-width: 840px) { 269 | nav.container { 270 | max-width: 100%; 271 | } 272 | 273 | .levels { 274 | margin-top: 175px !important; 275 | } 276 | 277 | footer { 278 | margin-top: 175px; 279 | } 280 | } 281 | @media (max-width: 740px) { 282 | nav { 283 | #menu-toggle { 284 | display: block; 285 | } 286 | 287 | ul { 288 | position: absolute; 289 | top: 100%; 290 | background: rgba(#000, .7); 291 | left: 0; 292 | right: 0; 293 | text-align: center; 294 | height: 0; 295 | transition: height 500ms ease-in; 296 | overflow: hidden; 297 | 298 | li { 299 | display: block; 300 | margin: 0; 301 | text-align: center; 302 | 303 | a { 304 | line-height: 128px; 305 | } 306 | } 307 | 308 | &.active { 309 | height: 384px; 310 | 311 | &::after { 312 | content: ''; 313 | position: absolute; 314 | top: 20px; 315 | left: 0; 316 | right: 0; 317 | bottom: 0; 318 | box-shadow: 0 2px 4px -1px rgba(#000,.2), 0 4px 5px rgba(#000,.14), 0 1px 10px rgba(#000,.12); 319 | z-index: -999; 320 | } 321 | } 322 | } 323 | } 324 | } 325 | /*==================================== 326 | Article 327 | ====================================*/ 328 | article { 329 | background: var(--background); 330 | section { 331 | width: 100vw; 332 | box-sizing: border-box; 333 | padding: 50px; 334 | 335 | &.what { 336 | display: flex; 337 | justify-content: center; 338 | align-items: center; 339 | flex-direction: column; 340 | width: 960px; 341 | max-width: 80%; 342 | margin: 0 auto; 343 | text-align: left; 344 | 345 | p { 346 | margin-top: 10px; 347 | text-align: justify; 348 | 349 | a { 350 | box-sizing: border-box; 351 | text-align: center; 352 | display: inline-block; 353 | padding: 12px 64px; 354 | background-color: var(--blue); 355 | color: #fff; 356 | text-decoration: inherit; 357 | margin-top: 48px; 358 | 359 | &:hover { 360 | text-decoration: underline; 361 | } 362 | } 363 | 364 | span.italic { 365 | margin-top: 20px; 366 | font-style: italic; 367 | opacity: 0.7; 368 | } 369 | } 370 | } 371 | 372 | &.levels { 373 | width: 960px; 374 | max-width: 80%; 375 | margin: 0 auto; 376 | padding: 50px 0; 377 | 378 | .progress { 379 | width: 0px; 380 | margin-left: 10px; 381 | height: 5px; 382 | background: #4CAF50; 383 | box-sizing: border-box; 384 | margin: 10px; 385 | transition: width 1s ease-in-out; 386 | .bg { 387 | &:after { 388 | content: ''; 389 | position: absolute; 390 | width: 940px; 391 | max-width: 80%; 392 | margin: 0 auto; 393 | height: 5px; 394 | background: rgba(0, 0, 0, 0.1); 395 | } 396 | } 397 | } 398 | 399 | .row { 400 | display: flex; 401 | flex-direction: row; 402 | flex-wrap: wrap; 403 | width: 100%; 404 | margin: 0 auto; 405 | position: relative; 406 | 407 | a { 408 | color: var(--text-color); 409 | text-decoration: none; 410 | text-align: center; 411 | padding: 32px 0 0; 412 | width: 220px; 413 | box-sizing: border-box; 414 | margin: 10px; 415 | vertical-align: top; 416 | top: 0; 417 | overflow: hidden; 418 | border-radius: 4px; 419 | box-shadow: 0 3px 1px -2px rgba(#000,.2), 0 2px 2px rgba(#000,.14), 0 1px 5px rgba(#000,.12); 420 | transition: box-shadow 250ms ease, transform 250ms ease; 421 | 422 | &:hover { 423 | box-shadow: 0 2px 4px -1px rgba(#000,.2), 0 4px 5px rgba(#000,.14), 0 1px 10px rgba(#000,.12); 424 | transform: translateY(-4px); 425 | } 426 | 427 | h3 { 428 | color: #fff; 429 | background-color: var(--blue); 430 | margin: 32px 0 0; 431 | padding: 24px 0; 432 | } 433 | 434 | .done { 435 | opacity: 0; 436 | position: absolute; 437 | transform: translate(100px, -42px); 438 | width: 20px; 439 | height: 20px; 440 | border-radius: 50%; 441 | background: #4CAF50; 442 | } 443 | } 444 | } 445 | 446 | .expand { 447 | display: flex; 448 | justify-content: center; 449 | align-items: center; 450 | 451 | .more { 452 | display: inline-flex; 453 | vertical-align: middle; 454 | align-items: center; 455 | margin: 0 auto; 456 | box-sizing: border-box; 457 | text-align: center; 458 | padding: 12px 64px; 459 | background-color: var(--blue); 460 | color: #fff; 461 | text-decoration: inherit; 462 | margin-top: 48px; 463 | cursor: pointer; 464 | transition: all 250ms ease, top 250ms ease; 465 | 466 | &:hover { 467 | box-shadow: 0 2px 4px -1px rgba(#000,.2), 0 4px 5px rgba(#000,.14), 0 1px 10px rgba(#000,.12); 468 | top: -4px; 469 | } 470 | } 471 | } 472 | } 473 | } 474 | } 475 | /*======================================== 476 | Be on a computer 477 | ========================================*/ 478 | .beoncomp { 479 | position: relative; 480 | top: 0; 481 | left: 0; 482 | width: 100%; 483 | height: 100%; 484 | background: white; 485 | display: none; 486 | flex-direction: column; 487 | justify-content: center; 488 | align-items: center; 489 | box-sizing: border-box; 490 | padding: 10vw; 491 | font-size: 20px; 492 | text-align: center; 493 | 494 | i { 495 | font-size: 3em; 496 | } 497 | } 498 | -------------------------------------------------------------------------------- /api/challenges.json: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | { 4 | "title": "CrypTools - Learn", 5 | "description": "An online platform to learn cryptography", 6 | "url": "https://cryptools.github.io/learn", 7 | "challenges": { 8 | "js": {{site.data.challenges | jsonify}}, 9 | "noob": {{site.data.noob | jsonify}} 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /challenges/b64.md: -------------------------------------------------------------------------------- 1 | # Base64 2 | 3 | # Encoding 4 | 5 | Let's try to encrypt a piece text, for example `"Hello World!"` 6 | 7 | Now, we'll take it's ASCII representation: 8 | ``` 9 | 72 101 108 108 111 10 119 111 114 108 100 33 10 | ``` 11 | We'll convert that to binary: 12 | ``` 13 | 01001000 01100101 01101100 01101100 01101111 00100000 01010111 01101111 01110010 01101100 01100100 00100001 14 | ``` 15 | After that, we'll split this 8 bit stream to a 6 bit stream: 16 | ``` 17 | 010010 000110 010101 101100 011011 000110 111100 100000 010101 110110 111101 110010 011011 000110 010000 100001 18 | ``` 19 | > If your string cannot split up in a 6 bit stream, add padding '0' at the end, we'll replace them by '=' 20 | 21 | Now, we'll convert this 6 bit stream to numbers in base 10: 22 | ``` 23 | 18 6 21 44 27 6 60 32 21 54 61 50 27 6 16 33 24 | ``` 25 | And using the Base64 table: 26 | ``` 27 | ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ 28 | ``` 29 | We have: 30 | ``` 31 | SGVsbG8gV29ybGQh 32 | ``` 33 | 34 | # What you need to do: 35 | **Without the decoding informations, create a Base64 decode function** 36 | ## Requirements: 37 | 38 | - Your program should use this template: 39 | 40 | ```javascript 41 | String.prototype.decrypt = function() { 42 | // to get the String you need to encrypt, use 'this' 43 | } 44 | ``` 45 | -------------------------------------------------------------------------------- /challenges/binascii.md: -------------------------------------------------------------------------------- 1 | # Binascii 2 | 3 | # How it works? 4 | 5 | ## Encoding 6 | 7 | ASCII stands for **A**merican **S**tandard **C**ode for **I**nformation **I**nterchange. 8 | 9 | It's a simple way of encoding characters to numbers. 10 | 11 | We can express these characters as hexadecimal (base 16) numbers using this table: 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 |
0NUL16DLE32SP48064@80P96`112p
1SOH17DC133!49165A81Q97a113q
2STX18DC234"50266B82R98b114r
3ETX19DC335#51367C83S99c115s
4EOT20DC436$52468D84T100d116t
5ENQ21NAK37%53569E85U101e117u
6ACK22SYN38&54670F86V102f118v
7BEL23ETB39'55771G87W103g119w
8BS24CAN40(56872H88X104h120x
9HT25EM41)57973I89Y105i121y
10LF26SUB42*58:74J90Z106j122z
11VT27ESC43+59;75K91[107k123{
12FF28FS44,60<76L92\108l124|
13CR29GS45-61=77M93]109m125}
14SO30RS46.62>78N94^110n126~
15SI31US47/63?79O95_111o127DEL
305 | 306 | So we know that `A` correspond to `65` in decimal (base 10). 307 | 308 | ### Convert decimal to Binary 309 | - Take any number `N`. 310 | 311 | - Keep dividing `N` by `2` and write down the remainder (`0` or `1`) 312 | - Reverse the list of remainder 313 | 314 | - Add padding `0`s at the beginning, so for example if we have `101` and we want an 8-bit stream, we output `00000101`. 315 | 316 | # What you need to do? 317 | Using this explanation, write a program that can **decode** 8 bit stream. 318 | 319 | ## Requirements 320 | - Your program should handle stream where there are no space between 8 bit numbers. 321 | - You should use the following template: 322 | ```js 323 | String.prototype.decrypt = function() { 324 | // to get the String you need to encrypt, use 'this' 325 | } 326 | ``` 327 | -------------------------------------------------------------------------------- /challenges/bitshift-encrypt.md: -------------------------------------------------------------------------------- 1 | # BitShift Cipher 2 | ## How it works 3 | 4 | ### Encoding 5 | 6 | The Bitshift Cipher works by (as the name suggests) shifting over the bits of the text's ASCII. We do this using the bitwise `<<` operator, which is used to shift the bits a certain number of places. 7 | 8 | To encode the text, we loop through the text, and for each character `x`, we loop through the key array, and for each key character `i`: 9 | 10 | ```py 11 | x = x + 1 << i % 8 12 | ``` 13 | 14 | We limit the maximum shift using modulo to avoid having a bit shifted by hundreds of places 15 | 16 | Example: 17 | 18 | Let's imagine we are currently working on the character `A`, and that our key is `YO` 19 | 20 | ```Python 21 | A = 0b01000001 # ASCII for A 22 | 0b01000010 # plus 1 23 | 0b010000100 # Y is 89, 89 % 8 = 1, so we add 1 zero. 24 | # next charachter in key: O 25 | 0b010000101 # plus 1 26 | 0b0100001010000000 # O is 79, 79 % 8 = 7, so we add 7 zeros. 27 | ``` 28 | 29 | After each character is encoded, we add it to an array and reverse the key to make frequency analysis harder. 30 | 31 | Let's say the next character in our string is `B`, our key now is `OY`, as it was reversed. 32 | 33 | ```Python 34 | B = 0b01000010 # ASCII for B 35 | 0b01000011 # plus 1 36 | 0b010000110000000 # O is 79, 79 % 8 = 7, so we add 7 zeros. 37 | # next character in key: Y 38 | 0b010000110000001 # plus 1 39 | 0b0100001100000010 # Y is 89, 89 % 8 = 1, so we add 1 zero. 40 | ``` 41 | 42 | Our array now looks like this: `[0b0100001010000000, 0b0100001100000010]`, or in decimal: `[17024, 17154]`. 43 | 44 | Finally, we encode the array in base64 to get the final encrypted string: `'WzE3MDI0LCAxNzE1NF0='`. 45 | 46 | # What you need to do 47 | 48 | **Using this explanation, recreate a function that encrypts a phrase such as `Hello World!` using any key** 49 | 50 | ## Requirements: 51 | 52 | - Your program should use this template: 53 | 54 | ```javascript 55 | String.prototype.encrypt = function(key) { 56 | // to get the String you need to encrypt, use 'this' 57 | } 58 | ``` 59 | -------------------------------------------------------------------------------- /challenges/caesar-decrypt.md: -------------------------------------------------------------------------------- 1 | # Caesar Cipher 2 | 3 | ## History and usage 4 | 5 | The _Caesar Cipher_ was named after Julius Caesar (100 B.C. – 44 B.C). He would use the cipher for secret communication (protect messages of military significance). The Caesar Cipher is a **substitution cipher**. Originally, Julius Caesar would use a shift of three to encrypt/decrypt a message. The Caesar Cipher encrypts a message using an affine function : f(x) = 1x + b. 6 | 7 | ## Detailed Explanations : How it works? 8 | 9 | 1. Firstly, each character of the initial text (message to encrypt) is converted in a number from 0 to 25, corresponding to its position in the Latin alphabet which contains 26 letters --> (a = 0, b = 1 ... z = 25 ). 10 | 11 | 2. Then, each number obtained is transformed by an affine function (f(x) = 1x + b). "x" is representing the number while "b" is defined during the encryption. "b" is the key used to decrypt the final message. 12 | 13 | 3. If we take all the images and put them in a list, we obtain n numbers corresponding to n characters of the initial text. The next step consists in finding the values of modulo 26 of each number. (**Modulo means remainder**) 14 | 15 | > Example : Modulo 4 of 19 is **3** because `19 = 4 * 4 + 3` In the other hand, modulo 26 of 26 is **0** because `26 = 26 * 1 + 0` 16 | 17 | 1. Therefore, we obtain a new list with n element, each between 0 and 25 both included. All these numbers are converted in letters of the Latin Alphabet using the tables below. 18 | 19 | 2. We finally create the final message by putting all the letters side by side. 20 | 21 | Steps 1 and 4 can be done with these tables : 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 |
ABCDEFGHIJKLMNOPQRSTUVWXYZ
012345678910111213141516171819202122232425
85 | 86 | # What you need to do: 87 | 88 | **Using this explanation, recreate a function that decrypts a word previously encrypted such as `LIPPS` using any key** 89 | 90 | ## Requirements: 91 | 92 | - Your program should be case insensitive, and return only upper cased letters. 93 | - Your program should use this template: 94 | 95 | ```javascript 96 | String.prototype.decrypt = function(key) { 97 | // to get the String you need to decrypt, use 'this' 98 | } 99 | ``` 100 | -------------------------------------------------------------------------------- /challenges/caesar-encrypt.md: -------------------------------------------------------------------------------- 1 | # Caesar Cipher 2 | 3 | ## History and usage 4 | 5 | The _Caesar Cipher_ was named after Julius Caesar (100 B.C. – 44 B.C). He would use the cipher for secret communication (protect messages of military significance). The Caesar Cipher is a **substitution cipher**. Originally, Julius Caesar would use a shift of three to encrypt/decrypt a message. The Caesar Cipher encrypts a message using an affine function : f(x) = 1x + b. 6 | 7 | ## Detailed Explanations : How it works? 8 | 9 | 1. Firstly, each character of the initial text (message to encrypt) is converted in a number from 0 to 25, corresponding to its position in the Latin alphabet which contains 26 letters --> (a = 0, b = 1 ... z = 25 ). 10 | 11 | 2. Then, each number obtained is transformed by an affine function (f(x) = 1x + b). "x" is representing the number while "b" is defined during the encryption. "b" is the key used to decrypt the final message. 12 | 13 | 3. If we take all the images and put them in a list, we obtain n numbers corresponding to n characters of the initial text. The next step consists in finding the values of modulo 26 of each number. (**Modulo means remainder**) 14 | 15 | > Example : Modulo 4 of 19 is **3** because `19 = 4 * 4 + 3` In the other hand, modulo 26 of 26 is **0** because `26 = 26 * 1 + 0` 16 | 17 | 1. Therefore, we obtain a new list with n element, each between 0 and 25 both included. All these numbers are converted in letters of the Latin Alphabet using the tables below. 18 | 19 | 2. We finally create the final message by putting all the letters side by side. 20 | 21 | Steps 1 and 4 can be done with these tables : 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 |
ABCDEFGHIJKLMNOPQRSTUVWXYZ
012345678910111213141516171819202122232425
85 | 86 | # What you need to do: 87 | 88 | **Using this explanation, recreate a function that encrypts a word such as `Hello` using any key** 89 | 90 | ## Requirements: 91 | 92 | - Your program should be case insensitive, and return only upper cased letters. 93 | - Your program should use this template: 94 | 95 | ```javascript 96 | String.prototype.encrypt = function(key) { 97 | // to get the String you need to encrypt, use 'this' 98 | } 99 | ``` 100 | -------------------------------------------------------------------------------- /challenges/emojigraphy.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | This is the first challenge of this platform. It's pretty easy, but don't worry, it will get harder in 3 | the next challenges. 4 | 5 | ### Tutorial: 6 | - On this section, you'll always see the 'course' and the challenge that you need to do 7 | - On the upper right corner, there is the code editor. This is where you'll write your answer (in JavaScript of course). 8 | - On the lower right corner, you'll see the console. This is where you'll know if you failed or not. 9 | > **ProTips 💡:** 10 | - Press `Ctrl+Enter` (or `Cmd + Enter` on macOS) to execute your code right from the editor. 11 | - Press `Shift+Enter` to enter full screen mode. (Press `Esc` to exit) 12 | - Press `Ctrl+Shift+C` (or `Cmd + Shift + C` on macOS) to clear the console 13 | 14 | # Emoji cipher 15 | 16 | The Emoji cipher is a very basic cipher. 17 | 18 | Basically, we convert letters to emojis to encode a message, and we do the opposite operation to decode this encrypted message. 19 | 20 | Here is the table: 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 |
ABCDEFGHIJKLMNOPQRSTUVWXYZ
😄😃😀😊😅😉😍😘😚😗😙😜😝😛😳😁😔😌😒😞😣😢😂😭😎😈
83 | 84 | # What you need to do 85 | 86 | **Using this explanation, recreate a function that encrypts a word such as `Hello` using any key** 87 | 88 | ## Requirements: 89 | 90 | - Your program should be case insensitive. 91 | - Your program should use this template: 92 | 93 | ```javascript 94 | String.prototype.encrypt = function() { 95 | // to get the String you need to encrypt, use 'this' 96 | } 97 | ``` 98 | -------------------------------------------------------------------------------- /challenges/hashshift.md: -------------------------------------------------------------------------------- 1 | # HashShift 2 | 3 | ## How it works? 4 | 5 | > We'll use the Swift implementation to describe what we're doing 6 | 7 | First, let's take a seed for our generator: 8 | 9 | ```swift 10 | var seed = 12 11 | ``` 12 | 13 | Then let's hash his `String` representation: 14 | 15 | ```swift 16 | let hash = String(seed).sha256 17 | ``` 18 | 19 | Now, we'll take the `10` first characters of the outputed hex digest: 20 | 21 | ```swift 22 | let first = hash.prefix(10) 23 | ``` 24 | 25 | Now we have a `hex` representation of a number in a `String`, let's parse it: 26 | 27 | ```swift 28 | let n = Int(first, radix: 16) 29 | ``` 30 | 31 | Then, we rotate `n` like: 32 | 33 | ```swift 34 | let r = (n! >> 13 * seed) % 99371 // for non-swift developers, 'n!' doesn't mean n factorial but the unwrapped value of n 35 | ``` 36 | 37 | And we change the `seed`: 38 | 39 | ```swift 40 | seed = (r ^ n! << 2 + n!) % 70937 41 | ``` 42 | 43 | Finally we output the absolute value as `Float` of `r` divided by `99371` to have a number between `0` and `1`: 44 | 45 | ```swift 46 | return Float(abs(r)) / 99371 47 | ``` 48 | 49 | # What you need to do: 50 | 51 | **Using this explanation, create a HashShift PRNG generator.** 52 | 53 | ## Requirements: 54 | - Your program should use this template: 55 | 56 | ```javascript 57 | String.prototype.sha256=function(){let r=this;const n=8,t=0;function e(r,n){const t=(65535&r)+(65535&n);return(r>>16)+(n>>16)+(t>>16)<<16|65535&t}function o(r,n){return r>>>n|r<<32-n}function u(r,n){return r>>>n}function c(r,n,t){return r&n^~r&t}function f(r,n,t){return r&n^r&t^n&t}function i(r){return o(r,2)^o(r,13)^o(r,22)}function a(r){return o(r,6)^o(r,11)^o(r,25)}function h(r){return o(r,7)^o(r,18)^u(r,3)}return function(r){const n=t?"0123456789ABCDEF":"0123456789abcdef";let e="";for(let t=0;t<4*r.length;t++)e+=n.charAt(r[t>>2]>>8*(3-t%4)+4&15)+n.charAt(r[t>>2]>>8*(3-t%4)&15);return e}(function(r,n){const t=new Array(1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298),C=new Array(1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225),g=new Array(64);let l,d,A,s,S,m,y,p,v,w;r[n>>5]|=128<<24-n%32,r[15+(n+64>>9<<4)]=n;for(var b=0;b>5]|=(r.charCodeAt(o/n)&e)<<24-o%32;return t}(r=function(r){r=r.replace(/\r\n/g,"\n");let n="";for(let t=0;t127&&e<2048?(n+=String.fromCharCode(e>>6|192),n+=String.fromCharCode(63&e|128)):(n+=String.fromCharCode(e>>12|224),n+=String.fromCharCode(e>>6&63|128),n+=String.fromCharCode(63&e|128))}return n}(r)),r.length*n))}; 58 | 59 | // To use SHA256, do something like: "some text".sha256() 60 | 61 | function* rand(seed) { 62 | while (true) { 63 | yield out // out is the outtputed number. 64 | } 65 | } 66 | ``` 67 | -------------------------------------------------------------------------------- /challenges/inverse.md: -------------------------------------------------------------------------------- 1 | # Question: 2 | If FIND is coded as URMW and ME is coded as NV, then **create a function that will reproduce this effect on any string** 3 | 4 | ## Help? 5 | You should look at this alphabet table: 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
ABCDEFGHIJKLMNOPQRSTUVWXYZ
39 | 40 | ## Requirements: 41 | 42 | - Your program should be case **insensitive**, and return capital letters only. 43 | - Your program should use this template: 44 | 45 | ```javascript 46 | String.prototype.encrypt = function() { 47 | // to get the String you need to encrypt, use 'this' 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /challenges/lost.md: -------------------------------------------------------------------------------- 1 | # Concept of Hash 2 | A cryptographic hash function is a special class of hash function that has certain properties which make it suitable for use in cryptography. 3 | 4 | It is a mathematical algorithm that maps data of arbitrary size to a bit string of a fixed size (a hash) and is designed to be a one-way function, that is, a function which is infeasible to invert. 5 | 6 | The only way to recreate the input data from an ideal cryptographic hash function's output is to attempt a brute-force search of possible inputs to see if they produce a match, or use a rainbow table of matched hashes. 7 | 8 | Bruce Schneier has called one-way hash functions "the workhorses of modern cryptography". The input data is often called the message, and the output (the hash value or hash) is often called the message digest or simply the digest. 9 | 10 | The ideal cryptographic hash function has five main properties: 11 | 12 | - it is deterministic so the same message always results in the same hash 13 | - it is quick to compute the hash value for any given message 14 | - it is infeasible to generate a message from its hash value except by trying all possible messages 15 | - a small change to a message should change the hash value so extensively that the new hash value appears - uncorrelated with the old hash value 16 | - it is infeasible to find two different messages with the same hash value 17 | 18 | # Problem 19 | At CrypTools, one of our admin forgot his password, but GitHub was able to obtain and give us a `SHA256` hash of his password: 20 | ``` 21 | 88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589 22 | ``` 23 | Hopefully, he remember that his password is only 4 letters long and that his password was made of lower cased letters. 24 | 25 | # What you need to do? 26 | Using the hash function `SHA256` that we provide, create a function that will brute force the hash and will output the password. 27 | ## Requirements: 28 | - Your program should use this template: 29 | 30 | ```javascript 31 | String.prototype.sha256=function(){let r=this;const n=8,t=0;function e(r,n){const t=(65535&r)+(65535&n);return(r>>16)+(n>>16)+(t>>16)<<16|65535&t}function o(r,n){return r>>>n|r<<32-n}function u(r,n){return r>>>n}function c(r,n,t){return r&n^~r&t}function f(r,n,t){return r&n^r&t^n&t}function i(r){return o(r,2)^o(r,13)^o(r,22)}function a(r){return o(r,6)^o(r,11)^o(r,25)}function h(r){return o(r,7)^o(r,18)^u(r,3)}return function(r){const n=t?"0123456789ABCDEF":"0123456789abcdef";let e="";for(let t=0;t<4*r.length;t++)e+=n.charAt(r[t>>2]>>8*(3-t%4)+4&15)+n.charAt(r[t>>2]>>8*(3-t%4)&15);return e}(function(r,n){const t=new Array(1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298),C=new Array(1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225),g=new Array(64);let l,d,A,s,S,m,y,p,v,w;r[n>>5]|=128<<24-n%32,r[15+(n+64>>9<<4)]=n;for(var b=0;b>5]|=(r.charCodeAt(o/n)&e)<<24-o%32;return t}(r=function(r){r=r.replace(/\r\n/g,"\n");let n="";for(let t=0;t127&&e<2048?(n+=String.fromCharCode(e>>6|192),n+=String.fromCharCode(63&e|128)):(n+=String.fromCharCode(e>>12|224),n+=String.fromCharCode(e>>6&63|128),n+=String.fromCharCode(63&e|128))}return n}(r)),r.length*n))}; 32 | 33 | // To use SHA256, do something like: "some text".sha256() 34 | function bruteforce() { 35 | const hash = "88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589" 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /challenges/railfence-encoding.md: -------------------------------------------------------------------------------- 1 | # Railfence Cipher 2 | 3 | A transposition cipher also called the zigzag cipher. 4 | 5 | ## How it works 6 | 7 | ### Encoding 8 | 9 | The Rail Fence Cipher places the letters in a zigzag pattern before reading them again, from top to bottom, right to left, ignoring the zigzag. 10 | 11 | Example: 12 | 13 | Let's imagine that we are encoding `Hello World!` on 3 rails. we draw out our three rails and place the lettres in the zigzag pattern like this: 14 | 15 | ```txt 16 | H - - - o - - - r - - - 17 | - e - l - - o - l - ! 18 | - - l - - - w - - - d - 19 | ``` 20 | 21 | When this is read top to bottom, left to right, we get `Horel ol!lwd` 22 | 23 | ## Requirements: 24 | 25 | - Your program should be case **sensitive** and should support any Unicode symbols 26 | - Your program should use this template: 27 | 28 | ```javascript 29 | String.prototype.encrypt = function(key) { // key is the number of rails 30 | // to get the String you need to encrypt, use 'this' 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /challenges/rot13.md: -------------------------------------------------------------------------------- 1 | # ROT13 2 | 3 | A stupidly simple reversible substitution cipher. 4 | 5 | > ROT13 was in use in the net.jokes newsgroup by the early 1980s. It is used to hide potentially offensive jokes, or to obscure an answer to a puzzle or other spoiler. - Wikipedia 6 | 7 | # How it works 8 | 9 | ## Encoding 10 | 11 | The ROT13 cipher will substitute each letter by the letter coming 13 places after it in the alphabet. According to this logic, N should map to the 27th character of the alphabet, but we only have 26 characters, so we loop the alphabet around. We now have the formula `ROT13(c) = (c + 13) % 26`, where c is the position in the alphabet of a given character. 12 | 13 | Therefore, `A => N, B => O, ..., M => Z, N => A` 14 | 15 | When encoding a string, we replace uppercase characters with their uppercase mirror, lowercase character with their lowercase mirror, and leave all other characters untouched. 16 | 17 | To help us with the encoding process, we create a lookup table like this: 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
ABCDEFGHIJKLM
NOPQRSTUVWXYZ
55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 |
NOPQRSTUVWXYZ
ABCDEFGHIJKLM
92 | Example: 93 | 94 | Let's encode the string `Hello World!`. We need to lookup each character in our table, and then write down its image. 95 | 96 | ``` 97 | H => U 98 | e => r 99 | l => y 100 | ... 101 | _ => _ # space maps to space. 102 | W => J 103 | ... 104 | ! => ! 105 | ``` 106 | 107 | Our final encoded string is `Urryb Jbeyq!`. 108 | 109 | ## Decoding 110 | 111 | As you might have noticed from the lookup table, `ROT13(ROT13(c)) = c`. This cipher is therefore reversible, and to decode, we just need to go through the whole encoding process once more. 112 | 113 | Example: 114 | 115 | Our encoded output was `Urryb Jbeyq!`. We need to lookup each character in our table, and then write down its image. 116 | 117 | ``` 118 | U => H 119 | r => e 120 | y => l 121 | ... 122 | _ => _ # space maps to space. 123 | J => W 124 | ... 125 | ! => ! 126 | ``` 127 | 128 | Our final decoded string is `Hello World!`. 129 | 130 | 131 | # What you need to do: 132 | **Using this explanation, recreate a function that encrypts a word such as `Hello`** 133 | 134 | ## Requirements: 135 | - Your program should be case insensitive, and return only upper cased letters. 136 | - Your program should use this template: 137 | 138 | ```javascript 139 | String.prototype.encrypt = function() { 140 | // to get the String you need to encrypt, use 'this' 141 | } 142 | ``` 143 | -------------------------------------------------------------------------------- /challenges/rsa.md: -------------------------------------------------------------------------------- 1 | # RSA 2 | **The RSA encryption is based on the following procedure:** 3 | 4 | Generate two distinct primes p and q. 5 | Compute `n = pq` and `φ = (p - 1)(q - 1)`. 6 | Find an integer `e`, `1 < e < φ`, such that `gcd(e, φ) = 1`. 7 | 8 | A message in this system is a number in the interval `[0, n - 1]`. 9 | A text to be encrypted is then somehow converted to messages (numbers in the interval `[0, n - 1]`). 10 | To encrypt the text, for each message, `m`, `c = me mod n` is calculated. 11 | 12 | To decrypt the text, the following procedure is needed: calculate `d` such that `ed = 1 mod φ`, then for each encrypted message, `c`, calculate `m = cd mod n`. 13 | 14 | There exist values of `e` and `m` such that `me mod n = m`. 15 | We call messages m for which me mod n=m unconcealed messages. 16 | 17 | An issue when choosing e is that there should not be too many unconcealed messages. 18 | For instance, let `p = 19` and `q = 37`. 19 | Then `n= 19*37 = 703` and `φ = 18*36 = 648`. 20 | If we choose `e=181`, then, although `gcd(181, 648) = 1` it turns out that all possible messages 21 | `m (0 ≤ m ≤ n - 1)` are unconcealed when calculating `me mod n`. 22 | For any valid choice of `e` there exist some unconcealed messages. 23 | > It's important that the number of unconcealed messages is at a minimum. 24 | 25 | # What you need to do: 26 | - Choose `p = 1009` and `q = 3643`. 27 | 28 | Find the sum of all values of e, `1< e <φ(1009,3643)` and `gcd(e, φ) = 1`, so that the number of unconcealed messages for this value of `e` is at a minimum. 29 | 30 | ## Requirements: 31 | - Your program should use this template: 32 | 33 | ```javascript 34 | function rsa() { 35 | return n // n is the answer 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /challenges/xorcipher.md: -------------------------------------------------------------------------------- 1 | # XORCipher 2 | A simple adaptive cipher based on the logical XOR operation. 3 | 4 | ## How it works 5 | 6 | ### Encoding 7 | 8 | The XOR cipher will encrypt a message by using the Boolean XOR (exclusive or) operation. A XOR B returns 1 if and only if A and B are different. 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
ABA XOR B
000
011
101
110
41 | 42 | To encrypt a message with a given key, we first convert the string into their ASCII equivalent, and we then XOR every character with the key. For example, if we want to encrypt XOR with 134 as a key, we would do: 43 | 44 | ```txt 45 | X O R 46 | 01011000 01001111 01010010 # String in ASCII 47 | 10000110 10000110 10000110 # Repeating key 134 48 | -------------------------- 49 | 11011110 11001001 11010100 # XOR result 50 | Þ É Ô # Result converted back into plain text 51 | ``` 52 | 53 | When implemented in JavaScript, we get `char ^ key`. 54 | 55 | As you might have noticed, in this cipher, a given character is always replaced by the same character. This makes frequency analysis easier. To avoid that, we can use a non-repeating key eg. `29, 62, 134`, where we loop through the keys to encode each character. 56 | 57 | ```txt 58 | X O R 59 | 88 79 82 60 | 29 62 134 61 | ---------- 62 | 69 113 212 63 | E q Ô 64 | ``` 65 | 66 | # What you need to do: 67 | 68 | **Using this explanation, recreate a function that encrypts a word such as `Hello` using any key** 69 | 70 | ## Requirements: 71 | 72 | - Your program should be case insensitive, and return only upper cased letters. 73 | - Your program should use this template: 74 | 75 | ```javascript 76 | String.prototype.encrypt = function(key) { // key is a number or an array 77 | // to get the String you need to encrypt, use 'this' 78 | } 79 | ``` 80 | -------------------------------------------------------------------------------- /css/challenges.scss: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | /*! HTML5 Boilerplate v5.3.0 | MIT License | https://html5boilerplate.com/ */ 5 | 6 | /* 7 | * What follows is the result of much research on cross-browser styling. 8 | * Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal, 9 | * Kroc Camen, and the H5BP dev community and team. 10 | */ 11 | 12 | /* ========================================================================== 13 | Base styles: opinionated defaults 14 | ========================================================================== */ 15 | 16 | html { 17 | color: #222; 18 | font-size: 1em; 19 | line-height: 1.4; 20 | } 21 | 22 | /* 23 | * Remove text-shadow in selection highlight: 24 | * https://twitter.com/miketaylr/status/12228805301 25 | * 26 | * These selection rule sets have to be separate. 27 | * Customize the background color to match your design. 28 | */ 29 | 30 | ::-moz-selection { 31 | background: #b3d4fc; 32 | text-shadow: none; 33 | } 34 | 35 | ::selection { 36 | background: #b3d4fc; 37 | text-shadow: none; 38 | } 39 | 40 | /* 41 | * A better looking default horizontal rule 42 | */ 43 | 44 | hr { 45 | display: block; 46 | height: 1px; 47 | border: 0; 48 | border-top: 1.5px solid #ccc; 49 | margin: 1em 0; 50 | padding: 0; 51 | } 52 | 53 | /* 54 | * Remove the gap between audio, canvas, iframes, 55 | * images, videos and the bottom of their containers: 56 | * https://github.com/h5bp/html5-boilerplate/issues/440 57 | */ 58 | 59 | audio, 60 | canvas, 61 | iframe, 62 | img, 63 | svg, 64 | video { 65 | vertical-align: middle; 66 | } 67 | 68 | /* 69 | * Remove default fieldset styles. 70 | */ 71 | 72 | fieldset { 73 | border: 0; 74 | margin: 0; 75 | padding: 0; 76 | } 77 | 78 | /* 79 | * Allow only vertical resizing of textareas. 80 | */ 81 | 82 | textarea { 83 | resize: vertical; 84 | } 85 | 86 | /* ========================================================================== 87 | Browser Upgrade Prompt 88 | ========================================================================== */ 89 | 90 | .browserupgrade { 91 | margin: 0.2em 0; 92 | background: #ccc; 93 | color: #000; 94 | padding: 0.2em 0; 95 | } 96 | 97 | /* ========================================================================== 98 | Author's custom styles 99 | ========================================================================== */ 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | @import "styles-challenges.scss"; 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | /* ========================================================================== 118 | Helper classes 119 | ========================================================================== */ 120 | 121 | /* 122 | * Hide visually and from screen readers 123 | */ 124 | 125 | .hidden { 126 | display: none !important; 127 | } 128 | 129 | /* 130 | * Hide only visually, but have it available for screen readers: 131 | * https://snook.ca/archives/html_and_css/hiding-content-for-accessibility 132 | * 133 | * 1. For long content, line feeds are not interpreted as spaces and small width 134 | * causes content to wrap 1 word per line: 135 | * https://medium.com/@jessebeach/beware-smushed-off-screen-accessible-text-5952a4c2cbfe 136 | */ 137 | 138 | .visuallyhidden { 139 | border: 0; 140 | clip: rect(0 0 0 0); 141 | height: 1px; 142 | margin: -1px; 143 | overflow: hidden; 144 | padding: 0; 145 | position: absolute; 146 | width: 1px; 147 | white-space: nowrap; /* 1 */ 148 | } 149 | 150 | /* 151 | * Extends the .visuallyhidden class to allow the element 152 | * to be focusable when navigated to via the keyboard: 153 | * https://www.drupal.org/node/897638 154 | */ 155 | 156 | .visuallyhidden.focusable:active, 157 | .visuallyhidden.focusable:focus { 158 | clip: auto; 159 | height: auto; 160 | margin: 0; 161 | overflow: visible; 162 | position: static; 163 | width: auto; 164 | white-space: inherit; 165 | } 166 | 167 | /* 168 | * Hide visually and from screen readers, but maintain layout 169 | */ 170 | 171 | .invisible { 172 | visibility: hidden; 173 | } 174 | 175 | /* 176 | * Clearfix: contain floats 177 | * 178 | * For modern browsers 179 | * 1. The space content is one way to avoid an Opera bug when the 180 | * `contenteditable` attribute is included anywhere else in the document. 181 | * Otherwise it causes space to appear at the top and bottom of elements 182 | * that receive the `clearfix` class. 183 | * 2. The use of `table` rather than `block` is only necessary if using 184 | * `:before` to contain the top-margins of child elements. 185 | */ 186 | 187 | .clearfix:before, 188 | .clearfix:after { 189 | content: " "; /* 1 */ 190 | display: table; /* 2 */ 191 | } 192 | 193 | .clearfix:after { 194 | clear: both; 195 | } 196 | 197 | /* ========================================================================== 198 | EXAMPLE Media Queries for Responsive Design. 199 | These examples override the primary ('mobile first') styles. 200 | Modify as content requires. 201 | ========================================================================== */ 202 | 203 | @media only screen and (min-width: 35em) { 204 | /* Style adjustments for viewports that meet the condition */ 205 | } 206 | 207 | @media print, 208 | (-webkit-min-device-pixel-ratio: 1.25), 209 | (min-resolution: 1.25dppx), 210 | (min-resolution: 120dpi) { 211 | /* Style adjustments for high resolution devices */ 212 | } 213 | 214 | /* ========================================================================== 215 | Print styles. 216 | Inlined to avoid the additional HTTP request: 217 | http://www.phpied.com/delay-loading-your-print-css/ 218 | ========================================================================== */ 219 | 220 | @media print { 221 | *, 222 | *:before, 223 | *:after, 224 | p:first-letter, 225 | div:first-letter, 226 | blockquote:first-letter, 227 | li:first-letter, 228 | p:first-line, 229 | div:first-line, 230 | blockquote:first-line, 231 | li:first-line { 232 | background: transparent !important; 233 | color: #000 !important; /* Black prints faster: 234 | http://www.sanbeiji.com/archives/953 */ 235 | box-shadow: none !important; 236 | text-shadow: none !important; 237 | } 238 | 239 | a, 240 | a:visited { 241 | text-decoration: underline; 242 | } 243 | 244 | a[href]:after { 245 | content: " (" attr(href) ")"; 246 | } 247 | 248 | abbr[title]:after { 249 | content: " (" attr(title) ")"; 250 | } 251 | 252 | /* 253 | * Don't show links that are fragment identifiers, 254 | * or use the `javascript:` pseudo protocol 255 | */ 256 | 257 | a[href^="#"]:after, 258 | a[href^="javascript:"]:after { 259 | content: ""; 260 | } 261 | 262 | pre { 263 | white-space: pre-wrap !important; 264 | } 265 | pre, 266 | blockquote { 267 | border: 1px solid #999; 268 | page-break-inside: avoid; 269 | } 270 | 271 | /* 272 | * Printing Tables: 273 | * http://css-discuss.incutio.com/wiki/Printing_Tables 274 | */ 275 | 276 | thead { 277 | display: table-header-group; 278 | } 279 | 280 | tr, 281 | img { 282 | page-break-inside: avoid; 283 | } 284 | 285 | p, 286 | h2, 287 | h3 { 288 | orphans: 3; 289 | widows: 3; 290 | } 291 | 292 | h2, 293 | h3 { 294 | page-break-after: avoid; 295 | } 296 | } 297 | -------------------------------------------------------------------------------- /css/main.scss: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | /*! HTML5 Boilerplate v5.3.0 | MIT License | https://html5boilerplate.com/ */ 5 | 6 | /* 7 | * What follows is the result of much research on cross-browser styling. 8 | * Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal, 9 | * Kroc Camen, and the H5BP dev community and team. 10 | */ 11 | 12 | /* ========================================================================== 13 | Base styles: opinionated defaults 14 | ========================================================================== */ 15 | 16 | html { 17 | color: #222; 18 | font-size: 1em; 19 | line-height: 1.4; 20 | } 21 | 22 | /* 23 | * Remove text-shadow in selection highlight: 24 | * https://twitter.com/miketaylr/status/12228805301 25 | * 26 | * These selection rule sets have to be separate. 27 | * Customize the background color to match your design. 28 | */ 29 | 30 | ::-moz-selection { 31 | background: #b3d4fc; 32 | text-shadow: none; 33 | } 34 | 35 | ::selection { 36 | background: #b3d4fc; 37 | text-shadow: none; 38 | } 39 | 40 | /* 41 | * A better looking default horizontal rule 42 | */ 43 | 44 | hr { 45 | display: block; 46 | height: 1px; 47 | border: 0; 48 | border-top: 1.5px solid #ccc; 49 | margin: 1em 0; 50 | padding: 0; 51 | } 52 | 53 | /* 54 | * Remove the gap between audio, canvas, iframes, 55 | * images, videos and the bottom of their containers: 56 | * https://github.com/h5bp/html5-boilerplate/issues/440 57 | */ 58 | 59 | audio, 60 | canvas, 61 | iframe, 62 | img, 63 | svg, 64 | video { 65 | vertical-align: middle; 66 | } 67 | 68 | /* 69 | * Remove default fieldset styles. 70 | */ 71 | 72 | fieldset { 73 | border: 0; 74 | margin: 0; 75 | padding: 0; 76 | } 77 | 78 | /* 79 | * Allow only vertical resizing of textareas. 80 | */ 81 | 82 | textarea { 83 | resize: vertical; 84 | } 85 | 86 | /* ========================================================================== 87 | Browser Upgrade Prompt 88 | ========================================================================== */ 89 | 90 | .browserupgrade { 91 | margin: 0.2em 0; 92 | background: #ccc; 93 | color: #000; 94 | padding: 0.2em 0; 95 | } 96 | 97 | /* ========================================================================== 98 | Author's custom styles 99 | ========================================================================== */ 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | @import "styles.scss"; 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | /* ========================================================================== 118 | Helper classes 119 | ========================================================================== */ 120 | 121 | /* 122 | * Hide visually and from screen readers 123 | */ 124 | 125 | .hidden { 126 | display: none !important; 127 | } 128 | 129 | /* 130 | * Hide only visually, but have it available for screen readers: 131 | * https://snook.ca/archives/html_and_css/hiding-content-for-accessibility 132 | * 133 | * 1. For long content, line feeds are not interpreted as spaces and small width 134 | * causes content to wrap 1 word per line: 135 | * https://medium.com/@jessebeach/beware-smushed-off-screen-accessible-text-5952a4c2cbfe 136 | */ 137 | 138 | .visuallyhidden { 139 | border: 0; 140 | clip: rect(0 0 0 0); 141 | height: 1px; 142 | margin: -1px; 143 | overflow: hidden; 144 | padding: 0; 145 | position: absolute; 146 | width: 1px; 147 | white-space: nowrap; /* 1 */ 148 | } 149 | 150 | /* 151 | * Extends the .visuallyhidden class to allow the element 152 | * to be focusable when navigated to via the keyboard: 153 | * https://www.drupal.org/node/897638 154 | */ 155 | 156 | .visuallyhidden.focusable:active, 157 | .visuallyhidden.focusable:focus { 158 | clip: auto; 159 | height: auto; 160 | margin: 0; 161 | overflow: visible; 162 | position: static; 163 | width: auto; 164 | white-space: inherit; 165 | } 166 | 167 | /* 168 | * Hide visually and from screen readers, but maintain layout 169 | */ 170 | 171 | .invisible { 172 | visibility: hidden; 173 | } 174 | 175 | /* 176 | * Clearfix: contain floats 177 | * 178 | * For modern browsers 179 | * 1. The space content is one way to avoid an Opera bug when the 180 | * `contenteditable` attribute is included anywhere else in the document. 181 | * Otherwise it causes space to appear at the top and bottom of elements 182 | * that receive the `clearfix` class. 183 | * 2. The use of `table` rather than `block` is only necessary if using 184 | * `:before` to contain the top-margins of child elements. 185 | */ 186 | 187 | .clearfix:before, 188 | .clearfix:after { 189 | content: " "; /* 1 */ 190 | display: table; /* 2 */ 191 | } 192 | 193 | .clearfix:after { 194 | clear: both; 195 | } 196 | 197 | /* ========================================================================== 198 | EXAMPLE Media Queries for Responsive Design. 199 | These examples override the primary ('mobile first') styles. 200 | Modify as content requires. 201 | ========================================================================== */ 202 | 203 | @media only screen and (min-width: 35em) { 204 | /* Style adjustments for viewports that meet the condition */ 205 | } 206 | 207 | @media print, 208 | (-webkit-min-device-pixel-ratio: 1.25), 209 | (min-resolution: 1.25dppx), 210 | (min-resolution: 120dpi) { 211 | /* Style adjustments for high resolution devices */ 212 | } 213 | 214 | /* ========================================================================== 215 | Print styles. 216 | Inlined to avoid the additional HTTP request: 217 | http://www.phpied.com/delay-loading-your-print-css/ 218 | ========================================================================== */ 219 | 220 | @media print { 221 | *, 222 | *:before, 223 | *:after, 224 | p:first-letter, 225 | div:first-letter, 226 | blockquote:first-letter, 227 | li:first-letter, 228 | p:first-line, 229 | div:first-line, 230 | blockquote:first-line, 231 | li:first-line { 232 | background: transparent !important; 233 | color: #000 !important; /* Black prints faster: 234 | http://www.sanbeiji.com/archives/953 */ 235 | box-shadow: none !important; 236 | text-shadow: none !important; 237 | } 238 | 239 | a, 240 | a:visited { 241 | text-decoration: underline; 242 | } 243 | 244 | a[href]:after { 245 | content: " (" attr(href) ")"; 246 | } 247 | 248 | abbr[title]:after { 249 | content: " (" attr(title) ")"; 250 | } 251 | 252 | /* 253 | * Don't show links that are fragment identifiers, 254 | * or use the `javascript:` pseudo protocol 255 | */ 256 | 257 | a[href^="#"]:after, 258 | a[href^="javascript:"]:after { 259 | content: ""; 260 | } 261 | 262 | pre { 263 | white-space: pre-wrap !important; 264 | } 265 | pre, 266 | blockquote { 267 | border: 1px solid #999; 268 | page-break-inside: avoid; 269 | } 270 | 271 | /* 272 | * Printing Tables: 273 | * http://css-discuss.incutio.com/wiki/Printing_Tables 274 | */ 275 | 276 | thead { 277 | display: table-header-group; 278 | } 279 | 280 | tr, 281 | img { 282 | page-break-inside: avoid; 283 | } 284 | 285 | p, 286 | h2, 287 | h3 { 288 | orphans: 3; 289 | widows: 3; 290 | } 291 | 292 | h2, 293 | h3 { 294 | page-break-after: avoid; 295 | } 296 | } 297 | -------------------------------------------------------------------------------- /css/noob.scss: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | /*! HTML5 Boilerplate v5.3.0 | MIT License | https://html5boilerplate.com/ */ 5 | 6 | /* 7 | * What follows is the result of much research on cross-browser styling. 8 | * Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal, 9 | * Kroc Camen, and the H5BP dev community and team. 10 | */ 11 | 12 | /* ========================================================================== 13 | Base styles: opinionated defaults 14 | ========================================================================== */ 15 | 16 | html { 17 | color: #222; 18 | font-size: 1em; 19 | line-height: 1.4; 20 | } 21 | 22 | /* 23 | * Remove text-shadow in selection highlight: 24 | * https://twitter.com/miketaylr/status/12228805301 25 | * 26 | * These selection rule sets have to be separate. 27 | * Customize the background color to match your design. 28 | */ 29 | 30 | ::-moz-selection { 31 | background: #b3d4fc; 32 | text-shadow: none; 33 | } 34 | 35 | ::selection { 36 | background: #b3d4fc; 37 | text-shadow: none; 38 | } 39 | 40 | /* 41 | * A better looking default horizontal rule 42 | */ 43 | 44 | hr { 45 | display: block; 46 | height: 1px; 47 | border: 0; 48 | border-top: 1.5px solid #ccc; 49 | margin: 1em 0; 50 | padding: 0; 51 | } 52 | 53 | /* 54 | * Remove the gap between audio, canvas, iframes, 55 | * images, videos and the bottom of their containers: 56 | * https://github.com/h5bp/html5-boilerplate/issues/440 57 | */ 58 | 59 | audio, 60 | canvas, 61 | iframe, 62 | img, 63 | svg, 64 | video { 65 | vertical-align: middle; 66 | } 67 | 68 | /* 69 | * Remove default fieldset styles. 70 | */ 71 | 72 | fieldset { 73 | border: 0; 74 | margin: 0; 75 | padding: 0; 76 | } 77 | 78 | /* 79 | * Allow only vertical resizing of textareas. 80 | */ 81 | 82 | textarea { 83 | resize: vertical; 84 | } 85 | 86 | /* ========================================================================== 87 | Browser Upgrade Prompt 88 | ========================================================================== */ 89 | 90 | .browserupgrade { 91 | margin: 0.2em 0; 92 | background: #ccc; 93 | color: #000; 94 | padding: 0.2em 0; 95 | } 96 | 97 | /* ========================================================================== 98 | Author's custom styles 99 | ========================================================================== */ 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | @import "styles-noob.scss"; 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | /* ========================================================================== 118 | Helper classes 119 | ========================================================================== */ 120 | 121 | /* 122 | * Hide visually and from screen readers 123 | */ 124 | 125 | .hidden { 126 | display: none !important; 127 | } 128 | 129 | /* 130 | * Hide only visually, but have it available for screen readers: 131 | * https://snook.ca/archives/html_and_css/hiding-content-for-accessibility 132 | * 133 | * 1. For long content, line feeds are not interpreted as spaces and small width 134 | * causes content to wrap 1 word per line: 135 | * https://medium.com/@jessebeach/beware-smushed-off-screen-accessible-text-5952a4c2cbfe 136 | */ 137 | 138 | .visuallyhidden { 139 | border: 0; 140 | clip: rect(0 0 0 0); 141 | height: 1px; 142 | margin: -1px; 143 | overflow: hidden; 144 | padding: 0; 145 | position: absolute; 146 | width: 1px; 147 | white-space: nowrap; /* 1 */ 148 | } 149 | 150 | /* 151 | * Extends the .visuallyhidden class to allow the element 152 | * to be focusable when navigated to via the keyboard: 153 | * https://www.drupal.org/node/897638 154 | */ 155 | 156 | .visuallyhidden.focusable:active, 157 | .visuallyhidden.focusable:focus { 158 | clip: auto; 159 | height: auto; 160 | margin: 0; 161 | overflow: visible; 162 | position: static; 163 | width: auto; 164 | white-space: inherit; 165 | } 166 | 167 | /* 168 | * Hide visually and from screen readers, but maintain layout 169 | */ 170 | 171 | .invisible { 172 | visibility: hidden; 173 | } 174 | 175 | /* 176 | * Clearfix: contain floats 177 | * 178 | * For modern browsers 179 | * 1. The space content is one way to avoid an Opera bug when the 180 | * `contenteditable` attribute is included anywhere else in the document. 181 | * Otherwise it causes space to appear at the top and bottom of elements 182 | * that receive the `clearfix` class. 183 | * 2. The use of `table` rather than `block` is only necessary if using 184 | * `:before` to contain the top-margins of child elements. 185 | */ 186 | 187 | .clearfix:before, 188 | .clearfix:after { 189 | content: " "; /* 1 */ 190 | display: table; /* 2 */ 191 | } 192 | 193 | .clearfix:after { 194 | clear: both; 195 | } 196 | 197 | /* ========================================================================== 198 | EXAMPLE Media Queries for Responsive Design. 199 | These examples override the primary ('mobile first') styles. 200 | Modify as content requires. 201 | ========================================================================== */ 202 | 203 | @media only screen and (min-width: 35em) { 204 | /* Style adjustments for viewports that meet the condition */ 205 | } 206 | 207 | @media print, 208 | (-webkit-min-device-pixel-ratio: 1.25), 209 | (min-resolution: 1.25dppx), 210 | (min-resolution: 120dpi) { 211 | /* Style adjustments for high resolution devices */ 212 | } 213 | 214 | /* ========================================================================== 215 | Print styles. 216 | Inlined to avoid the additional HTTP request: 217 | http://www.phpied.com/delay-loading-your-print-css/ 218 | ========================================================================== */ 219 | 220 | @media print { 221 | *, 222 | *:before, 223 | *:after, 224 | p:first-letter, 225 | div:first-letter, 226 | blockquote:first-letter, 227 | li:first-letter, 228 | p:first-line, 229 | div:first-line, 230 | blockquote:first-line, 231 | li:first-line { 232 | background: transparent !important; 233 | color: #000 !important; /* Black prints faster: 234 | http://www.sanbeiji.com/archives/953 */ 235 | box-shadow: none !important; 236 | text-shadow: none !important; 237 | } 238 | 239 | a, 240 | a:visited { 241 | text-decoration: underline; 242 | } 243 | 244 | a[href]:after { 245 | content: " (" attr(href) ")"; 246 | } 247 | 248 | abbr[title]:after { 249 | content: " (" attr(title) ")"; 250 | } 251 | 252 | /* 253 | * Don't show links that are fragment identifiers, 254 | * or use the `javascript:` pseudo protocol 255 | */ 256 | 257 | a[href^="#"]:after, 258 | a[href^="javascript:"]:after { 259 | content: ""; 260 | } 261 | 262 | pre { 263 | white-space: pre-wrap !important; 264 | } 265 | pre, 266 | blockquote { 267 | border: 1px solid #999; 268 | page-break-inside: avoid; 269 | } 270 | 271 | /* 272 | * Printing Tables: 273 | * http://css-discuss.incutio.com/wiki/Printing_Tables 274 | */ 275 | 276 | thead { 277 | display: table-header-group; 278 | } 279 | 280 | tr, 281 | img { 282 | page-break-inside: avoid; 283 | } 284 | 285 | p, 286 | h2, 287 | h3 { 288 | orphans: 3; 289 | widows: 3; 290 | } 291 | 292 | h2, 293 | h3 { 294 | page-break-after: avoid; 295 | } 296 | } 297 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrypTools/learn/da480816ba59f93dac637aea68674aafa236cb35/favicon.ico -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CrypTools/learn/da480816ba59f93dac637aea68674aafa236cb35/icon.png -------------------------------------------------------------------------------- /img/logo-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /img/logo-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: html 3 | title: CrypTools - Learn 4 | description: The best platform to learn cryptography 5 | --- 6 | 7 |
8 |
9 |

Welcome on our platform to learn cryptography

10 |

11 | Cryptography is the art of writing and solving problems in order to prevent third parties or the public from reading private messages. And as any art, it can be taught. This was our mission by creating this platform. You'll have some challenges to complete, 12 | the first ones are easy, but don't worry, it will get much harder after some point. 13 |

14 | - CrypTools 15 |
16 | 17 | Get Started 18 | 19 |

20 |
21 |
22 |

Levels:

23 |

You don't know code?

24 |
25 |
26 |
27 |
28 | {% for i in site.data.noob %} 29 | 30 | 31 |

#{{ forloop.index }}

32 |

{{i.fancy}}

33 |
{% endfor %} 34 |
35 |
36 |
37 | More expand_more 38 |
39 |
40 |

Know JavaScript?

41 |
42 |
43 |
44 |
45 | {% for i in site.data.challenges %} 46 | 47 | 48 |

#{{ forloop.index }}

49 |

{{i.fancy}}

50 |
{% endfor %} 51 |
52 |
53 |
54 | More expand_more 55 |
56 |
57 |
58 | computer 59 |

60 | This section is not optimized for mobile devices. Please try on a computer. Otherwise it will be glitchy ! 61 |

62 |
63 |
64 |
65 | -------------------------------------------------------------------------------- /js/challenges.js: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | class Done { 5 | constructor() { 6 | if (!localStorage.getItem("CrypTools Learn Done")) { 7 | this.init() 8 | } 9 | } 10 | init() { 11 | localStorage.setItem("CrypTools Learn Done", JSON.stringify({ 12 | noob: [], 13 | js: [] 14 | })) 15 | } 16 | get() { 17 | const str = localStorage.getItem("CrypTools Learn Done") 18 | return JSON.parse(str); 19 | } 20 | addNoob() { 21 | let json = this.get() 22 | json.noob.push(...arguments) 23 | localStorage.setItem("CrypTools Learn Done", JSON.stringify(json)) 24 | 25 | } 26 | addJS() { 27 | let json = this.get() 28 | json.js.push(...arguments) 29 | localStorage.setItem("CrypTools Learn Done", JSON.stringify(json)) 30 | } 31 | isDone(id, name) { 32 | return this.get()[id].includes(name); 33 | } 34 | } 35 | 36 | const done = new Done() 37 | 38 | const challengesData = {{site.data.challenges | jsonify}} 39 | 40 | let challenges = {} 41 | 42 | for (let i of challengesData) { 43 | challenges[i.name] = i 44 | } 45 | class Router { 46 | constructor() { 47 | let hash; 48 | if (localStorage.getItem("CrypToolsLearn")) { 49 | hash = localStorage.getItem("CrypToolsLearn").substring(1); 50 | } else { 51 | hash = window.location.hash.substring(1); 52 | } 53 | if (hash == "") { 54 | this.page = challenges["emojigraphy"] /* level 1 */ 55 | } else { 56 | this.page = challenges[hash] 57 | } 58 | this.load() 59 | } 60 | load() { 61 | let question = document.querySelector(".questions") 62 | const converter = new showdown.Converter({extensions: ['github']}) 63 | fetch(`../challenges/${this.page.question}`).then(data => data.text()).then(text => { 64 | question.innerHTML = converter.makeHtml(text); 65 | }) 66 | 67 | editor.insert(this.page.init) 68 | } 69 | } 70 | 71 | const router = new Router() 72 | 73 | class Test { 74 | constructor(data) { 75 | this.data = data; 76 | 77 | const runEl = document.getElementById("run") 78 | this.addEvents(runEl) 79 | } 80 | 81 | addEvents(el) { 82 | el.addEventListener("click", e => { 83 | this.test() 84 | }) 85 | } 86 | test() { 87 | console.command("run tests") 88 | let out = ""; 89 | let before = ""; 90 | for (let i = 0; i < this.data.tests.length; i++) { 91 | const current = this.data.tests[i] 92 | const command = eval("`" + this.data.testCommand + "`") 93 | const result = editor.run(command) 94 | const expected = current.expected; 95 | before += `${current.word} -> ${result}
` 96 | if (result == expected) { 97 | out = out === false ? false : true 98 | } else { 99 | out = false 100 | } 101 | } 102 | if (out === true) { 103 | console.log("Congratulations 🎉! The code you've written passed the tests.") 104 | done.addJS(this.data.name) 105 | document.querySelector(".done").style.display = "flex" 106 | setTimeout(() => { 107 | document.querySelector(".done").classList.add("active") 108 | }, 1000) 109 | } else { 110 | console.log(`${before}Argh 😤! You've failed! Try again...`) 111 | } 112 | } 113 | } 114 | 115 | const test = new Test(router.page) 116 | -------------------------------------------------------------------------------- /js/console.js: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | class Console { 4 | constructor(el) { 5 | this.el = el; 6 | this.clear() 7 | } 8 | clear() { 9 | this.el.innerHTML = "$" 10 | } 11 | log(text) { 12 | this.el.innerHTML += `
${text}
$` 13 | } 14 | warn() { 15 | return null; 16 | } 17 | command(text) { 18 | this.el.innerHTML += ` ${text}` 19 | } 20 | } 21 | 22 | const outEl = document.querySelector(".console") 23 | window.console = new Console(outEl) 24 | -------------------------------------------------------------------------------- /js/editor.js: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | class Editor { 4 | constructor(el) { 5 | this.ed = el; 6 | } 7 | value() { 8 | return this.ed.getValue() /* the code written in the editor */ 9 | } 10 | insert(text) { 11 | const doc = this.ed.getDoc(); 12 | const cursor = doc.getCursor(); 13 | doc.replaceRange(text, cursor); 14 | } 15 | run(command) { 16 | const val = this.value() 17 | const f = new Function(`${val}\n${command}`) /* safe eval() */ 18 | let out; 19 | try { 20 | out = f() 21 | } catch (e) { 22 | out = e 23 | } finally { 24 | return out; 25 | } 26 | } 27 | } 28 | 29 | const editorEl = CodeMirror(document.querySelector(".editor"), { 30 | mode: "javascript", 31 | theme: "monokai", 32 | lineNumbers: true, 33 | autoCloseTags: true, 34 | autoCloseBrackets: true, 35 | matchBrackets: true, 36 | indentUnit: 4, 37 | indentWithTabs: true, 38 | closeBrackets: true, 39 | viewportMargin: Infinity, 40 | extraKeys: { 41 | "Shift-Enter": function(cm) { 42 | cm.setOption("fullScreen", !cm.getOption("fullScreen")); 43 | }, 44 | "Esc": function(cm) { 45 | if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false); 46 | } 47 | } 48 | }); 49 | 50 | const editor = new Editor(editorEl) 51 | -------------------------------------------------------------------------------- /js/landing.js: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | function detectmob() { 4 | if (window.innerWidth < 1024 && window.innerHeight < 800) { 5 | return true; 6 | } else { 7 | return false; 8 | } 9 | } 10 | if (detectmob()) { 11 | document.querySelector(".beoncomp").style.display = "flex"; 12 | document.querySelectorAll(".row")[1].style.display = "none" 13 | document.querySelectorAll(".expand")[1].style.display = "none" 14 | } 15 | 16 | 17 | class Menu { 18 | constructor() { 19 | this.state = false 20 | this.toggle = document.getElementById('menu-toggle') 21 | this.links = document.querySelectorAll('nav .menu-container a') 22 | this.container = document.querySelector('nav .menu-container') 23 | this.open = this.open.bind(this) 24 | this.close = this.close.bind(this) 25 | this.swap = this.swap.bind(this) 26 | 27 | this._addEventListeners() 28 | } 29 | 30 | _addEventListeners() { 31 | this.links.forEach(l => l.addEventListener('click', this.close)) 32 | this.toggle.addEventListener('click', this.swap) 33 | } 34 | 35 | open() { 36 | this.toggle.classList.add('cross') 37 | this.container.style.display = "flex" 38 | this.state = true 39 | } 40 | 41 | close() { 42 | this.toggle.classList.remove('cross') 43 | this.container.style.display = "none" 44 | this.state = false 45 | } 46 | 47 | swap() { 48 | if (this.state == true) this.close() 49 | else if (this.state == false) this.open() 50 | } 51 | } 52 | 53 | var m = new Menu() 54 | 55 | class Expand { 56 | constructor() { 57 | this.state = false; 58 | this.toggles = document.querySelectorAll(".expand > .more"); 59 | 60 | const noob = document.querySelectorAll(".noob > *") 61 | const js = document.querySelectorAll(".js > *") 62 | let noobItems = []; 63 | for (let i = 0; i < noob.length - 8; i++) { 64 | noobItems.push(noob[i + 8]) 65 | } 66 | 67 | let jsItems = []; 68 | for (let i = 0; i < js.length - 8; i++) { 69 | jsItems.push(js[i + 8]) 70 | } 71 | this.sections = [noobItems, jsItems] 72 | 73 | this.hide({ id: 0 }); 74 | this.hide({ id: 1 }); 75 | 76 | this._addEventListeners(); 77 | } 78 | _addEventListeners() { 79 | for (let i = 0; i < this.toggles.length; i++) { 80 | this.toggles[i].addEventListener("click", ev => e.toggle(ev.currentTarget) ) 81 | } 82 | } 83 | hide(el) { 84 | this.sections[el.id].forEach(el => { 85 | el.style.display = "none"; 86 | }) 87 | el.innerHTML = `More expand_more` 88 | 89 | this.state = false 90 | } 91 | show(el) { 92 | this.sections[el.id].forEach(el => { 93 | el.style.display = "block"; 94 | }) 95 | el.innerHTML = `Less expand_less` 96 | this.state = true; 97 | } 98 | toggle(el) { 99 | if (this.state == true) this.hide(el) 100 | else if (this.state == false) this.show(el) 101 | } 102 | } 103 | 104 | const e = new Expand() 105 | 106 | 107 | class Done { 108 | constructor() { 109 | if (!localStorage.getItem("CrypTools Learn Done")) { 110 | this.init() 111 | } 112 | } 113 | init() { 114 | localStorage.setItem("CrypTools Learn Done", JSON.stringify({ 115 | noob: [], 116 | js: [] 117 | })) 118 | } 119 | get() { 120 | const str = localStorage.getItem("CrypTools Learn Done") 121 | return JSON.parse(str); 122 | } 123 | addNoob() { 124 | let json = this.get() 125 | json.noob.push(...arguments) 126 | localStorage.setItem("CrypTools Learn Done", JSON.stringify(json)) 127 | 128 | } 129 | addJS() { 130 | let json = this.get() 131 | json.js.push(...arguments) 132 | localStorage.setItem("CrypTools Learn Done", JSON.stringify(json)) 133 | } 134 | isDone(id, name) { 135 | return this.get()[id].includes(name); 136 | } 137 | } 138 | 139 | const done = new Done() 140 | 141 | 142 | document.querySelectorAll(".row > a").forEach(el => { 143 | el.addEventListener("click", e => { 144 | e.preventDefault(); 145 | localStorage.setItem("CrypToolsLearn", el.hash) 146 | window.open(el.href, "_self") 147 | }) 148 | }) 149 | 150 | /* Done */ 151 | document.querySelectorAll(".js > a").forEach(el => { 152 | if (done.isDone("js", el.id)) { 153 | el.querySelector(".done").style.opacity = 1; 154 | } 155 | }) 156 | document.querySelectorAll(".noob > a").forEach(el => { 157 | if (done.isDone("noob", el.id)) { 158 | el.querySelector(".done").style.opacity = 1; 159 | } 160 | const width = (done.get().noob.length / document.querySelectorAll(".noob > a").length) * 100 161 | document.querySelectorAll(".progress")[0].style.width = `calc(${width}% - 20px)` 162 | }) 163 | 164 | const widthJ = (done.get().js.length / document.querySelectorAll(".js > a").length) * 100 165 | document.querySelectorAll(".progress")[1].style.width = `calc(${widthJ}% - 20px)` 166 | 167 | const widthN = (done.get().noob.length / document.querySelectorAll(".noob > a").length) * 100 168 | document.querySelectorAll(".progress")[0].style.width = `calc(${widthN}% - 20px)` 169 | -------------------------------------------------------------------------------- /js/noob.js: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | class Menu { 4 | constructor() { 5 | this.state = false 6 | this.toggle = document.getElementById('menu-toggle') 7 | this.links = document.querySelectorAll('nav .menu-container a') 8 | this.container = document.querySelector('nav .menu-container') 9 | this.open = this.open.bind(this) 10 | this.close = this.close.bind(this) 11 | this.swap = this.swap.bind(this) 12 | 13 | this._addEventListeners() 14 | } 15 | 16 | _addEventListeners() { 17 | this.links.forEach(l => l.addEventListener('click', this.close)) 18 | this.toggle.addEventListener('click', this.swap) 19 | } 20 | 21 | open() { 22 | this.toggle.classList.add('cross') 23 | this.container.style.display = "flex" 24 | this.state = true 25 | } 26 | 27 | close() { 28 | this.toggle.classList.remove('cross') 29 | this.container.style.display = "none" 30 | this.state = false 31 | } 32 | 33 | swap() { 34 | if (this.state == true) this.close() 35 | else if (this.state == false) this.open() 36 | } 37 | } 38 | 39 | var m = new Menu() 40 | 41 | class Done { 42 | constructor() { 43 | if (!localStorage.getItem("CrypTools Learn Done")) { 44 | this.init() 45 | } 46 | } 47 | init() { 48 | localStorage.setItem("CrypTools Learn Done", JSON.stringify({ 49 | noob: [], 50 | js: [] 51 | })) 52 | } 53 | get() { 54 | const str = localStorage.getItem("CrypTools Learn Done") 55 | return JSON.parse(str); 56 | } 57 | addNoob() { 58 | let json = this.get() 59 | json.noob.push(...arguments) 60 | localStorage.setItem("CrypTools Learn Done", JSON.stringify(json)) 61 | 62 | } 63 | addJS() { 64 | let json = this.get() 65 | json.js.push(...arguments) 66 | localStorage.setItem("CrypTools Learn Done", JSON.stringify(json)) 67 | } 68 | isDone(id, name) { 69 | return this.get()[id].includes(name); 70 | } 71 | } 72 | 73 | const done = new Done() 74 | 75 | 76 | const challengesData = {{site.data.noob | jsonify}} 77 | 78 | let challenges = {} 79 | 80 | for (let i of challengesData) { 81 | challenges[i.name] = i 82 | } 83 | class Router { 84 | constructor() { 85 | let hash; 86 | if (localStorage.getItem("CrypToolsLearn")) { 87 | hash = localStorage.getItem("CrypToolsLearn").substring(1); 88 | } else { 89 | hash = window.location.hash.substring(1); 90 | } 91 | 92 | if (hash == "") { 93 | this.page = challenges["emojigraphy"] /* level 1 */ 94 | } else { 95 | this.page = challenges[hash] 96 | } 97 | this.load() 98 | } 99 | load() { 100 | let question = document.querySelector(".questions") 101 | const converter = new showdown.Converter({extensions: ['github']}) 102 | fetch(`../noob_questions/${this.page.question}`).then(data => data.text()).then(text => { 103 | question.innerHTML = converter.makeHtml(text); 104 | }) 105 | } 106 | } 107 | 108 | const router = new Router() 109 | 110 | class Test { 111 | constructor(data) { 112 | this.data = data; 113 | 114 | const runEl = document.querySelector("form") 115 | const checkEl = document.getElementById("run") 116 | this.addEvents(runEl, checkEl) 117 | } 118 | 119 | addEvents(el1, el2) { 120 | el1.addEventListener("submit", e => { 121 | e.preventDefault() 122 | this.test() 123 | }) 124 | el2.addEventListener("click", e => { 125 | this.test() 126 | }) 127 | } 128 | test() { 129 | const ans = document.querySelector(".ans").value 130 | let out = document.querySelector(".out") 131 | if (this.data.answer == ans) { 132 | out.style.color = "green" 133 | out.innerHTML = "Congratulations 🎉! Your answer is correct ✅" 134 | done.addNoob(this.data.name) 135 | document.querySelector(".done").style.display = "flex" 136 | setTimeout(() => { 137 | document.querySelector(".done").classList.add("active") 138 | }, 1000) 139 | } else { 140 | out.style.color = "red" 141 | out.innerHTML = "Oupps 🤭! Try again. ❎" 142 | } 143 | } 144 | } 145 | 146 | const test = new Test(router.page) 147 | -------------------------------------------------------------------------------- /js/shortcuts.js: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | Mousetrap.bindGlobal(['command+enter', 'ctrl+enter'], () => { 5 | test.test() 6 | return false; 7 | }) 8 | 9 | Mousetrap.bindGlobal(['command+shift+c', 'ctrl+shift+c'], () => { 10 | console.clear() 11 | return false; 12 | }) 13 | -------------------------------------------------------------------------------- /levels.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: challenges 3 | title: CrypTools - Learn 4 | description: The best platform to learn cryptography 5 | --- 6 |
7 | 8 |
9 |
10 | 11 |
12 |
13 |

Well done! Choose another level.

14 | 19 |
20 | -------------------------------------------------------------------------------- /noob.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: noob 3 | title: CrypTools - Learn 4 | description: The best platform to learn cryptography online 5 | --- 6 |
7 |
8 |

Answer:

9 |
10 | 11 |
12 |
13 |
14 |
15 |

Well done! Choose another level, you're doing good !

16 | 21 |
22 | -------------------------------------------------------------------------------- /noob_questions/b64.md: -------------------------------------------------------------------------------- 1 | # Base64 2 | 3 | # Encoding 4 | 5 | Let's try to encrypt a piece text, for example `"Hello World!"` 6 | 7 | Now, we'll take it's ASCII representation: 8 | ``` 9 | 72 101 108 108 111 10 119 111 114 108 100 33 10 | ``` 11 | We'll convert that to binary: 12 | ``` 13 | 01001000 01100101 01101100 01101100 01101111 00100000 01010111 01101111 01110010 01101100 01100100 00100001 14 | ``` 15 | After that, we'll split this 8 bit stream to a 6 bit stream: 16 | ``` 17 | 010010 000110 010101 101100 011011 000110 111100 100000 010101 110110 111101 110010 011011 000110 010000 100001 18 | ``` 19 | > If your string cannot split up in a 6 bit stream, add padding '0' at the end, we'll replace them by '=' 20 | 21 | Now, we'll convert this 6 bit stream to numbers in base 10: 22 | ``` 23 | 18 6 21 44 27 6 60 32 21 54 61 50 27 6 16 33 24 | ``` 25 | And using the Base64 table: 26 | ``` 27 | ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ 28 | ``` 29 | We have: 30 | ``` 31 | SGVsbG8gV29ybGQh 32 | ``` 33 | 34 | # What you need to do: 35 | - What is the base64 of `CrypTools`? 36 | -------------------------------------------------------------------------------- /noob_questions/binascii.md: -------------------------------------------------------------------------------- 1 | # Binascii 2 | 3 | # How it works? 4 | 5 | ## Encoding 6 | 7 | ASCII stands for **A**merican **S**tandard **C**ode for **I**nformation **I**nterchange. 8 | 9 | It's a simple way of encoding characters to numbers. 10 | 11 | We can express these characters as hexadecimal (base 16) numbers using this table: 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 |
0NUL16DLE32SP48064@80P96`112p
1SOH17DC133!49165A81Q97a113q
2STX18DC234"50266B82R98b114r
3ETX19DC335#51367C83S99c115s
4EOT20DC436$52468D84T100d116t
5ENQ21NAK37%53569E85U101e117u
6ACK22SYN38&54670F86V102f118v
7BEL23ETB39'55771G87W103g119w
8BS24CAN40(56872H88X104h120x
9HT25EM41)57973I89Y105i121y
10LF26SUB42*58:74J90Z106j122z
11VT27ESC43+59;75K91[107k123{
12FF28FS44,60<76L92\108l124|
13CR29GS45-61=77M93]109m125}
14SO30RS46.62>78N94^110n126~
15SI31US47/63?79O95_111o127DEL
305 | 306 | So we know that `A` correspond to `65` in decimal (base 10). 307 | 308 | ### Convert decimal to Binary 309 | - Take any number `N`. 310 | 311 | - Keep dividing `N` by `2` and write down the remainder (`0` or `1`) 312 | - Reverse the list of remainder 313 | 314 | - Add padding `0`s at the beginning, so for example if we have `101` and we want an 8-bit stream, we output `00000101`. 315 | 316 | # What you need to do? 317 | Write `code` using the Binascii cipher. 318 | 319 | ## Requirements 320 | - Each binary numbers should be expressed in 8 bits 321 | - Separate each characters by a space. 322 | -------------------------------------------------------------------------------- /noob_questions/bitshift.md: -------------------------------------------------------------------------------- 1 | # BitShift Cipher 2 | > ⚠️ We strongly recommend you to know how to program in at least one programming language. 3 | 4 | ## How it works 5 | 6 | ### Encoding 7 | 8 | The Bitshift Cipher works by (as the name suggests) shifting over the bits of the text's ASCII. We do this using the bitwise `<<` operator, which is used to shift the bits a certain number of places. 9 | 10 | To encode the text, we loop through the text, and for each character `x`, we loop through the key array, and for each key character `i`: 11 | 12 | ```py 13 | x = x + 1 << i % 8 14 | ``` 15 | 16 | We limit the maximum shift using modulo to avoid having a bit shifted by hundreds of places 17 | 18 | Example: 19 | 20 | Let's imagine we are currently working on the character `A`, and that our key is `YO` 21 | 22 | ```Python 23 | A = 0b01000001 # ASCII for A 24 | 0b01000010 # plus 1 25 | 0b010000100 # Y is 89, 89 % 8 = 1, so we add 1 zero. 26 | # next charachter in key: O 27 | 0b010000101 # plus 1 28 | 0b0100001010000000 # O is 79, 79 % 8 = 7, so we add 7 zeros. 29 | ``` 30 | 31 | After each character is encoded, we add it to an array and reverse the key to make frequency analysis harder. 32 | 33 | Let's say the next character in our string is `B`, our key now is `OY`, as it was reversed. 34 | 35 | ```Python 36 | B = 0b01000010 # ASCII for B 37 | 0b01000011 # plus 1 38 | 0b010000110000000 # O is 79, 79 % 8 = 7, so we add 7 zeros. 39 | # next character in key: Y 40 | 0b010000110000001 # plus 1 41 | 0b0100001100000010 # Y is 89, 89 % 8 = 1, so we add 1 zero. 42 | ``` 43 | 44 | Our array now looks like this: `[0b0100001010000000, 0b0100001100000010]`, or in decimal: `[17024, 17154]`. 45 | 46 | Finally, we encode the array in base64 to get the final encrypted string: `'WzE3MDI0LCAxNzE1NF0='`. 47 | 48 | # What you need to do 49 | - What would be, in a decimal array (basically you don't need to Base64 encode your output) the encrypted result of `CrypTools` with the key `learn`. 50 | 51 | ## Requirements 52 | - Your array should begin with `[` and end with `]`. 53 | - No space after or before `[` and `]` 54 | - Separated with a comma and a space like: `, `. 55 | - Integers should be in base 10. 56 | - We'll use unsigned 32 bit integers method to represent numbers. 57 | -------------------------------------------------------------------------------- /noob_questions/box.md: -------------------------------------------------------------------------------- 1 | # The problem 2 | ![Box with 9 23 14 14 18 5 written on it](https://ds055uzetaobb.cloudfront.net/image_optimizer/4792c83f3197dbc4d38097fd1fd45e3b8cffff7c.png) 3 | 4 | A magic word is needed to open a certain box. A secret code assign each letter of the alphabet to a unique number. The code for the magic word is written on the outside of he box. 5 | 6 | # What is the word inside the box? 7 | To help you, here is some words that could have been written: 8 | - LOOSER 9 | - SECRET 10 | - LOTTOS 11 | - WINNER 12 | 13 | _This challenge was inspired by [Brilliant](http://brilliant.org)_ 14 | -------------------------------------------------------------------------------- /noob_questions/caesar-encrypt.md: -------------------------------------------------------------------------------- 1 | # Caesar Cipher 2 | 3 | ## History and usage 4 | 5 | The _Caesar Cipher_ was named after Julius Caesar (100 B.C. – 44 B.C). He would use the cipher for secret communication (protect messages of military significance). The Caesar Cipher is a **substitution cipher**. Originally, Julius Caesar would use a shift of three to encrypt/decrypt a message. The Caesar Cipher encrypts a message using an affine function : f(x) = 1x + b. 6 | 7 | ## Detailed Explanations : How it works? 8 | 9 | 1. Firstly, each character of the initial text (message to encrypt) is converted in a number from 0 to 25, corresponding to its position in the Latin alphabet which contains 26 letters --> (a = 0, b = 1 ... z = 25 ). 10 | 11 | 2. Then, each number obtained is transformed by an affine function (f(x) = 1x + b). "x" is representing the number while "b" is defined during the encryption. "b" is the key used to decrypt the final message. 12 | 13 | 3. If we take all the images and put them in a list, we obtain n numbers corresponding to n characters of the initial text. The next step consists in finding the values of modulo 26 of each number. (**Modulo means remainder**) 14 | 15 | > Example : Modulo 4 of 19 is **3** because `19 = 4 * 4 + 3` In the other hand, modulo 26 of 26 is **0** because `26 = 26 * 1 + 0` 16 | 17 | 1. Therefore, we obtain a new list with n element, each between 0 and 25 both included. All these numbers are converted in letters of the Latin Alphabet using the tables below. 18 | 19 | 2. We finally create the final message by putting all the letters side by side. 20 | 21 | Steps 1 and 4 can be done with these tables : 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 |
ABCDEFGHIJKLMNOPQRSTUVWXYZ
012345678910111213141516171819202122232425
85 | 86 | # What you need to do: 87 | 88 | **Using this explanation, what would be the encoded string of `HELLO` with the key `4`** 89 | -------------------------------------------------------------------------------- /noob_questions/emojigraphy.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | This is the first challenge of this platform. It's pretty easy, but don't worry, it will get harder in 3 | the next challenges. 4 | 5 | ### Tutorial: 6 | - On this section, you'll always see the 'course' and the challenge that you need to do 7 | - On your right (or on the bottom if you're on mobile), there is a form. This is where you'll post your answers. 8 | > **ProTip 💡:** 9 | - Press `Enter` to submit your answer. 10 | 11 | # Emoji cipher 12 | 13 | The Emoji cipher is a very basic cipher. 14 | 15 | Basically, we convert letters to emojis to encode a message, and we do the opposite operation to decode this encrypted message. 16 | 17 | Here is the table: 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
ABCDEFGHIJKLMNOPQRSTUVWXYZ
😄😃😀😊😅😉😍😘😚😗😙😜😝😛😳😁😔😌😒😞😣😢😂😭😎😈
80 | 81 | # What you need to do 82 | 83 | **Using this explanation, what would be the encoded string of `EMOJI`** 84 | -------------------------------------------------------------------------------- /noob_questions/frequencyanalysis.md: -------------------------------------------------------------------------------- 1 | # Frequency Analysis with Caesar Cipher 2 | Remember the [Caesar Cipher](https://cryptools.github.io/learn/noob#caesar-encrypt) challenge? 3 | 4 | > The Caesar Cipher, also known as a shift cipher, is one of the oldest and simplest forms of encrypting a message. It is a type of substitution cipher where each letter in the original message (which in cryptography is called the plaintext) is replaced with a letter corresponding to a certain number of letters shifted up or down in the alphabet. 5 | 6 | So for example, if our letter is `A` and our shift is `4`, we get `E`. 7 | 8 | # Get the key: 9 | With a given encrypted text, we can get the key by analyzing the letters frequency. For example, in English `E` is the most used letter. 10 | 11 | ### Example 12 | If you have `pixxiv`, we see that there are 2 `i` and 2 `x`. We'll start with `i`, and we'll suppose that it's an `e`. 13 | ```js 14 | i - e = 4 // We aren't substracting letters but their position in the alphabet 15 | ``` 16 | Let's try to decode `pixxiv` with `4`. 17 | 18 | And we get `letter`, which is an English word, so the key was `4`. 19 | 20 | # What you need to do? 21 | Try to get the key of the following phrase: 22 | ``` 23 | aol xbpjr iyvdu mve qbtwz vcly aol shgf kvn 24 | ``` 25 | -------------------------------------------------------------------------------- /noob_questions/hashshift.md: -------------------------------------------------------------------------------- 1 | # HashShift 2 | 3 | > ⚠️ We strongly recommend you to know how to program in at least one programming language 4 | 5 | ## How it works? 6 | 7 | > We'll use the Swift implementation to describe what we're doing 8 | 9 | First, let's take a seed for our generator: 10 | 11 | ```swift 12 | var seed = 12 13 | ``` 14 | 15 | Then let's hash his `String` representation: 16 | 17 | ```swift 18 | let hash = String(seed).sha256 19 | ``` 20 | 21 | Now, we'll take the `10` first characters of the outputed hex digest: 22 | 23 | ```swift 24 | let first = hash.prefix(10) 25 | ``` 26 | 27 | Now we have a `hex` representation of a number in a `String`, let's parse it: 28 | 29 | ```swift 30 | let n = Int(first, radix: 16) 31 | ``` 32 | 33 | Then, we rotate `n` like: 34 | 35 | ```swift 36 | let r = (n! >> 13 * seed) % 99371 // for non-swift developers, 'n!' doesn't mean n factorial but the unwrapped value of n 37 | ``` 38 | 39 | And we change the `seed`: 40 | 41 | ```swift 42 | seed = (r ^ n! << 2 + n!) % 70937 43 | ``` 44 | 45 | Finally we output the absolute value as `Float` of `r` divided by `99371` to have a number between `0` and `1`: 46 | 47 | ```swift 48 | return Float(abs(r)) / 99371 49 | ``` 50 | 51 | # What you need to do? 52 | **Using this explanation, determine what would be the second number outputted using `seed = 12` by the HashShift PRNG** 53 | 54 | ## Requirements 55 | - Your answer is composed of the `10` first digits. 56 | - We write numbers in the english way, like `3.1415926535` or `0.57721566`. 57 | -------------------------------------------------------------------------------- /noob_questions/inverse.md: -------------------------------------------------------------------------------- 1 | # Question: 2 | If FIND is coded as URMW and ME is coded as NV, then how is CRYPTOOLS coded as? 3 | 4 | ## Help? 5 | You should look at this alphabet table: 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
ABCDEFGHIJKLMNOPQRSTUVWXYZ
39 | -------------------------------------------------------------------------------- /noob_questions/railfence.md: -------------------------------------------------------------------------------- 1 | # Railfence Cipher 2 | 3 | A transposition cipher also called the zigzag cipher. 4 | 5 | ## How it works 6 | 7 | ### Encoding 8 | 9 | The Rail Fence Cipher places the letters in a zigzag pattern before reading them again, from top to bottom, right to left, ignoring the zigzag. 10 | 11 | Example: 12 | 13 | Let's imagine that we are encoding `Hello World!` on 3 rails. we draw out our three rails and place the lettres in the zigzag pattern like this: 14 | 15 | ```txt 16 | H - - - o - - - r - - - 17 | - e - l - - o - l - ! 18 | - - l - - - w - - - d - 19 | ``` 20 | 21 | When this is read top to bottom, left to right, we get `Horel ol!lwd` 22 | 23 | # What you need to do: 24 | - Find what would become the phrase `The Railfence Cipher is not that secure` with `8` rails 25 | -------------------------------------------------------------------------------- /noob_questions/randomness.md: -------------------------------------------------------------------------------- 1 | # Randomness 2 | > ⚠️ We strongly recommend you to know how to program in at least one programming language. 3 | 4 | You've stumbled onto a significant vulnerability in a commonly used cryptographic library. It turns out that the random number generator it uses frequently produces the same primes when it is generating keys. 5 | 6 | ### Key 1 7 | ``` 8 | 1c7bb1ae67670f7e6769b515c174414278e16c27e95b43a789099a1c7d55c717b2f0a0442a7d49503ee09552588ed9bb6eda4af738a02fb31576d78ff72b2499b347e49fef1028182f158182a0ba504902996ea161311fe62b86e6ccb02a9307d932f7fa94cde410619927677f94c571ea39c7f4105fae00415dd7d 9 | ``` 10 | ### Key 2 11 | ``` 12 | 2710e45014ed7d2550aac9887cc18b6858b978c2409e86f80bad4b59ebcbd90ed18790fc56f53ffabc0e4a021da2e906072404a8b3c5555f64f279a21ebb60655e4d61f4a18be9ad389d8ff05b994bb4c194d8803537ac6cd9f708e0dd12d1857554e41c9cbef98f61c5751b796e5b37d338f5d9b3ec3202b37a32f 13 | ``` 14 | 15 | # What you need to do 16 | Exploit this knowledge to factor the (hexadecimal) keys below, and enter your answer as the last six digits of the largest factor you find (in decimal). 17 | 18 | 19 | > This challenge comes from [Brilliant](https://brilliant.org/problems/sometimes-we-need-more-random/) 20 | -------------------------------------------------------------------------------- /noob_questions/rsa.md: -------------------------------------------------------------------------------- 1 | # RSA 2 | **The RSA encryption is based on the following procedure:** 3 | 4 | Generate two distinct primes p and q. 5 | Compute `n = pq` and `φ = (p - 1)(q - 1)`. 6 | Find an integer `e`, `1 < e < φ`, such that `gcd(e, φ) = 1`. 7 | 8 | A message in this system is a number in the interval `[0, n - 1]`. 9 | A text to be encrypted is then somehow converted to messages (numbers in the interval `[0, n - 1]`). 10 | To encrypt the text, for each message, `m`, `c = me mod n` is calculated. 11 | 12 | To decrypt the text, the following procedure is needed: calculate `d` such that `ed = 1 mod φ`, then for each encrypted message, `c`, calculate `m = cd mod n`. 13 | 14 | There exist values of `e` and `m` such that `me mod n = m`. 15 | We call messages m for which me mod n=m unconcealed messages. 16 | 17 | An issue when choosing e is that there should not be too many unconcealed messages. 18 | For instance, let `p = 19` and `q = 37`. 19 | Then `n= 19*37 = 703` and `φ = 18*36 = 648`. 20 | If we choose `e=181`, then, although `gcd(181, 648) = 1` it turns out that all possible messages 21 | `m (0 ≤ m ≤ n - 1)` are unconcealed when calculating `me mod n`. 22 | For any valid choice of `e` there exist some unconcealed messages. 23 | > It's important that the number of unconcealed messages is at a minimum. 24 | 25 | # What you need to do: 26 | - Choose `p = 1009` and `q = 3643`. 27 | 28 | Find the sum of all values of e, `1< e <φ(1009,3643)` and `gcd(e, φ) = 1`, so that the number of unconcealed messages for this value of `e` is at a minimum. 29 | -------------------------------------------------------------------------------- /noob_questions/vernam.md: -------------------------------------------------------------------------------- 1 | # Vernam Cipher 2 | Suppose Alice wishes to send the message "HELLO" to Bob. Assume two pads of paper containing identical random sequences of letters were somehow previously produced and securely issued to both. Alice chooses the appropriate unused page from the pad. 3 | 4 | The material on the selected sheet is the key for this message. Each letter from the pad will be combined in a predetermined way with one letter of the message. (It is common, but not required, to assign each letter a numerical value, e.g., "A" is 0, "B" is 1, and so on.) 5 | 6 | # Encryption 7 | 8 | In this example, the technique is to combine the key and the message using modular addition. The numerical values of corresponding message and key letters are added together, modulo 26\. So, if key material begins with "XMCKL" and the message is "HELLO", then the coding would be done as follows: 9 | 10 | ``` 11 | H E L L O message 12 | 7 (H) 4 (E) 11 (L) 11 (L) 14 (O) message 13 | + 23 (X) 12 (M) 2 (C) 10 (K) 11 (L) key 14 | = 30 16 13 21 25 message + key 15 | = 4 (E) 16 (Q) 13 (N) 21 (V) 25 (Z) (message + key) mod 26 16 | E Q N V Z → ciphertext 17 | ``` 18 | 19 | If a number is larger than 26, then the remainder after subtraction of 26 is taken in modular arithmetic fashion. This simply means that if the computations "go past" Z, the sequence starts again at A. 20 | 21 | # What you need to do? 22 | What would be `CRYPTOOLS` encrypted with `VERNAMCIP`? 23 | -------------------------------------------------------------------------------- /robots.txt: -------------------------------------------------------------------------------- 1 | # www.robotstxt.org/ 2 | 3 | # Allow crawling of all content 4 | User-agent: * 5 | Disallow: 6 | 7 | Sitemap: https://cryptools.github.io/sitemap.txt 8 | --------------------------------------------------------------------------------