Skip to content

Commit

Permalink
3.3.0 to 3.3.2: Merge pull request #19 from mqxym/dev
Browse files Browse the repository at this point in the history
3.3.0 to 3.3.2
  • Loading branch information
mqxym authored Nov 9, 2024
2 parents bae74d0 + 8914151 commit 3e81c36
Show file tree
Hide file tree
Showing 5 changed files with 812 additions and 376 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# EmojiCrypt Version 3.2.0 🌈
# EmojiCrypt Version 3.3.2 🌈

Your convenient and secure text encryption, where emojis are all that matters.
This repo is hosted here:
Expand All @@ -22,8 +22,8 @@ The idea is to implement a protocol where only you and the receiver knows what t
- Generate emoji keys which look like encrypted messages
- Save keys within the browser
- Site can be added to homescreen on Android and iOS to act as an app (Webapp)
- The web app is available in 7 languages (feel free to improve the automated translations, not all features have been translated yet)
- Dark mode
- The web app is available in 7 languages (feel free to improve the automated translations)
- Auto Dark mode

### Basic Security Information 🔐

Expand All @@ -50,7 +50,7 @@ The idea is to implement a protocol where only you and the receiver knows what t
3. The hash before that
4. A custom, fixed salt that differs in each of the 16 switch cases
- Custom Hash Loop Lengths: As of version 1.1.0, different encryption algorithms have varying hash loop lengths and intermediate salt integers. Therefore, each of the three encryption algorithms uses a custom, deterministically derived key: 256-bit for AES and 4096-byte for XOR (as of version 3.0.0)
- *On modern devices, the hashing time can range from a minimum of 400 to a maximum of 1500 miliseconds and it is heavily dependent of the random salt*
- *On modern devices, the hashing time can range from a minimum of ~700 to a maximum of ~1000 miliseconds and it is dependent of the random salt resulting in more or less hash rounds and a different distribution in more computationally intensive hash functions (SHA-384,SHA-512)*
- Additional obfuscation: As of version 3.1.0, the binary-to-emoji algorithm employs a unique emoji sorting order derived from the input key.

## Includes ⤴️
Expand Down
152 changes: 120 additions & 32 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,20 @@
<div class="wrapper">
<!-- Main Content -->
<div class="main-container">
<!-- Encryption/Decryption Section -->
<!-- Crypto API Error Header -->
<div class="p-2 m-3 bg-danger border rounded rounded-sm d-none" id="errorHeader">
<span class="text-light">
Your browser does not support this application. Please update your system.
Your browser does not support this application. Please update your browser or system.
</span>
</div>
<!-- Javascript Support Error Header -->
<noscript>
<div class="p-2 m-3 bg-danger border rounded rounded-sm">
<span class="text-light">
Your browser does not support this application. Please enable JavaScript in your browser settings.
</span>
</div>
</noscript>
<!-- Encryption/Decryption Section -->
<div class="main-content p-3 encrypt-section" id="encryptSection">
<form class="form">
Expand Down Expand Up @@ -224,12 +232,12 @@
<hr><hr>

<!-- Private Conversion Algorithm -->
<a class="btn btn-secondary bg-secondary btn-block text-light mb-3" data-toggle="collapse" data-target="#privateAlgorithmSection" aria-expanded="true" aria-controls="privateAlgorithmSection">💎 Private Algorithm</a>
<a class="btn btn-secondary bg-secondary btn-block text-light mb-3" data-toggle="collapse" data-target="#privateAlgorithmSection" aria-expanded="true" aria-controls="privateAlgorithmSection" id="showPrivateAlgorithmButton">💎 Private Algorithm</a>
<div id="privateAlgorithmSection" class="collapse">
<div class="card">
<div class="card-body">
<button id="generatePrivateConversionButton" type="button" class="btn btn-secondary bg-dark btn-block mb-2">🔮 Generate (new) private algorithm</button>
Your link to the private conversion algorithm: <br>
<span id="privateLinkText">Your link to the private conversion algorithm: </span> <br>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">🧬</span>
Expand All @@ -243,15 +251,15 @@
</div>

