Forum: PC-Programmierung Rot-n Algorithmus


von Johannes Lake (Gast)


Lesenswert?

Hallo Leute,

ich bin auf der Suche nach einem Quellcode für einen Rot-n Algorithmus 
ausgelegt für die Asciizeichen im Bereich 33 bis 126.

Meine bisherige Lösung implementiert lediglich Rot47. Aktuell mache ich 
damit eine Text unlesbar. Nun würde ich jedoch gerne die Funktion 
dahingehend erweitern, dass wenn an einer bestimmten Stelle eine Zahl 
zwischen 1 und 47 auftaucht, der Text um die besagte Zahl verschoben 
wird.

Aktuelle programmiere ich in Visual Basic aber wenn ihr zufällig nen 
passenden Codesnippet rumfliegen habt würde ich mich sehr über den Code 
freuen, unabhängig von der Sprache (jedenfalls was die geläufigsten 
angeht ;)).

Schönen Sonntag noch,
J.L.

von Markus M. (mark_m)


Lesenswert?

Du meinst sich die "rotate by n" oder Caesar-Verschlüsselung.

Du addierst einfach n auf deinen Asciiwert und beim Überschreiten der 
Bereichsgrenzen fügst du eine Sonderbehandlung ein. Dafür kannst du den 
Modulo-Operator nutzen.

Notiere dir mal die Rahmenbedingungen auf einen Zettel und du wirst 
schnell zu einer Lösung gelangen.

Grüsse

von Yalu X. (yalu) (Moderator)


Lesenswert?

Wenn du ROT47 schon hast, wo liegt dann das Problem, das Verfahren für
andere n umzusetzen?

von Johannes Lake (Gast)


Lesenswert?

Ich bin nur etwas verwirrt wegen der Grenzen und dem Modulo.

Mein Bisheriger Code sieht folgerndermaßen aus und klappt auch ohne 
dergleichen:
1
    Public Function encode(strInput As String, n As Integer)
2
        Dim i As Integer
3
        Dim strOutput As String
4
        For i = 1 To Len(strInput)
5
            strOutput = strOutput & Chr((Asc(Mid(strInput, i, 1)) + n))
6
        Next i
7
        encode = strOutput
8
    End Function
9
10
    Public Function decode(strInput As String, n As Integer)
11
        Dim i As Integer
12
        Dim strOutput As String
13
        For i = 1 To Len(strInput)
14
            strOutput = strOutput & Chr((Asc(Mid(strInput, i, 1)) - n))
15
        Next i
16
        decode = strOutput
17
    End Function

von Johannes Lake (Gast)


Lesenswert?

Oh, ich seh gerade das mein Verschlüsseln auch Zeichen außerhalb des 
Bereiches vorkommen. Das soll natürlich nicht! ;)

von Johannes Lake (Gast)


Lesenswert?

Könnte mir da evtl noch jemand auf die Sprünge helfen?

von Markus M. (mark_m)


Lesenswert?

Dein Bereich liegt zwischen 33 und 126 bzw. '!' und '~'.

Bei der Verschlüsselung wird der Wert > 126, dass musst du behandeln.

Bei der Entschlüsselung wird der Wert < 33, dass musst Du ebenfalls 
behandeln.

Warum verwendest Du '&'? Ist dieses den kein logischer Operator? Den 
Zusammenhang verstehe ich hier nicht.

Grüsse

von Sven P. (Gast)


Lesenswert?

Markus M. schrieb:
> Warum verwendest Du '&'? Ist dieses den kein logischer Operator? Den
> Zusammenhang verstehe ich hier nicht.
Das ist in Basic der Zeichenketten-Verkettungsoperator.

Wenn ich mich recht entsinne, darf in Visual Basic die Mid()-Funktion 
als Mid-Anweisung auch als l-value stehen, sodass man direkt zuweisen 
kann.
1
Mid(s$, i, 1) = Chr(Asc(Mid(s$, i, 1)) + n)

von Johannes Lake (Gast)


Lesenswert?

Die Frage zu dem &-Opertaor wurde ja bereits erklärt daher
habe ich jetzt mal versucht den Code anzupassen aber es will noch nicht.

