181 lines
4.1 KiB
Go
181 lines
4.1 KiB
Go
/*
|
|
Only use ASCII letters between A and Z or the Characters in square... . If the row with 'J' is removed from the squares,
|
|
then the square is a 'Polybios square' and you must use removeSpaceI(text) to encrypt and decrypt
|
|
*/
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
var (
|
|
squareRosetta [][]byte = [][]byte{ //rosettacode
|
|
{'A', 'B', 'C', 'D', 'E'},
|
|
{'F', 'G', 'H', 'I', 'K'},
|
|
{'L', 'M', 'N', 'O', 'P'},
|
|
{'Q', 'R', 'S', 'T', 'U'},
|
|
{'V', 'W', 'X', 'Y', 'Z'},
|
|
{'J', '1', '2', '3', '4'},
|
|
}
|
|
|
|
squareWikipedia [][]byte = [][]byte{ // wikipedia
|
|
|
|
{'B', 'G', 'W', 'K', 'Z'},
|
|
{'Q', 'P', 'N', 'D', 'S'},
|
|
{'I', 'O', 'A', 'X', 'E'},
|
|
{'F', 'C', 'L', 'U', 'M'},
|
|
{'T', 'H', 'Y', 'V', 'R'},
|
|
{'J', '1', '2', '3', '4'},
|
|
}
|
|
|
|
textRosetta string = "0ATTACKATDAWN"
|
|
textRosettaEncoded string = "DQBDAXDQPDQH" // only for test
|
|
textWikipedia string = "FLEEATONCE"
|
|
textWikipediaEncoded string = "UAEOLWRINS" // only for test
|
|
textTest string = "The invasion will start on the first of January"
|
|
textTextEncoded string = "RASOAQXFIOORXESXADETSWLTNIAZQOISBRGBALY" // only for test
|
|
)
|
|
|
|
type koord struct {
|
|
X byte
|
|
Y byte
|
|
}
|
|
|
|
func (k *koord) LessThen(other *koord) bool {
|
|
if k.Y > other.Y {
|
|
return false
|
|
}
|
|
if k.Y < other.Y {
|
|
return true
|
|
}
|
|
if k.X < other.X {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (k *koord) EqualTo(other koord) bool {
|
|
if k.X == other.X && k.Y == other.Y {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
var encryptMap map[byte]koord
|
|
var decryptMap map[koord]byte
|
|
|
|
func squareToMaps(square [][]byte) (map[byte]koord, map[koord]byte) {
|
|
eMap := make(map[byte]koord)
|
|
dMap := make(map[koord]byte)
|
|
for x, col := range square {
|
|
for y, v := range col {
|
|
eMap[v] = koord{byte(x), byte(y)}
|
|
dMap[koord{byte(x), byte(y)}] = v
|
|
|
|
}
|
|
}
|
|
return eMap, dMap
|
|
}
|
|
|
|
func removeSpaceI(text string) string {
|
|
var n string
|
|
s := strings.ToUpper(text)
|
|
for _, b := range []byte(s) {
|
|
//use only ASCII Characters from A to Z
|
|
if b < 'A' || b > 'Z' {
|
|
continue
|
|
}
|
|
if b == 'J' {
|
|
b = 'I'
|
|
}
|
|
n = n + string(b)
|
|
}
|
|
return n
|
|
}
|
|
|
|
func removeSpace(text string, square map[byte]koord) string {
|
|
var n string
|
|
//to UpperCase and then remove all Spaces an Characters witch are not in square
|
|
s := strings.ReplaceAll(strings.ToUpper(text), " ", "")
|
|
for _, b := range []byte(s) {
|
|
_, ok := square[b]
|
|
if ok {
|
|
n = n + string(b)
|
|
}
|
|
}
|
|
return n
|
|
}
|
|
|
|
func encrypt(text string, emap map[byte]koord, dmap map[koord]byte) string {
|
|
text = removeSpace(text, emap)
|
|
var row0, row1 []byte
|
|
for _, b := range []byte(text) {
|
|
xy := emap[b]
|
|
row0 = append(row0, xy.X)
|
|
row1 = append(row1, xy.Y)
|
|
}
|
|
row0 = append(row0, row1...)
|
|
|
|
var s string
|
|
for i := 0; i < len(row0); i += 2 {
|
|
s = s + string(dmap[koord{row0[i], row0[i+1]}])
|
|
}
|
|
return s
|
|
}
|
|
|
|
func decrypt(text string, emap map[byte]koord, dmap map[koord]byte) string {
|
|
text = removeSpace(text, emap)
|
|
k := make([]koord, len(text))
|
|
|
|
for i, b := range []byte(text) {
|
|
k[i] = emap[b]
|
|
}
|
|
|
|
kl := make([]byte, len(k)*2)
|
|
i := int(0)
|
|
for _, ki := range k {
|
|
kl[i] = ki.X
|
|
kl[i+1] = ki.Y
|
|
i += 2
|
|
}
|
|
l := len(kl) / 2
|
|
k1 := kl[:l]
|
|
k2 := kl[l:]
|
|
var s string
|
|
|
|
for i := 0; i < l; i++ {
|
|
s = s + string(dmap[koord{k1[i], k2[i]}])
|
|
}
|
|
return s
|
|
}
|
|
|
|
func main() {
|
|
|
|
encryptMap, decryptMap = squareToMaps(squareRosetta)
|
|
fmt.Println("from Rosettacode")
|
|
fmt.Println("original:\t", textRosetta)
|
|
s := encrypt(textRosetta, encryptMap, decryptMap)
|
|
fmt.Println("codiert:\t", s)
|
|
s = decrypt(s, encryptMap, decryptMap)
|
|
fmt.Println("and back:\t", s)
|
|
|
|
fmt.Println("from Wikipedia")
|
|
encryptMap, decryptMap = squareToMaps(squareWikipedia)
|
|
fmt.Println("original:\t", textWikipedia)
|
|
s = encrypt(textWikipedia, encryptMap, decryptMap)
|
|
fmt.Println("codiert:\t", s)
|
|
s = decrypt(s, encryptMap, decryptMap)
|
|
fmt.Println("and back:\t", s)
|
|
|
|
encryptMap, decryptMap = squareToMaps(squareWikipedia)
|
|
fmt.Println("from Rosettacode long part")
|
|
fmt.Println("original:\t", textTest)
|
|
s = encrypt(textTest, encryptMap, decryptMap)
|
|
fmt.Println("codiert:\t", s)
|
|
// Wenn der Text eine ungerade Anzahl Buchstaben hat, funktioniert der Algorithmus nicht!!!
|
|
s = decrypt(s, encryptMap, decryptMap)
|
|
fmt.Println("and back:\t", s)
|
|
|
|
}
|