<div class="card-footer">
<i>
<i id="privateAlgorithmDisclaimer">
Using a private algorithm is just another layer of obfuscation, but can be cracked pretty easily.
<br>
Especially, when using the same algorithm more than once.
</i>
</div>
</div>
</div>
<i class="text-muted"> You can use a private algorithm with a unique key to obfuscate your messages.</i>
<i class="text-muted" id="privateAlgorithmFooter"> You can use a private algorithm with a unique key to obfuscate your messages.</i>
</div>
<!-- About Section -->
<div class="p-3 main-content info-section" id="aboutSection">
Expand Down Expand Up @@ -335,6 +343,31 @@ <h5 class="mb-0">
</div>
</div>
</div>
<!-- FAQ Item 25 -->
<div class="card">
<div class="card-header" id="faqHeading25">
<h5 class="mb-0">
<button class="btn faq-button collapsed" type="button" data-toggle="collapse" data-target="#faqCollapse25" aria-expanded="false" aria-controls="faqCollapse25">
<strong id="faqQuestion25">How do I use the private algorithm?</strong>
</button>
</h5>
</div>
<div id="faqCollapse25" class="collapse" aria-labelledby="faqHeading3" data-parent="#faqAccordion">
<div class="card-body">
<span id="faqAnswer25">
To use the private algorithm:
<ul>
<li>Ensure you're on the <strong>Conversion</strong> app (the default app).</li>
<li>Click <strong>💎 Private Algorithm</strong> and generate a key.</li>
<li>You can use the conversion app like before.</li>
<li>Share the link with your receipient.</li>
<li>When the key does not match, the output is gibberish.</li>
<li>The more you use the same key for different messages and the longer the messages are, the easier it is to crack the key.</li>
</ul>
</span>
</div>
</div>
</div>
<!-- FAQ Item 4 -->
<div class="card">
<div class="card-header" id="faqHeading4">
Expand Down Expand Up @@ -764,7 +797,7 @@ <h5 class="card-title">Privacy Policy for NasaEmoji</h5>
if ( privateConversionId ) {
customEmojiArray = await generateSecurePermutationFromString(privateConversionId, getEmojiArray());
$('#privateConversionLink').val(window.location.href);
$('#convertTopMessage').html("<i class='text-muted'>A private algorithm is used. <br>Click '💎 Private Algorithm' for more information.</i>")
$('#convertTopMessage').html(getTranslation('privateAlgorithmHeader', languageIndex));
$('#disablePrivateConversionButton').removeClass('d-none');
} else {
customEmojiArray = null;
Expand All @@ -787,6 +820,25 @@ <h5 class="card-title">Privacy Policy for NasaEmoji</h5>
{ code: 'fr', name: 'French 🇫🇷' },
{ code: 'ar', name: 'Arabic 🇸🇦' },
];

/**
* Retrieves the matching language code from the global languages array by reading the user set language.
*
* @returns {string|null} The matching language code if found, otherwise `null`.
*/
function getUserLanguageCode() {
// Get the user's preferred language from the browser
const userLanguage = navigator.language || (navigator.languages && navigator.languages[0]) || 'en';

// Extract the primary language code (e.g., 'en' from 'en-US')
const primaryCode = userLanguage.split('-')[0].toLowerCase();

// Find the language with the primary code
const language = languages.find(lang => lang.code.toLowerCase() === primaryCode);

// Return the language code if found, otherwise null
return language ? language.code : null;
}

