PageSourceSearch

https://www.bergbahn-heidelberg.de/de/static/js/HRSysLib/Security/cryptTools.js?nc=1790145913416

js bergbahn-heidelberg.de collected 2026-09-24 18:56:26 UTC 11,523 bytes, 291 lines download raw bytes

1/** **************************************************************************
2// Firma:        Hehner Reus Systems GmbH
3// Projekt:      com.cerno.basis
4// Datei:        cryptTools
5// Erstellung:   12.10.2022
6// Verwendung:   Diese Klasse bietet ein paar bequeme Zugriffe auf kryptografische Funktionen an.
7//
8// Benötigte JS-Dateien: DOM.js, CSS.js, Event.js
9//
10// $Id: cryptTools.js,v 1.15 2025/06/06 10:58:11 lpo Exp $
11// $Author: lpo $
12//
13/**************************************************************************** */
14
15"use strict";
16
17class HRCrypt
18{
19   /*
20    * Die für eine Eingabe eines Passwortes erlaubten Sonderzeichen.
21    */
22   static PasswordSpecialCharacters = '[`~!@#$%^&*()\\-_=+|\[{\\]}};:\'\",<.>\/?]';
23   
24   /**
25    * Folgender Algorithmus "verschlüsselt" eine gegebene (kurze!) Zeichenkette nach dem Prinzip "Security by Obscurity". Es handelt sich 
26    * nicht wirklich um eine Verschlüsselung, sondern darum, die gegebene Zeichenkette anhand eines unbekannten Verfahrens so schlecht 
27    * lesbar wie nur möglich zu machen. Längere Texte können natürlich über eine Häufigkeitsanalyse ohne Weiteres "entschlüsselt" werden.
28    * Der Zweck dieses Algorithmuses liegt darin, kurze Texte wie E-Mailadressen im Quellcode der Seite nicht im Klartext stehen zu haben.  
29    * Wir wollen hier eine Hürde schaffen, damit z.B. Bots keine E-Mail-Adressen im Klartext auf der Seite abgreifen können. Auch benutzen 
30    * wir kein Standard-Verschlüsselungsverfahren, weil dieses auch clientseitig umgesetzt werden muss und wir dort unseren auf dem Server 
31    * gespeicherten Schlüssel nicht nutzen dürfen.
32    * 
33    * <p>(Da E-Mail-Adressen i.A. sehr kurz sind, ist der Erfolg beim Angriff der Häufigkeitsanalyse sogar recht unwahrscheinlich.)</p>
34    * 
35    * <p><strong>Achtung:</strong></p>
36    * <p>Da hier jeglicher Pseudozufall fehlt und aus wiederholtem Input der selbe Output generiert wird, auf keinen Fall für ernsthafte 
37    * Verschlüsselungen nutzen! Das ist KEIN sinnvoller Verschlüsselungsalgorithmus!</p>
38    *
39    * @param message Die zu verschlüsselnde Nachricht.
40    * @return Die "verschlüsselte" Nachricht.
41    */
42   static hrEncrypt(message)
43   {
44      // Dreht den String einmal um...
45      let reversedString = '';
46      for (let i = message.length - 1; i >= 0; i--)
47      {
48         reversedString += message.charAt(i);
49      }
50      
51      // ...und einmal noch die Bytes spiegeln.
52      let tempBytes = new Uint8Array(reversedString.length);
53      for (let i = 0; i < reversedString.length; i++)
54      {
55         tempBytes[i] = 255 - reversedString.charCodeAt(i);
56      }
57      
58      // Base64-Kodierung der Byte-Daten
59      let binaryString = '';
60      for (let byte of tempBytes)
61      {
62         binaryString += String.fromCharCode(byte);
63      }
64      return btoa(binaryString).trim();
65   }
66   
67   /**
68    * Folgender Algorithmus "entschlüsselt" eine gegebene (kurze!) Zeichenkette, die zuvor nach dem Prinzip "Security by Obscurity" verschlüsselt wurde.  
69    * Es handelt sich nicht wirklich um eine Verschlüsselung, sondern darum, die gegebene Zeichenkette anhand eines unbekannten Verfahrens so schlecht 
70    * lesbar wie nur möglich zu machen. Längere Texte können natürlich über eine Häufigkeitsanalyse ohne Weiteres "entschlüsselt" werden. 
71    * Der Zweck dieses Algorithmuses liegt darin, kurze Texte wie E-Mailadressen im Quellcode der Seite nicht im Klartext stehen zu haben. 
72    * Wir wollen hier eine Hürde schaffen, damit z.B. Bots keine E-Mail-Adressen im Klartext auf der Seite abgreifen können.
73    * 
74    * @param message Eine über unsere eigene "HR-Encode" verschlüsselte Nachricht.
75    * @returns die entschlüsselte Nachricht.
76    */
77   static hrDecrypt(message)
78   {
79      // Base-64-Decoding.
80      const temp = window.atob(message);
81      
82      let decrypted = '';
83      for (let i = temp.length - 1; i >= 0; i--)
84      {
85         decrypted += temp.charAt(i);
86      }
87      
88      let encoder = [];
89      for (let i = 0; i < decrypted.length; i++)
90      {
91         encoder[i] = 255 - decrypted.charCodeAt(i);
92      }
93      
94      decrypted = '';
95      for (let i = 0; i < encoder.length; i++)
96      {
97         decrypted += String.fromCharCode(encoder[i]);
98      }
99      
100      return decrypted;
101   };
102   
103   /**
104    * Verschlüsselt eine gegebene Nachricht mithilfe einer Fibonacci-Sequenz zur Modifikation der Zeichenwerte.
105    * Die Fibonacci-Sequenz ist eine Zahlenreihe, in der jede Zahl die Summe der beiden vorhergehenden Zahlen ist, beginnend mit 3 und 5.
106    * 
107    * <p><strong>Achtung:</strong></p>
108    * <p>Da hier jeglicher Pseudozufall fehlt und aus wiederholtem Input der selbe Output generiert wird, auf keinen Fall für ernsthafte 
109    * Verschlüsselungen nutzen! Das ist KEIN sinnvoller Verschlüsselungsalgorithmus!</p>
110    *
111    * @param message Die zu verschlüsselnde Nachricht.
112    * @return Die verschlüsselte Nachricht als String.
113    */
114   static hrEncryptFibonacciShift(message)
115   {
116      // Fibonacci-Verschlüsselung: Startet bei 3 & 5
117      let prev = 3;
118      let next = 5;
119      let result = '';
120      
121      for (let curr of message)
122      {
123         // Zeichen aus dem Alphabet von 33 bis 126
124         result += String.fromCharCode(((curr.charCodeAt(0) + next) % 93) + 33);
125         let temp = prev + next;
126         prev = next;
127         next = temp;
128      }
129      
130      return result.trim();
131   }
132   
133   /**
134    * Verschlüsselt eine gegebene Nachricht mithilfe abwechselnder Bitverschiebungen.
135    * Bei der Bitverschiebung wird abwechselnd nach links und nach rechts verschoben.
136    *
137    * <p><strong>Achtung:</strong></p>
138    * <p>Da hier jeglicher Pseudozufall fehlt und aus wiederholtem Input der selbe Output generiert wird, auf keinen Fall für ernsthafte 
139    * Verschlüsselungen nutzen! Das ist KEIN sinnvoller Verschlüsselungsalgorithmus!</p>
140    *
141    * @param message Die zu verschlüsselnde Nachricht.
142    * @return Die verschlüsselte Nachricht als String.
143    */
144   static hrEncryptAlternateBitShift(message) 
145   {
146      let result = '';
147      
148      // Bit-Shift-Verschiebung: Abwechselnd links und rechts
149      let shiftLeft = true;
150      
151      // Schleife über die Nachricht
152      for (let curr of message)
153      {
154         // Verschiebung des Zeichens um eine Stelle.
155         let shiftedChar;
156         if (shiftLeft)
157            shiftedChar = (curr.charCodeAt(0) << 1) & 0x7F;
158         else
159            shiftedChar = (curr.charCodeAt(0) >> 1) & 0x7F;
160         
161         // Stellt sicher, dass es druckbare Zeichen sind.
162         result += String.fromCharCode((shiftedChar % 93) + 33);
163         
164         // Wechsel der Richtung der Bitverschiebung
165         shiftLeft = !shiftLeft;
166      }
167      
168      return result.trim();
169   }
170   
171   /**
172    * Validiert ein Passwort nach bestimmten Passwort-Policies.
173    * 
174    * @param password Passwort zum Überprüfen.
175    * @param min Gibt die Mindestlänge des Passwortes an.
176    * @param caseSensitive Gibt an, ob Groß- und Kleinschreibung überprüft werden soll.
177    * @param specials Gibt an, ob in dem Passwort Sonderzeichen vorhanden sein sollten.
178    * @param numbers Gibt an, ob in dem Passwort Zahlen vorkommen sollten.
179    * 
180    * @return Ein js-Objekt der Form {min: true/false, caseSensitive: true/false, specials: true/false, numbers: true/false},
181    *         welches angibt, welche Prüfungen gescheitert und welche erfüllt sind. Wurde keine Zeichenkette übergeben (null, 
182    *         undefined, anderer Type, so wird null zurückgegeben.
183    */
184   static validatePassword(password, min, caseSensitive, specials, numbers)
185   {
186      let result = null;
187      
188      try
189      {
190         if (password != null && password != undefined && typeof(password) === 'string')
191         {
192            result = {};
193            
194            password = password.trim();
195            
196            // Test: Minimum an Zeichen
197            if (min > 0)
198               result.min = (password.length >= min);
199            
200            // Test: Groß- und Kleinschreibung
201            if (caseSensitive)
202               result.caseSensitive = (/(?=.*[a-z])(?=.*[A-Z])/.exec(password) != null);
203            
204            // Test: Sonderzeichen
205            if (specials)
206               result.specials = (new RegExp(this.PasswordSpecialCharacters).exec(password) != null);
207            
208            // Test: Zahl in Passwort
209            if (numbers)
210               result.numbers = (/\d/.exec(password) != null);
211         }
212      }
213      catch (e)
214      {
215         if (typeof(HRLogError) === 'function')
216            HRLogError(e);
217      }
218      
219      return result;
220   }
221   
222   /**
223    * Diese Funktion dekodiert jede Mail-Adresse die mit dem data-Attribut "data-encrypted" 
224    * oder dem von uns eigens entwickelten Tag <hrencoded>...</hrencoded> versehen wurde.
225    * 
226    * Letzteres dient insbesondere dazu die indizierten Mail-Adressen in der Volltextsuche zu kennzeichnen.
227    * Diese werden dekodiert indiziert, damit die Volltextsuche diese berücksichtigen kann,
228    * aber kodiert in den Quelltext geschrieben.
229    * 
230    * Darüber hinaus werden Mail-Adressen, die im Linktext eines a-Tags vorkommen, ebenfalls mit dem Tag
231    * gekennzeichnet, damit diese hier leichter wieder dekodiert werden können.
232    */
233   static decryptMailAddresses()
234   {
235      // Mailadressen im href von Links dekodieren.
236      Array.from(document.querySelectorAll("a[data-encrypted]")).forEach(match => { 
237         if (match.href.indexOf('mailto:') >= 0)
238         {
239            const mailaddress = match.href.substring(match.href.indexOf('mailto:') + 7, match.href.length).trim();
240            const decryptedMailaddress = this.hrDecrypt(mailaddress);
241            match.href = `mailto:${decryptedMailaddress}`;
242            match.removeAttribute('data-encrypted');
243            if (mailaddress == match.innerHTML.trim())
244               match.innerHTML = decryptedMailaddress;
245         }
246      });
247      
248      // Mailadressen im Tag <hrencrypted>...</hrencrypted> dekodieren.
249      Array.from(document.querySelectorAll("hrencrypted")).forEac
249h(match => {
250         const mailaddress = match.innerHTML.trim();
251         const decryptedMailaddress = this.hrDecrypt(mailaddress);
252         
253         // Das spezielle Tag wird durch die dekodierte Mail als Textknoten ersetzt.
254         match.parentNode.replaceChild(document.createTextNode(decryptedMailaddress), match);
255      });
256   }
257   
258   /**
259    * Erzeugt eine v4-UUID.
260    * 
261    * Idee aus: https://stackoverflow.com/questions/105034/how-do-i-create-a-guid-uuid?page=1&tab=scoredesc#tab-top
262    * 
263    * @return eine v4-UUID oder die aktuellen Millisekunden seit 1.1.1970, falls ein Fehler bei der Generierung auftritt.
264    */
265   static getUUID()
266   {
267      try
268      {
269         // Die Methode ist nur in sicherem Context, d.h. localhost:8080 
270         // oder in Verbindungen über HTTPS nutzbar. Außerhalb dieses Contexts wird eine
271         // alternative Erzeugung gemacht.
272         if (typeof(Crypto.randomUUID) === 'function')
273            return Crypto.randomUUID();
274         else
275         {
276            return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
277              (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
278            );
279         }
280      }
281      catch (e)
282      {
283         if (typeof(HRLogError) === 'function')
284            HRLogError(e);
285         
286         return Math.floor(Math.random() * 1000) + '-' + new Date().getTime();  // Schwacher Ersatz
287      }
288      
289      return null;
290   }
291}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.