Ich möchte im Bereich von 1  bis 47 verschieben, daher komme ich 
zwischen 'p' über die '~' möglicherweise über die grenzen und 
sicherstellen das er beim Verschlüsseln ein Zeichen >32 daraus macht.
Mein Code sieht jetzt wie folgt aus.
1
    Public Function encode(strInput As String, n As Integer)
2
        Dim i, asciidec As Integer
3
        Dim strOutput As String
4
        For i = 1 To Len(strInput)
5
            asciidec = Asc(Mid(strInput, i, 1))
6
            'strOutput = strOutput & Chr(asciidec + n))
7
            If asciidec >= 80 And asciidec <= 126 Then
8
                strOutput = strOutput & Chr(32 + ((asciidec + n) Mod 126))
9
            Else
10
                strOutput = strOutput & Chr(asciidec + n)
11
            End If
12
        Next i
13
        encode = strOutput
14
    End Function
15
16
    Public Function decode(strInput As String, n As Integer)
17
        Dim i, asciidec As Integer
18
        Dim strOutput As String
19
        For i = 1 To Len(strInput)
20
            asciidec = Asc(Mid(strInput, i, 1))
21
            'strOutput = strOutput & Chr(asciidec - n))
22
            If asciidec >= 80 And asciidec <= 126 Then
23
                strOutput = strOutput & Chr(32 + ((asciidec + n) Mod 126))
24
            Else
25
                strOutput = strOutput & Chr(asciidec + n)
26
            End If
27
        Next i
28
        decode = strOutput
29
    End Function

Aber wenn ich die Rotation-n verändere hab ich wieder Chaos.

von Markus M. (mark_m)


Lesenswert?

Ist doch klar, dass es Chaos gibt Du gibt die Grenzen mit 80 und 126 
vor. Gehst aber davon aus, das dein "Alphabet" bei 32 beginnt.

Was kommt heraus, wenn Du 32 durch 80 ersetzt oder äquivalent 80 durch 
32?

Ausserdem sollte der Inputwert immer innerhalb der Grenzen liegen. Das 
brauchst Du nicht zu prüfen. Denn umgekehrten Fall musst Du prüfen.

Range: 33 bis 126
if: (input + n) > 126  ->  (input + n + 33 ) - 125  - 1

Grüsse

von Johannes Lake (Gast)


Lesenswert?

Dann kommt auch nur Blödsinn raus. Alles was nicht in den Grenzen ist 
(ausgehend davon das auch nur auch nur Zeichen verschlüsselt werden die 
in dem Bereich 33-126 liegen) wird ja mit dem ELSE-Zweig abgefangen und 
um n erhöht.

von Markus M. (mark_m)


Lesenswert?

In C sieht die Verschlüsselung für einen Buchstaben, für ein beliebiges 
n, so aus:
1
#define MIN_ASCII 33
2
#define MAX_ASCII 126
3
4

5
6
char c += n;
7
    
8
if ( c > MAX_ASCII )
9
{  
10
    c = (c % MAX_ASCII) + MIN_ASCII - 1;
11
}

'%' ist der Modulo Operator.

Grüsse

von Johannes Lake (Gast)


Lesenswert?

Danke. Das Funktioniert wunderbar.
Könntest du mir auch noch verraten wie du das decodierts?
Zeichen -32 +126 - n ?

von Johannes Lake (Gast)


Lesenswert?

Mein Code sieht jetzt folgendermaßen aus:
1
    Public Function encode(strInput As String, n As Integer)
2
        Dim i, asciidec As Integer
3
        Dim strOutput As String
4
5
        For i = 1 To Len(strInput)
6
            asciidec = Asc(Mid(strInput, i, 1))
7
            asciidec = asciidec + n
8
            If asciidec > 126 Then
9
                asciidec = (asciidec Mod 126) + 32
10
            End If
11
            strOutput = strOutput & Chr(asciidec)
12
        Next i
13
        encode = strOutput
14
    End Function
15
16
    Public Function decode(strInput As String, n As Integer)
17
        Dim i, asciidec As Integer
18
        Dim strOutput As String
19
20
        For i = 1 To Len(strInput)
21
            asciidec = Asc(Mid(strInput, i, 1))
22
            If (asciidec < (126 - n)) Then
23
                asciidec = asciidec - 32
24
                asciidec = asciidec + 126
25
                asciidec = asciidec - n
26
            Else
27
                asciidec = asciidec - n
28
            End If
29
            strOutput = strOutput & Chr(asciidec)