/**
* Get the language code from the URL parameter 'lang'.
Expand All @@ -811,10 +863,11 @@ <h5 class="card-title">Privacy Policy for NasaEmoji</h5>
* @returns {Object} An object containing languageCode and languageIndex.
*/
function initializeLanguage() {
let languageCode = getLanguageCodeFromURL() || localStorage.getItem('lang') || 'en';
let languageCode = getLanguageCodeFromURL() || localStorage.getItem('lang') || getUserLanguageCode() || 'en';
let languageIndex = getLanguageIndexFromCode(languageCode);

if (languageIndex === -1) {

languageCode = 'en';
languageIndex = 0;
}
Expand Down Expand Up @@ -851,6 +904,13 @@ <h5 class="card-title">Privacy Policy for NasaEmoji</h5>
{ selector: '#explanation', key: 'explanation' },
{ selector: '#footerHighlight', key: 'footerHighlight' },
{ selector: '#footerSource', key: 'footerSource' },
{ selector: '#privateLinkText', key: 'privateLinkText' },
{ selector: '#copyPrivateConversionLink', key: 'copyPrivateConversionLink' },
{ selector: '#disablePrivateConversionButton', key: 'disablePrivateConversionButton' },
{ selector: '#privateAlgorithmDisclaimer', key: 'privateAlgorithmDisclaimer' },
{ selector: '#generatePrivateConversionButton', key: 'generatePrivateConversionButton' },
{ selector: '#privateAlgorithmFooter', key: 'privateAlgorithmFooter' },
{ selector: '#showPrivateAlgorithmButton', key: 'showPrivateAlgorithmButton' },
];

