admin / crypto flashcards

Last active 1 week ago

Like 0

Revision 26a7ce4dd0e6a17b09a69d5c03d5233190478f40

crypto flashcards Raw
1<!DOCTYPE html>
2<html lang="en">
3<head>
4<meta charset="UTF-8">
5<meta name="viewport" content="width=device-width, initial-scale=1.0">
6
7<title>Learn2Lan Cryptography Study</title>
8
9<style>
10:root {
11 --bg: #080b10;
12 --panel: #111722;
13 --panel2: #171e2b;
14 --text: #f4f7fb;
15 --muted: #98a2b3;
16
17 --green: #8cff00;
18 --purple: #b45cff;
19 --orange: #ff9d00;
20 --red: #ff4d67;
21
22 --border: #283143;
23}
24
25* {
26 box-sizing: border-box;
27}
28
29body {
30 margin: 0;
31 font-family: Arial, Helvetica, sans-serif;
32 background:
33 radial-gradient(circle at top left, rgba(180,92,255,.12), transparent 30%),
34 radial-gradient(circle at top right, rgba(140,255,0,.08), transparent 25%),
35 #080b10;
36 color: var(--text);
37 min-height: 100vh;
38}
39
40.wrapper {
41 width: min(1000px, 94%);
42 margin: auto;
43 padding: 40px 0 60px;
44}
45
46/* HEADER */
47
48header {
49 margin-bottom: 28px;
50}
51
52.brand {
53 color: var(--green);
54 font-size: .9rem;
55 font-weight: bold;
56 letter-spacing: 3px;
57 text-transform: uppercase;
58}
59
60h1 {
61 margin: 8px 0 6px;
62 font-size: clamp(2rem, 5vw, 3.5rem);
63}
64
65.subtitle {
66 color: var(--muted);
67 margin: 0;
68}
69
70/* STATS */
71
72.stats {
73 margin-top: 24px;
74 display: grid;
75 grid-template-columns: repeat(4, 1fr);
76 gap: 12px;
77}
78
79.stat {
80 background: rgba(17,23,34,.8);
81 border: 1px solid var(--border);
82 border-radius: 12px;
83 padding: 15px;
84}
85
86.stat-number {
87 font-size: 1.5rem;
88 font-weight: bold;
89}
90
91.stat-label {
92 color: var(--muted);
93 font-size: .8rem;
94 margin-top: 4px;
95}
96
97.stat:nth-child(1) .stat-number {
98 color: var(--purple);
99}
100
101.stat:nth-child(2) .stat-number {
102 color: var(--green);
103}
104
105.stat:nth-child(3) .stat-number {
106 color: var(--red);
107}
108
109.stat:nth-child(4) .stat-number {
110 color: var(--orange);
111}
112
113/* PROGRESS */
114
115.progress-track {
116 height: 7px;
117 background: #1c2330;
118 border-radius: 10px;
119 overflow: hidden;
120 margin: 18px 0 26px;
121}
122
123.progress-bar {
124 height: 100%;
125 width: 0%;
126 background: linear-gradient(
127 90deg,
128 var(--purple),
129 var(--green),
130 var(--orange)
131 );
132 transition: width .3s ease;
133}
134
135/* MODE BUTTONS */
136
137.toolbar {
138 display: flex;
139 gap: 10px;
140 flex-wrap: wrap;
141 margin-bottom: 24px;
142}
143
144button {
145 border: 1px solid var(--border);
146 background: var(--panel);
147 color: white;
148 padding: 11px 16px;
149 border-radius: 8px;
150 cursor: pointer;
151 font-weight: bold;
152 transition: .2s;
153}
154
155button:hover {
156 transform: translateY(-1px);
157 border-color: var(--purple);
158}
159
160.active {
161 border-color: var(--purple);
162 box-shadow: 0 0 18px rgba(180,92,255,.2);
163}
164
165/* FLASHCARD */
166
167.card-area {
168 perspective: 1000px;
169}
170
171.flashcard {
172 height: 340px;
173 position: relative;
174 cursor: pointer;
175}
176
177.card-inner {
178 position: relative;
179 width: 100%;
180 height: 100%;
181 transition: transform .55s;
182 transform-style: preserve-3d;
183}
184
185.flashcard.flipped .card-inner {
186 transform: rotateY(180deg);
187}
188
189.card-face {
190 position: absolute;
191 width: 100%;
192 height: 100%;
193
194 backface-visibility: hidden;
195 -webkit-backface-visibility: hidden;
196
197 background:
198 linear-gradient(
199 145deg,
200 rgba(180,92,255,.05),
201 rgba(140,255,0,.02)
202 ),
203 var(--panel);
204
205 border: 1px solid var(--border);
206 border-radius: 20px;
207
208 display: flex;
209 flex-direction: column;
210 justify-content: center;
211 align-items: center;
212
213 text-align: center;
214 padding: 40px;
215}
216
217.card-front {
218 box-shadow: 0 20px 60px rgba(0,0,0,.35);
219}
220
221.card-back {
222 transform: rotateY(180deg);
223 border-color: rgba(140,255,0,.35);
224}
225
226.card-label {
227 position: absolute;
228 top: 24px;
229 left: 28px;
230
231 text-transform: uppercase;
232 letter-spacing: 2px;
233 font-size: .72rem;
234 color: var(--muted);
235}
236
237.card-front h2 {
238 font-size: clamp(2.5rem, 8vw, 5rem);
239 margin: 0;
240 color: var(--purple);
241}
242
243.card-back h2 {
244 font-size: clamp(1.5rem, 5vw, 2.5rem);
245 max-width: 750px;
246 color: var(--green);
247 margin: 0;
248}
249
250.tap {
251 position: absolute;
252 bottom: 20px;
253 color: var(--muted);
254 font-size: .78rem;
255}
256
257/* RESULT BUTTONS */
258
259.result-buttons {
260 display: grid;
261 grid-template-columns: 1fr 1fr;
262 gap: 12px;
263 margin-top: 18px;
264}
265
266.know {
267 border-color: rgba(140,255,0,.4);
268}
269
270.know:hover {
271 background: rgba(140,255,0,.08);
272 border-color: var(--green);
273}
274
275.missed {
276 border-color: rgba(255,77,103,.4);
277}
278
279.missed:hover {
280 background: rgba(255,77,103,.08);
281 border-color: var(--red);
282}
283
284/* NAVIGATION */
285
286.navigation {
287 margin-top: 16px;
288 display: grid;
289 grid-template-columns: 1fr auto 1fr;
290 align-items: center;
291 gap: 12px;
292}
293
294.navigation button:last-child {
295 justify-self: end;
296}
297
298.counter {
299 color: var(--muted);
300 font-size: .9rem;
301}
302
303.message {
304 margin-top: 24px;
305 padding: 18px;
306 border: 1px solid var(--border);
307 border-radius: 12px;
308 background: var(--panel);
309 color: var(--muted);
310 display: none;
311}
312
313/* MOBILE */
314
315@media (max-width: 650px) {
316
317 .stats {
318 grid-template-columns: 1fr 1fr;
319 }
320
321 .flashcard {
322 height: 300px;
323 }
324
325 .card-face {
326 padding: 28px 20px;
327 }
328
329 .navigation {
330 grid-template-columns: 1fr 1fr;
331 }
332
333 .counter {
334 grid-column: 1 / -1;
335 grid-row: 1;
336 text-align: center;
337 }
338
339 .navigation button:last-child {
340 justify-self: stretch;
341 }
342
343 .navigation button {
344 width: 100%;
345 }
346}
347</style>
348</head>
349
350
351<body>
352
353<div class="wrapper">
354
355<header>
356 <div class="brand">Learn2Lan</div>
357
358 <h1>Cryptography Study Lab</h1>
359
360 <p class="subtitle">
361 Algorithms, key sizes, block sizes, IVs, and message digests.
362 </p>
363
364 <div class="stats">
365
366 <div class="stat">
367 <div class="stat-number" id="totalCount">20</div>
368 <div class="stat-label">Cards</div>
369 </div>
370
371 <div class="stat">
372 <div class="stat-number" id="knownCount">0</div>
373 <div class="stat-label">Known</div>
374 </div>
375
376 <div class="stat">
377 <div class="stat-number" id="missedCount">0</div>
378 <div class="stat-label">Missed</div>
379 </div>
380
381 <div class="stat">
382 <div class="stat-number" id="remainingCount">20</div>
383 <div class="stat-label">Unreviewed</div>
384 </div>
385
386 </div>
387
388 <div class="progress-track">
389 <div class="progress-bar" id="progressBar"></div>
390 </div>
391</header>
392
393
394<div class="toolbar">
395
396 <button id="allButton" class="active" onclick="showAll()">
397 Study All
398 </button>
399
400 <button id="missedButton" onclick="showMissed()">
401 Review Missed
402 </button>
403
404 <button onclick="shuffleCards()">
405 Shuffle
406 </button>
407
408 <button onclick="resetProgress()">
409 Reset Progress
410 </button>
411
412</div>
413
414
415<div class="card-area">
416
417 <div class="flashcard" id="flashcard" onclick="flipCard()">
418
419 <div class="card-inner">
420
421 <div class="card-face card-front">
422
423 <span class="card-label">
424 Algorithm / Technology
425 </span>
426
427 <h2 id="cardFront"></h2>
428
429 <span class="tap">
430 Click card to reveal answer
431 </span>
432
433 </div>
434
435
436 <div class="card-face card-back">
437
438 <span class="card-label">
439 Key Fact
440 </span>
441
442 <h2 id="cardBack"></h2>
443
444 <span class="tap">
445 Click card to flip back
446 </span>
447
448 </div>
449
450 </div>
451
452 </div>
453
454</div>
455
456
457<div class="result-buttons">
458
459 <button
460 class="missed"
461 onclick="event.stopPropagation(); markCard('missed')">
462
463 ✕ Missed It
464
465 </button>
466
467 <button
468 class="know"
469 onclick="event.stopPropagation(); markCard('known')">
470
471 ✓ Know It
472
473 </button>
474
475</div>
476
477
478<div class="navigation">
479
480 <button onclick="previousCard()">
481 ← Previous
482 </button>
483
484 <div class="counter" id="counter"></div>
485
486 <button onclick="nextCard()">
487 Next →
488 </button>
489
490</div>
491
492
493<div class="message" id="message"></div>
494
495</div>
496
497
498
499<script>
500
501/*
502=================================================
503LEARN2LAN CRYPTOGRAPHY STUDY DATA
504=================================================
505*/
506
507const cards = [
508
509{
510 front: "A5/1",
511 back: "64-bit key; used with GSM cellular networks"
512},
513
514{
515 front: "A5/3 / KASUMI",
516 back: "128-bit key; associated with 3GPP"
517},
518
519{
520 front: "WEP",
521 back: "24-bit IV; uses RC4"
522},
523
524{
525 front: "WPA / TKIP",
526 back: "Uses RC4 with a 128-bit key"
527},
528
529{
530 front: "WPA2",
531 back: "48-bit IV"
532},
533
534{
535 front: "AES",
536 back: "128-bit blocks; 128-, 192-, or 256-bit keys"
537},
538
539{
540 front: "DES",
541 back: "64-bit block size"
542},
543
544{
545 front: "3DES",
546 back: "64-bit blocks; 112-bit key option"
547},
548
549{
550 front: "IDEA",
551 back: "64-bit blocks; 128-bit key"
552},
553
554{
555 front: "Skipjack",
556 back: "64-bit blocks; 80-bit key"
557},
558
559{
560 front: "XTEA",
561 back: "64-bit blocks; 128-bit key"
562},
563
564{
565 front: "Blowfish",
566 back: "Variable key size: 32–448 bits"
567},
568
569{
570 front: "Twofish",
571 back: "Variable key size up to 256 bits"
572},
573
574{
575 front: "MD5",
576 back: "Produces a 128-bit message digest"
577},
578
579{
580 front: "SHA-1",
581 back: "Produces a 160-bit message digest"
582},
583
584{
585 front: "Trivium",
586 back: "80-bit key + 80-bit IV"
587},
588
589{
590 front: "Rabbit",
591 back: "128-bit key + 64-bit IV"
592},
593
594{
595 front: "PRESENT",
596 back: "Hardware-oriented lightweight SPN block cipher"
597},
598
599{
600 front: "SPECK",
601 back: "Lightweight block cipher optimized for software"
602},
603
604{
605 front: "SIMON",
606 back: "Lightweight block cipher optimized for hardware"
607}
608
609];
610
611
612/*
613=================================================
614APP STATE
615=================================================
616*/
617
618let studyCards = [...cards];
619
620let currentIndex = 0;
621
622let progress =
623 JSON.parse(
624 localStorage.getItem("l2lCryptoProgress")
625 ) || {};
626
627
628/*
629=================================================
630DISPLAY CARD
631=================================================
632*/
633
634function displayCard() {
635
636 if (studyCards.length === 0) {
637
638 document.getElementById("message").style.display = "block";
639
640 document.getElementById("message").innerHTML =
641 "No cards are currently in this study set.";
642
643 document.getElementById("cardFront").innerText = "Complete";
644
645 document.getElementById("cardBack").innerText =
646 "Nothing to review.";
647
648 document.getElementById("counter").innerText = "0 / 0";
649
650 return;
651 }
652
653 document.getElementById("message").style.display = "none";
654
655 if (currentIndex >= studyCards.length) {
656 currentIndex = 0;
657 }
658
659 const card = studyCards[currentIndex];
660
661 document.getElementById("cardFront").innerText =
662 card.front;
663
664 document.getElementById("cardBack").innerText =
665 card.back;
666
667 document.getElementById("counter").innerText =
668 `${currentIndex + 1} / ${studyCards.length}`;
669
670 document
671 .getElementById("flashcard")
672 .classList
673 .remove("flipped");
674
675 updateStats();
676}
677
678
679/*
680=================================================
681FLIP CARD
682=================================================
683*/
684
685function flipCard() {
686
687 document
688 .getElementById("flashcard")
689 .classList
690 .toggle("flipped");
691
692}
693
694
695/*
696=================================================
697NAVIGATION
698=================================================
699*/
700
701function nextCard() {
702
703 if (studyCards.length === 0) return;
704
705 currentIndex++;
706
707 if (currentIndex >= studyCards.length) {
708 currentIndex = 0;
709 }
710
711 displayCard();
712}
713
714
715function previousCard() {
716
717 if (studyCards.length === 0) return;
718
719 currentIndex--;
720
721 if (currentIndex < 0) {
722 currentIndex = studyCards.length - 1;
723 }
724
725 displayCard();
726}
727
728
729/*
730=================================================
731MARK CARD
732=================================================
733*/
734
735function markCard(status) {
736
737 if (studyCards.length === 0) return;
738
739 const card =
740 studyCards[currentIndex];
741
742 progress[card.front] = status;
743
744 localStorage.setItem(
745 "l2lCryptoProgress",
746 JSON.stringify(progress)
747 );
748
749 updateStats();
750
751 setTimeout(
752 nextCard,
753 150
754 );
755
756}
757
758
759/*
760=================================================
761STATS
762=================================================
763*/
764
765function updateStats() {
766
767 let known = 0;
768
769 let missed = 0;
770
771 cards.forEach(card => {
772
773 if (progress[card.front] === "known") {
774 known++;
775 }
776
777 if (progress[card.front] === "missed") {
778 missed++;
779 }
780
781 });
782
783 const reviewed =
784 known + missed;
785
786 const remaining =
787 cards.length - reviewed;
788
789 document.getElementById("totalCount").innerText =
790 cards.length;
791
792 document.getElementById("knownCount").innerText =
793 known;
794
795 document.getElementById("missedCount").innerText =
796 missed;
797
798 document.getElementById("remainingCount").innerText =
799 remaining;
800
801 const percent =
802 cards.length
803 ? (reviewed / cards.length) * 100
804 : 0;
805
806 document.getElementById("progressBar").style.width =
807 percent + "%";
808
809}
810
811
812/*
813=================================================
814STUDY ALL
815=================================================
816*/
817
818function showAll() {
819
820 studyCards =
821 [...cards];
822
823 currentIndex = 0;
824
825 document
826 .getElementById("allButton")
827 .classList
828 .add("active");
829
830 document
831 .getElementById("missedButton")
832 .classList
833 .remove("active");
834
835 displayCard();
836
837}
838
839
840/*
841=================================================
842REVIEW MISSED
843=================================================
844*/
845
846function showMissed() {
847
848 studyCards =
849 cards.filter(
850 card =>
851 progress[card.front] === "missed"
852 );
853
854 currentIndex = 0;
855
856 document
857 .getElementById("missedButton")
858 .classList
859 .add("active");
860
861 document
862 .getElementById("allButton")
863 .classList
864 .remove("active");
865
866 displayCard();
867
868}
869
870
871/*
872=================================================
873SHUFFLE
874=================================================
875*/
876
877function shuffleCards() {
878
879 for (
880 let i = studyCards.length - 1;
881 i > 0;
882 i--
883 ) {
884
885 const j =
886 Math.floor(
887 Math.random() * (i + 1)
888 );
889
890 [
891 studyCards[i],
892 studyCards[j]
893 ] =
894 [
895 studyCards[j],
896 studyCards[i]
897 ];
898
899 }
900
901 currentIndex = 0;
902
903 displayCard();
904
905}
906
907
908/*
909=================================================
910RESET
911=================================================
912*/
913
914function resetProgress() {
915
916 const confirmed =
917 confirm(
918 "Reset all study progress?"
919 );
920
921 if (!confirmed) return;
922
923 progress = {};
924
925 localStorage.removeItem(
926 "l2lCryptoProgress"
927 );
928
929 showAll();
930
931}
932
933
934/*
935=================================================
936KEYBOARD SHORTCUTS
937=================================================
938*/
939
940document.addEventListener(
941 "keydown",
942 event => {
943
944 if (event.code === "Space") {
945
946 event.preventDefault();
947
948 flipCard();
949
950 }
951
952 if (event.key === "ArrowRight") {
953 nextCard();
954 }
955
956 if (event.key === "ArrowLeft") {
957 previousCard();
958 }
959
960 if (event.key.toLowerCase() === "k") {
961 markCard("known");
962 }
963
964 if (event.key.toLowerCase() === "m") {
965 markCard("missed");
966 }
967
968 }
969);
970
971
972/*
973=================================================
974START APP
975=================================================
976*/
977
978displayCard();
979
980</script>
981
982</body>
983</html>
984