GoLang: SimpleCipher
Hello back again, Golang is just a new syntax for me. Even though behind the scenes they developers have simplified many things, for a consumer like me writing a program is more about learning the new syntax and getting familiarized with the control and stack.
In my constant quest to try something different, today I try and solve the simple cipher which by definition is a text replacement algorithm that makes the text a little difficult to break while reading with naked eyes.
SimpleCipher: Code available in GitHub
Version 1.0
The first version was a basic logic writing which allowed to check for the code and decode capability.
// Encrypt struct
type Encrypt struct {
distance int
key string
}
// NewCaesar Object that implements the interface Cipher
func NewCaesar() Cipher {
return Encrypt{distance: 3, key: ""}
}
// NewShift Object that implements the interface Cipher
func NewShift(distance int) Cipher {
// Corner case when of 0, 26, -26
if distance < -26 || distance > 26 || distance == 0 {
return nil
}
return Encrypt{distance, ""}
}
// NewVigenere Object that implements the interface Cipher
func NewVigenere(key string) Cipher {
if key == "" || checkKeyInvalid(key) {
return nil
}
return Encrypt{0, key}
}
// checkAllAs Checks for all A's in the key.
func checkKeyInvalid(s string) (f bool) {
// If any invalid character matches
if matched, _ := regexp.MatchString(`[^a-z]`, s); matched {
return true
}
for _, m := range s {
switch m {
case 'a':
f = true
default:
f = false
return
}
}
return
}
I also wrote a utility to remove all invalid character basically all the chars that were not either of A-Z or a-z.
// removeAllOtherCharcterBeforeEncoding replace all the other elements
func removeAllOtherCharcterBeforeEncoding(s string) (o string) {
o = RegularExp.ReplaceAllString(s, "")
log.Printf(" String: %s", o)
o = strings.ToLower(o)
return
}
var RegularExp = regexp.MustCompile(`[^A-Za-z]`)
The basic logic of transforming the input string to encoded string was written in these two functions below
func transformWithString(s string, e string, flag bool) string {
var sb strings.Builder
em := []rune(e)
for i, sm := range s {
// The key has to be repeated
var d rune = 0
if i < len(em) {
d = em[i] - 'a'
} else {
d = em[(i%len(em))] - 'a'
}
if flag {
switch {
case sm >= 'a' && sm <= 'z':
fmt.Fprintf(&sb, "%s", string('a'+(sm-'a'+d)%26))
}
} else {
switch {
case sm >= 'a' && sm <= 'z':
diff := ((sm - 'a' - d) % 26)
newChar := ""
if diff < 0 {
newChar = string('z' + diff + 1)
} else {
newChar = string('a' + diff)
}
fmt.Fprintf(&sb, "%s", newChar)
}
}
}
return sb.String()
}
// transformWithDistance Allows transformation based on distance.
func transformWithDistance(s string, d int) string {
rotateFunction := func(r rune) rune {
switch {
case r >= 'a' && r <= 'z':
val := (r - 'a' + rune(d))
if val < 0 && d < 0 {
return 'z' + ((val + 1) % 26)
}
return 'a' + (val % 26)
default:
log.Printf(" Not a charcter: %s", string(r))
}
return ' '
}
return strings.Map(rotateFunction, s)
}
The basic functions that invoke these encode and decode functions are as under
// Encode Implements the interface Cipher
func (e Encrypt) Encode(s string) (o string) {
o = ""
s = removeAllOtherCharcterBeforeEncoding(s)
if s == "" || len(s) <= 0 {
return
}
// Iterate throught the runes
switch {
case e.distance != 0:
o = strings.ReplaceAll(transformWithDistance(s, e.distance), " ", "")
default:
o = transformWithString(s, e.key, true)
}
return
}
// Decode decides the encrypted string
func (e Encrypt) Decode(s string) (o string) {
o = ""
log.Printf(" Decode: %s", s)
if s == "" || len(s) <= 0 {
return
}
switch {
case e.distance != 0:
log.Printf(" Distance: %d", e.distance)
o = transformWithDistance(s, -e.distance)
default:
o = transformWithString(s, e.key, false)
}
return
}
Now the general feeling after writing this was I have too much the same code that I should remove for example
- transformWithDistance
- transformWithString
They are essentially doing the same thing?
Version 2…. to follow soon.