// Elements to update placeholder attributes
Expand All @@ -865,7 +925,7 @@ <h5 class="card-title">Privacy Policy for NasaEmoji</h5>
* @param {number} languageIndex - Index of the current language.
*/
function updateFAQItems(languageIndex) {
const faqItemCount = 24;
const faqItemCount = 25;
for (let i = 1; i <= faqItemCount; i++) {
$(`#faqQuestion${i}`).html(getTranslation(`faqQuestion${i}`, languageIndex));
$(`#faqAnswer${i}`).html(getTranslation(`faqAnswer${i}`, languageIndex));
Expand Down Expand Up @@ -957,11 +1017,22 @@ <h5 class="card-title">Privacy Policy for NasaEmoji</h5>

/**
* Check if dark mode is enabled.
* @returns {boolean} True if dark mode is enabled.
* @returns {boolean} True if dark mode is enabled
*/
function isDarkModeEnabled() {
return localStorage.getItem('darkMode') === 'true';
}

/**
* DarkMode Toggle for site device
*/
function handleDarkModeToggle () {
if (isDarkModeEnabled()) {
disableDarkMode();
} else {
enableDarkMode();
}
}

const darkModeClassToggles = [
{ selector: 'body', classes: 'bg-dark text-light dark-mode' },
Expand All @@ -978,11 +1049,11 @@ <h5 class="card-title">Privacy Policy for NasaEmoji</h5>
{ selector: '.form-control', classes: 'bg-secondary text-light' },
{ selector: 'footer', removeClasses: 'bg-light', classes: 'bg-dark text-light' },
];

/**
* Enable dark mode by adding appropriate classes.
*/
function enableDarkMode() {
function enableDarkMode(fromToggle = false) {
darkModeClassToggles.forEach((item) => {
if (item.removeClasses) {
$(item.selector).removeClass(item.removeClasses);
Expand Down Expand Up @@ -1022,6 +1093,22 @@ <h5 class="card-title">Privacy Policy for NasaEmoji</h5>
localStorage.setItem('darkMode', 'false');
$('#darkModeMenu').html(getTranslation('enableDarkMode', languageIndex));
}

function setAutoDarkMode () {
if (darkModeDeviceIsActive()) {
enableDarkMode();
} else {
disableDarkMode();
}
}
/**
* Get device dark mode information
*
* @returns {boolean} Returns True if device dark mode is enabled
*/
function darkModeDeviceIsActive() {
return (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches);
}

// =======================================
// Section Transition Handling
Expand Down Expand Up @@ -1209,16 +1296,16 @@ <h5 class="card-title">Privacy Policy for NasaEmoji</h5>

switch (currentMenu) {
case 'encryptSection':
title = 'Encrypt Text with Emojis - Emoji Encryption Tool';
description = 'Securely encrypt and decrypt messages using emojis.';
title = getTranslation('metaTitleEncrypt', languageIndex);
description = getTranslation('metaDescriptionEncrypt', languageIndex);
break;
case 'convertSection':
title = 'Convert Text to Emojis - Emoji Conversion Tool';
description = 'Easily convert your text into emojis and back.';
title = getTranslation('metaTitleConvert', languageIndex);
description = getTranslation('metaTitleEncrypt', languageIndex);
break;
case 'aboutSection':
title = 'About Emoji Encryption Tool';
description = 'Learn more about our emoji encryption and conversion tool.';
title = getTranslation('metaTitleAbout', languageIndex);
description = getTranslation('metaDescriptionAbout', languageIndex);
break;
}

Expand Down Expand Up @@ -1270,17 +1357,17 @@ <h5 class="card-title">Privacy Policy for NasaEmoji</h5>
};

// Dark Mode Toggle
if (isDarkModeEnabled()) {
enableDarkMode();
} else {
disableDarkMode();
}
setAutoDarkMode();

$('#darkModeMenu').click(function () {
if (isDarkModeEnabled()) {
disableDarkMode();
} else {
handleDarkModeToggle()
});

window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
if (event.matches) {
enableDarkMode();
} else {
disableDarkMode();
}
});

Expand Down Expand Up @@ -1483,17 +1570,17 @@ <h5 class="card-title">Privacy Policy for NasaEmoji</h5>

$('#privateConversionLink').val(window.location.href);
$('#disablePrivateConversionButton').removeClass('d-none');
$('#convertTopMessage').html("<i class='text-muted'>A private algorithm is used. <br>Click '💎 Private Algorithm' for more information.</i>")
$thisButton.removeClass('bg-dark').addClass('bg-success').text("⚙️ Private algorithm generated!");
$('#convertTopMessage').html(getTranslation('privateAlgorithmHeader', languageIndex));
$thisButton.removeClass('bg-dark').addClass('bg-success').text(getTranslation('btnPrivateAlgorithmGenerated', languageIndex));
await new Promise((r) => setTimeout(r, 5000));
$thisButton.addClass('bg-dark').removeClass('bg-success').text("🔮 Generate (new) private algorithm");
$thisButton.addClass('bg-dark').removeClass('bg-success').text(getTranslation('generatePrivateConversionButton', languageIndex));

});

// Handle remove private algorithm button
$('#disablePrivateConversionButton').click(async function () {
if (customEmojiArray) {
if (confirm("Do you want to remove the private algorithm?")) {
if (confirm(getTranslation('modalDisablePrivateAlgorithm', languageIndex))) {
if (localStorage.getItem("pa")) {
localStorage.removeItem("pa");
}
Expand All @@ -1503,10 +1590,10 @@ <h5 class="card-title">Privacy Policy for NasaEmoji</h5>
updateURLParameter();
$('#privateConversionLink').val(null);
$('#convertTopMessage').addClass('d-none');
$thisButton.text("Algorithm removed.");
$thisButton.text(getTranslation('btnPrivateAlgorithmRemoved', languageIndex));
await new Promise((r) => setTimeout(r, 4000));
$thisButton.addClass('d-none');
$thisButton.text("🗑️ Remove private algorithm");
$thisButton.text(getTranslation('disablePrivateConversionButton', languageIndex));
}
}
});
Expand Down Expand Up @@ -1538,6 +1625,7 @@ <h5 class="card-title">Privacy Policy for NasaEmoji</h5>

// Update the UI language
updateUILanguage();
updateMetadata();

// Update the URL
history.pushState(null, '', href);
Expand Down
Loading

0 comments on commit 3e81c36

Please sign in to comment.