tughra
Version:
The Tughra Library offers robust End-to-End Encryption (E2EE), ensuring that data remains private and secure from the point it leaves the sender to the moment it reaches the intended recipient. With E2EE, data is encrypted on the sender's device, transmit
2 lines (1 loc) • 17.2 kB
JavaScript
class Tughra{constructor(t,e,r,n="",a=!1){const s=Array.from(new Set(n)).map((t=>{const e="string"==typeof t?t.charCodeAt(0):t;if(isNaN(e))throw new Error("Invalid character in encryption array. Only letters and numbers are allowed.");return t})).join("");if("default"===r&&0===s.length)throw new Error("keyOffsets must contain at least one valid value.");this.keyOffsets=s,this.mode=t||"encrypt",this.useBaseEncoding=a,this.baseCharset=e||"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",this.baseLibrary=this.baseEncodeDecode(this.baseCharset),this.encryptionKey=(new TextEncoder).encode(n),"default"!==r&&this.checkKeyStrength(n),this.algorithm=r||"default",this.substitutionKey={a:"q",b:"w",c:"e",d:"r",e:"t",f:"y",g:"u",h:"i",i:"o",j:"p",k:"a",l:"s",m:"d",n:"f",o:"g",p:"h",q:"j",r:"k",s:"l",t:"z",u:"x",v:"c",w:"v",x:"b",y:"n",z:"m",A:"Q",B:"W",C:"E",D:"R",E:"T",F:"Y",G:"U",H:"I",I:"O",J:"P",K:"A",L:"S",M:"D",N:"F",O:"G",P:"H",Q:"J",R:"K",S:"L",T:"Z",U:"X",V:"C",W:"V",X:"B",Y:"N",Z:"M"},this.reverseSubstitutionKey=Object.fromEntries(Object.entries(this.substitutionKey).map((([t,e])=>[e,t]))),this.a=5,this.b=8,this.m=26}setAlgorithm(t){this.algorithm=t}checkKeyStrength(t){if(t.length<8)throw new Error("Key must be at least 8 characters long.")}process(t,e){this.useBaseEncoding&&"decrypt"===this.mode&&(t=this.fromBase(t)),"xor"!==this.algorithm&&"ROT47"!==this.algorithm&&"ROT13"!==this.algorithm||(e=1);let r=t;for(let t=0;t<e;t++)r=this._processCycle(r,this.mode);return this.useBaseEncoding&&"encrypt"===this.mode?this.toBase(r):r}_processCycle(t,e){switch(this.algorithm){case"caesar":return"encrypt"===e?this._caesarEncrypt(t):this._caesarDecrypt(t);case"vigenere":return"encrypt"===e?this._vigenereEncrypt(t):this._vigenereDecrypt(t);case"xor":return"encrypt"===e?this._xorEncrypt(t):this._xorDecrypt(t);case"ROT47":return"encrypt"===e?this._encryptROT47(t):this._decryptROT47(t);case"Atbash":return"encrypt"===e?this._encryptAtbash(t):this._decryptAtbash(t);case"Substitution":return"encrypt"===e?this._encryptSubstitution(t):this._decryptSubstitution(t);case"Base64":return"encrypt"===e?this._encryptBase64(t):this._decryptBase64(t);case"ASCII":return"encrypt"===e?this._encryptAsciiShift(t):this._decryptAsciiShift(t);case"Affine":return"encrypt"===e?this._encryptAffine(t):this._decryptAffine(t);case"Unicode Shift":return"encrypt"===e?this._encryptUnicodeShift(t):this._decryptUnicodeShift(t);case"Numeric":return"encrypt"===e?this._encryptNumeric(t):this._decryptNumeric(t);case"Reversed Caesar":return"encrypt"===e?this._encryptReversedCaesar(t):this._decryptReversedCaesar(t);case"ROT13":return"encrypt"===e?this._encryptROT13(t):this._decryptROT13(t);case"ROT18":return"encrypt"===e?this._encryptROT18(t):this._decryptROT18(t);case"ROT25":return"encrypt"===e?this._encryptROT25(t):this._decryptROT25(t);case"ROT30":return"encrypt"===e?this._encryptROT30(t):this._decryptROT30(t);case"XOR Pro":return"encrypt"===e?this._encryptXORPro(t,this.keyOffsets):this._decryptXORPro(t,this.keyOffsets);case"Affine Pro":return"encrypt"===e?this._encryptAffinePro(t,this.encryptionKey):this._decryptAffinePro(t,this.encryptionKey);case"Substitution Pro":return"encrypt"===e?this._encryptSubstitutionPro(t,this.encryptionKey):this._decryptSubstitutionPro(t,this.encryptionKey);default:return"encrypt"===e?this._TughraEncrypt(t):this._TughraDecrypt(t)}}_modInverse(t,e){for(let r=1;r<e;r++)if(t*r%e==1)return r;return null}_encryptAffine(t){return t.split("").map((t=>{if(/[A-Za-z]/.test(t)){const e=t===t.toUpperCase()?65:97;return String.fromCharCode((this.a*(t.charCodeAt(0)-e)+this.b)%26+e)}return t})).join("")}_decryptAffine(t){const e=this._modInverse(this.a,26);return t.split("").map((t=>{if(/[A-Za-z]/.test(t)){const r=t===t.toUpperCase()?65:97;return String.fromCharCode((e*(t.charCodeAt(0)-r-this.b+26)%26+26)%26+r)}return t})).join("")}_encryptAffinePro(t){return t.split("").map((t=>{if(/[a-zA-Z]/.test(t)){const e=t===t.toUpperCase()?"A".charCodeAt(0):"a".charCodeAt(0),r=t.charCodeAt(0)-e;return String.fromCharCode((this.a*r+this.b)%this.m+e)}return t})).join("")}_decryptAffinePro(t){const e=this._modInverse(this.a,this.m);if(null===e)throw new Error("No modular inverse exists for the given key 'a'");return t.split("").map((t=>{if(/[a-zA-Z]/.test(t)){const r=t===t.toUpperCase()?"A".charCodeAt(0):"a".charCodeAt(0),n=t.charCodeAt(0)-r;return String.fromCharCode(e*(n-this.b+this.m)%this.m+r)}return t})).join("")}_encryptSubstitutionPro(t){return t.split("").map((t=>this.substitutionKey[t]||t)).join("")}_decryptSubstitutionPro(t){return t.split("").map((t=>this.reverseSubstitutionKey[t]||t)).join("")}_encryptROT13(t){return t.replace(/[A-Za-z]/g,(t=>{const e=t<="Z"?"A".charCodeAt(0):"a".charCodeAt(0);return String.fromCharCode((t.charCodeAt(0)-e+13)%26+e)}))}_decryptROT13(t){return this._encryptROT13(t)}_encryptROT18(t){return t.replace(/[A-Za-z]/g,(t=>{const e=t<="Z"?"A".charCodeAt(0):"a".charCodeAt(0);return String.fromCharCode((t.charCodeAt(0)-e+18)%26+e)}))}_decryptROT18(t){return t.replace(/[A-Za-z]/g,(t=>{const e=t<="Z"?"A".charCodeAt(0):"a".charCodeAt(0);return String.fromCharCode((t.charCodeAt(0)-e+26-18)%26+e)}))}_encryptROT25(t){return t.replace(/[A-Za-z]/g,(t=>{const e=t<="Z"?"A".charCodeAt(0):"a".charCodeAt(0);return String.fromCharCode((t.charCodeAt(0)-e+25)%26+e)}))}_decryptROT25(t){return t.replace(/[A-Za-z]/g,(t=>{const e=t<="Z"?"A".charCodeAt(0):"a".charCodeAt(0);return String.fromCharCode((t.charCodeAt(0)-e+26-25)%26+e)}))}_encryptROT30(t){return t.replace(/[A-Za-z]/g,(t=>{const e=t<="Z"?"A".charCodeAt(0):"a".charCodeAt(0);return String.fromCharCode((t.charCodeAt(0)-e+4)%26+e)}))}_decryptROT30(t){return t.replace(/[A-Za-z]/g,(t=>{const e=t<="Z"?"A".charCodeAt(0):"a".charCodeAt(0);return String.fromCharCode(((t.charCodeAt(0)-e+22)%26+26)%26+e)}))}_encryptXORPro(t,e){return t.split("").map(((t,r)=>String.fromCharCode(t.charCodeAt(0)^e.charCodeAt(r%e.length)))).join("")}_decryptXORPro(t,e){return this._encryptXORPro(t,e)}_TughraEncrypt(t){let e="";for(let r=0;r<t.length;r++){let n=t.charCodeAt(r),a=this.keyOffsets.charCodeAt(r%this.keyOffsets.length);e+=String.fromCharCode(n+a)}return e}_TughraDecrypt(t){let e="";for(let r=0;r<t.length;r++){let n=t.charCodeAt(r),a=this.keyOffsets.charCodeAt(r%this.keyOffsets.length);e+=String.fromCharCode(n-a)}return e}_caesarEncrypt(t){return t.split("").map((t=>String.fromCharCode(t.charCodeAt(0)+this.encryptionKey.length))).join("")}_caesarDecrypt(t){return t.split("").map((t=>String.fromCharCode(t.charCodeAt(0)-this.encryptionKey.length))).join("")}_vigenereEncrypt(t){const e=(new TextEncoder).encode(t).map(((t,e)=>(t+this.encryptionKey[e%this.encryptionKey.length])%256));return this._arrayBufferToBase64(e)}_vigenereDecrypt(t){const e=this._base64ToArrayBuffer(t).map(((t,e)=>(t-this.encryptionKey[e%this.encryptionKey.length]+256)%256));return(new TextDecoder).decode(Uint8Array.from(e))}_arrayBufferToBase64(t){const e=[],r=new Uint8Array(t);for(let t=0;t<r.length;t+=8192)e.push(String.fromCharCode(...r.slice(t,t+8192)));return btoa(e.join(""))}_base64ToArrayBuffer(t){const e=atob(t),r=new Uint8Array(e.length);for(let t=0;t<e.length;t++)r[t]=e.charCodeAt(t);return r}_xorEncrypt(t){if(!this.encryptionKey)throw new Error("Encryption key is missing.");const e=(new TextEncoder).encode(t),r=(new TextEncoder).encode(this.encryptionKey),n=e.map(((t,e)=>t^r[e%r.length]));return btoa(String.fromCharCode(...n))}_xorDecrypt(t){const e=atob(t).split("").map((t=>t.charCodeAt(0))),r=(new TextEncoder).encode(this.encryptionKey),n=e.map(((t,e)=>t^r[e%r.length]));return(new TextDecoder).decode(Uint8Array.from(n))}_encryptROT47(t){return t.replace(/[!-~]/g,(t=>String.fromCharCode(33+(t.charCodeAt(0)+14)%94)))}_decryptROT47(t){return this.encryptROT47(t)}_encryptAtbash(t){return t.replace(/[a-zA-Z]/g,(t=>{const e=t<="Z"?65:97;return String.fromCharCode(e+(25-(t.charCodeAt(0)-e)))}))}_decryptAtbash(t){return this.encryptAtbash(t)}_encryptSubstitution(t){return t.split("").map((t=>this.substitutionKey[t]||t)).join("")}_decryptSubstitution(t){return t.split("").map((t=>this.reverseSubstitutionKey[t]||t)).join("")}_encryptBase64(t){return btoa(t)}_decryptBase64(t){return atob(t)}_encryptAsciiShift(t){return t.split("").map((t=>String.fromCharCode(t.charCodeAt(0)+this.encryptionKey.length))).join("")}_decryptAsciiShift(t){return t.split("").map((t=>String.fromCharCode(t.charCodeAt(0)-this.encryptionKey.length))).join("")}_encryptUnicodeShift(t){return t.split("").map((t=>String.fromCharCode(t.charCodeAt(0)+this.encryptionKey.length))).join("")}_decryptUnicodeShift(t){return t.split("").map((t=>String.fromCharCode(t.charCodeAt(0)-this.encryptionKey.length))).join("")}_encryptNumeric(t){return t.split("").map((t=>t.charCodeAt(0))).join("-")}_decryptNumeric(t){return t.split("-").map((t=>String.fromCharCode(parseInt(t)))).join("")}_encryptReversedCaesar(t){return t.replace(/[a-zA-Z]/g,(t=>{const e=t<="Z"?65:97;return String.fromCharCode((25-(t.charCodeAt(0)-e)+this.encryptionKey.length)%26+e)}))}_decryptReversedCaesar(t){return t.replace(/[a-zA-Z]/g,(t=>{const e=t<="Z"?65:97;return String.fromCharCode((25-(t.charCodeAt(0)-e)-this.encryptionKey.length+26)%26+e)}))}toBase(t){if(!t)return t;try{return this.baseLibrary.encode(unescape(encodeURIComponent(t)))}catch(e){return console.error("Base encoding failed:",e),t}}fromBase(t){if(!t)return t;try{return decodeURIComponent(escape(this.baseLibrary.decode(t)))}catch(e){return console.error("Base decoding failed:",e),t}}baseEncodeDecode(t){const e=t.length,r=Math.ceil(Math.log(e));return{encode:e=>{let n="",a="";for(let t=0;t<e.length;t++)a+=e.charCodeAt(t).toString(2).padStart(8,"0");for(let e=0;e<a.length;e+=r){const s=a.substring(e,e+r).padEnd(r,"0"),i=parseInt(s,2);n+=t[i]}return n},decode:e=>{let n="";for(let a=0;a<e.length;a++){const s=t.indexOf(e[a]);if(-1===s)throw new Error("Invalid Base character");n+=s.toString(2).padStart(r,"0")}let a="";for(let t=0;t<n.length;t+=8){const e=n.substring(t,t+8);8===e.length&&(a+=String.fromCharCode(parseInt(e,2)))}return a}}}}class TughraLibrary{constructor(){this.unicodeGroups=[{name:"Numbers",start:48,end:57},{name:"Lowercase English",start:97,end:122},{name:"Uppercase English",start:65,end:90},{name:"Basic Latin",start:33,end:127},{name:"Latin-1 Supplement",start:128,end:255},{name:"Latin Extended-A",start:256,end:383},{name:"Latin Extended-B",start:384,end:591},{name:"IPA Extensions",start:592,end:687},{name:"Greek and Coptic",start:880,end:1023},{name:"Cyrillic",start:1024,end:1279},{name:"Arabic",start:1536,end:1791},{name:"Hebrew",start:1424,end:1535},{name:"Devanagari",start:2304,end:2431},{name:"Bengali",start:2432,end:2559},{name:"Gurmukhi",start:2560,end:2687},{name:"Gujarati",start:2688,end:2815},{name:"Oriya",start:2816,end:2943},{name:"Tamil",start:2944,end:3071},{name:"Telugu",start:3072,end:3199},{name:"Kannada",start:3200,end:3327},{name:"Malayalam",start:3328,end:3455},{name:"Thai",start:3584,end:3711},{name:"Lao",start:3712,end:3839},{name:"Tibetan",start:3840,end:4095},{name:"Georgian",start:4256,end:4351},{name:"Hangul Jamo",start:4352,end:4607},{name:"Latin Extended Additional",start:7680,end:7935},{name:"Greek Extended",start:7936,end:8191},{name:"General Punctuation",start:8192,end:8303},{name:"Superscripts and Subscripts",start:8304,end:8351},{name:"Currency Symbols",start:8352,end:8399},{name:"Combining Diacritical Marks",start:8400,end:8447},{name:"Letterlike Symbols",start:8448,end:8527},{name:"Number Forms",start:8528,end:8591},{name:"Arrows",start:8592,end:8703},{name:"Mathematical Operators",start:8704,end:8959},{name:"Miscellaneous Technical",start:8960,end:9215},{name:"Control Pictures",start:9216,end:9279},{name:"Optical Character Recognition",start:9280,end:9311},{name:"Enclosed Alphanumerics",start:9312,end:9471},{name:"Box Drawing",start:9472,end:9599},{name:"Block Elements",start:9600,end:9631},{name:"Geometric Shapes",start:9632,end:9727},{name:"Miscellaneous Symbols",start:9728,end:9983},{name:"Dingbats",start:9984,end:10175},{name:"Braille Patterns",start:10240,end:10495},{name:"CJK Symbols and Punctuation",start:12288,end:12351},{name:"Hiragana",start:12352,end:12447},{name:"Katakana",start:12448,end:12543},{name:"Bopomofo",start:12544,end:12591},{name:"Hangul Compatibility Jamo",start:12592,end:12687},{name:"Phonetic Extensions",start:12704,end:12735},{name:"Enclosed CJK Letters and Months",start:12800,end:13055},{name:"CJK Compatibility",start:13056,end:13311},{name:"CJK Unified Ideographs",start:19968,end:40959},{name:"Hangul Syllables",start:44032,end:55215},{name:"Private Use Area",start:57344,end:63743},{name:"CJK Compatibility Ideographs",start:63744,end:64255},{name:"Alphabetic Presentation Forms",start:64256,end:64335},{name:"Arabic Presentation Forms-A",start:64336,end:65023},{name:"Variation Selectors",start:65024,end:65039},{name:"Combining Half Marks",start:65056,end:65071},{name:"CJK Compatibility Forms",start:65072,end:65103},{name:"Small Form Variants",start:65104,end:65135},{name:"Arabic Presentation Forms-B",start:65136,end:65279},{name:"Halfwidth and Fullwidth Forms",start:65280,end:65519},{name:"Specials",start:65520,end:65535},{name:"Linear B Syllabary",start:65536,end:65663},{name:"Linear B Ideograms",start:65664,end:65791},{name:"Aegean Numbers",start:65792,end:65855},{name:"Ancient Greek Numbers",start:65856,end:65935},{name:"Ancient Symbols",start:65936,end:65999},{name:"Phaistos Disc",start:66e3,end:66047},{name:"Lycian",start:66176,end:66207},{name:"Carian",start:66208,end:66271},{name:"Coptic Epact Numbers",start:66272,end:66303},{name:"Old Italic",start:66304,end:66351},{name:"Gothic",start:66352,end:66383},{name:"Old Permic",start:66384,end:66431},{name:"Ugaritic",start:66432,end:66463},{name:"Old Persian",start:66464,end:66527},{name:"Deseret",start:66560,end:66639},{name:"Shavian",start:66640,end:66687},{name:"Osmanya",start:66688,end:66735},{name:"Cypriot Syllabary",start:67584,end:67647},{name:"Imperial Aramaic",start:67648,end:67679},{name:"Phoenician",start:67840,end:67871},{name:"Lydian",start:67872,end:67903},{name:"Meroitic Hieroglyphs",start:67968,end:67999},{name:"Meroitic Cursive",start:68e3,end:68095},{name:"Kharoshthi",start:68096,end:68191},{name:"Old South Arabian",start:68192,end:68223},{name:"Avestan",start:68352,end:68415},{name:"Inscriptional Parthian",start:68416,end:68447},{name:"Inscriptional Pahlavi",start:68448,end:68479},{name:"Old Turkic",start:68480,end:68511},{name:"Rumi Numeral Symbols",start:68512,end:68543},{name:"Brahmi",start:69632,end:69703},{name:"Kaithi",start:69728,end:69791},{name:"Sora Sompeng",start:69840,end:69863},{name:"Chakma",start:69984,end:70079},{name:"Sharada",start:70080,end:70143},{name:"Takri",start:70144,end:70239},{name:"Mahajani",start:70240,end:70271},{name:"Mandaic",start:70272,end:70335},{name:"Ahlat",start:70336,end:70383},{name:"Miao",start:70384,end:70431},{name:"Arabic Mathematical Alphabetic Symbols",start:70464,end:70495},{name:"CJK Compatibility Ideographs Extension A",start:108224,end:108455},{name:"CJK Compatibility Ideographs Extension B",start:110576,end:110751},{name:"CJK Compatibility Ideographs Extension C",start:110752,end:110855},{name:"CJK Compatibility Ideographs Extension D",start:110856,end:110879},{name:"CJK Compatibility Ideographs Extension E",start:110880,end:110999},{name:"CJK Compatibility Ideographs Extension F",start:111040,end:111411}]}_formatSize(t){const e=["bytes","KB","MB","GB","TB"];let r=0;for(;t>=1024&&r<e.length-1;)t/=1024,r++;return`${t.toFixed(2)} ${e[r]}`}_calculateStats(t){let e,r="text/plain";if(t instanceof Blob)e=t.text(),r=t.type;else{if("string"==typeof t&&t.startsWith("data:")){const[n,a]=t.split(",");r=n.match(/:(.*?);/)[1];const s=atob(a);e=s;const i=new Blob([s],{type:r});return{characters:s.length,words:s.trim().split(/\s+/).filter(Boolean).length,lines:s.split(/\r\n|\r|\n/).length,size:i.size,type:r,isBlob:!1,isDataURI:!0}}e=t}const n=new Blob([e],{type:r}).size,a=e.trim().split(/\s+/).filter(Boolean).length,s=e.split(/\r\n|\r|\n/).length;return{characters:e.length,words:a,lines:s,size:n,type:r,isBlob:t instanceof Blob,isDataURI:!1}}detectLanguage(t){const e={};this.unicodeGroups.forEach((t=>{e[t.name]=0}));for(let r of t){const t=r.charCodeAt(0);for(let r of this.unicodeGroups)if(t>=r.start&&t<=r.end){e[r.name]++;break}}let r=null,n=0;for(let t in e)e[t]>n&&(n=e[t],r=t);return r}getUnicodeGroups(){return this.unicodeGroups}generateKey(t,e){const r=[],n=[];e.split(",").forEach((t=>{const e=t.trim(),r=this.unicodeGroups.find((t=>t.name===e));if(!r)throw new Error(`Invalid Unicode group name: ${e}`);n.push(r)}));for(let e=0;e<t;e++){const t=n[Math.floor(Math.random()*n.length)],e=[];for(let r=t.start;r<=t.end;r++)e.push(String.fromCharCode(r));const a=Math.floor(Math.random()*e.length);r.push(e[a])}return r}displayCharacters(t){const e=this.unicodeGroups.find((e=>e.name===t));if(!e)return console.log(`Group "${t}" not found.`),"";let r="";for(let t=e.start;t<=e.end;t++)r+=String.fromCodePoint(t);return r}}"undefined"!=typeof module&&module.exports&&(module.exports=Tughra,module.exports=TughraLibrary);