30
        Next i
31
        decode = strOutput
32
    End Function

Die Verschlüsselung für n=47 klappt nur mit der Decodierung hapert es.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Johannes Lake schrieb:
>                asciidec = (asciidec Mod 126) + 32

Das 'Mod' kannst du hier auch durch ein '-' ersetzen, also
1
                asciidec = asciidec - 126 + 32

oder gleich
1
                asciidec = asciidec - 94

>            If (asciidec < (126 - n)) Then
>                asciidec = asciidec - 32
>                asciidec = asciidec + 126
>                asciidec = asciidec - n
>            Else
>                asciidec = asciidec - n
>            End If

Statt (126 - n) müsste in der obersten Zeile (33 + n) stehen.

Oder mach's einfach genauso wie bei encode, nur andersherum:
1
            asciidec = asciidec - n
2
            If asciidec < 33 Then
3
                asciidec = asciidec + 94
4
            End If

Gleiche oder sehr ähnliche Code-Abschnitte sind meist schlecht, weil
aufwendiger zu lesen und weniger wartungsfreundlich. Besser und noch
einfacher geht es so:
1
    Public Function decode(strInput As String, n As Integer)
2
        decode = encode(strInput, 94 - n)

von Johannes Lake (Gast)


Lesenswert?

Danke an alle. Hatte es gerade selber ans Laufen gekriegt aber mit den 
Optimierungstipps vom Vorredner ist es nochmal ein Stück sauberer 
geworden.
1
 Public Function encode(strInput As String, n As Integer)
2
        Dim i, asciidec As Integer
3
        Dim strOutput As String
4
5
        For i = 1 To Len(strInput)
6
            asciidec = Asc(Mid(strInput, i, 47))
7
            asciidec = asciidec + n
8
            If asciidec > 126 Then
9
                asciidec = asciidec - 94
10
            End If
11
            strOutput = strOutput & Chr(asciidec)
12
        Next i
13
        encode = strOutput
14
    End Function
15
16
    Public Function decode(strInput As String, n As Integer)
17
        Dim i, asciidec As Integer
18
        Dim strOutput As String
19
20
        For i = 1 To Len(strInput)
21
            asciidec = Asc(Mid(strInput, i, 1))
22
            asciidec = asciidec - n
23
            If asciidec < 33 Then
24
                asciidec = asciidec + 94
25
            End If
26
            strOutput = strOutput & Chr(asciidec)
27
        Next i
28
        decode = strOutput
29
    End Function

von Markus M. (mark_m)


Lesenswert?

> Das 'Mod' kannst du hier auch durch ein '-' ersetzen, also
Bei Verwendung von Modulo sind beliebige n bei der Verschlüsselung 
gültig. Z.B. Auch n = 555. Wieder eine Abfrage gespart. ;-)

Funktionssicherheit erhöht!

@ Johannes
Wenn Du jetzt noch die Zahlen durch sprechende Konstanten ersetzt, wird 
es nochmal ein Stück sauberer.

Grüsse

von Yalu X. (yalu) (Moderator)


Lesenswert?

Markus M. schrieb:
> Bei Verwendung von Modulo sind beliebige n bei der Verschlüsselung
> gültig.

Auch negative n? ;-)

von Markus M. (mark_m)


Lesenswert?

Dann etwas präziser: für n > 0

Grüsse

von Yalu X. (yalu) (Moderator)


Lesenswert?

Markus M. schrieb:
> Dann etwas präziser: für n > 0

Also doch eine Abfrage ;-)

Nee, du hast schon recht. Mod ist sicherer als nur eine Subtraktion, nur
eben noch nicht völlig sicher.

Gerade bei Integer-Divisionen und Modulo-Operationen muss man bei
negativen Operanden höllisch aufpassen, um keine Überraschungen zu
erleben. Zudem werden negative Operanden in verschiedenen Programmier-
sprachen unterschiedlich behandelt, leider meist so, wie man es nicht
erwartet ;-).

Nicht einmal innerhalb von Microsoft kann man sich auf eine einheitliche
Definition der Modulo-Funktion einigen, deswegen liefert das Visual-
Basic-Mod andere Ergebnisse als das Excel-Mod. Das ist für die Anwender
schwer nachvollziehbar, da VBS ja ein Bestandteil von Excel ist:

  http://support.microsoft.com/kb/141178

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.