package cipher import ( "regexp" "strings" ) // Cipher is an interface for all ciphers type Cipher interface { Encode(string) string Decode(string) string } // ShiftCipher is a cipher that shifts all letters a fixed distance type ShiftCipher struct { width int } // NewShift returns a new ShiftCipher func NewShift(w int) *ShiftCipher { if w == 0 || w < -25 || w > 25 { return nil } c := new(ShiftCipher) c.width = w return c } // Encode encodes a string using the current ShiftCipher func (c *ShiftCipher) Encode(s string) string { var ret string s = strings.ToLower(s) re := regexp.MustCompile("[^a-z]") s = re.ReplaceAllString(s, "") for i := range s { newChar := s[i] + byte(c.width) if newChar < 'a' { newChar = 'z' - ('a' - newChar) + 1 } if newChar > 'z' { newChar = 'a' + (newChar - 'z') - 1 } ret = ret + string(newChar) } return ret } // Decode decodes a string using the current ShiftCipher func (c *ShiftCipher) Decode(s string) string { var ret string s = strings.ToLower(s) re := regexp.MustCompile("[^a-z]") s = re.ReplaceAllString(s, "") for i := range s { newChar := s[i] - byte(c.width) if newChar < 'a' { newChar = 'z' - ('a' - newChar) + 1 } if newChar > 'z' { newChar = 'a' + (newChar - 'z') - 1 } ret = ret + string(newChar) } return ret } // A CeasarCipher is a ShiftCipher, just hardcoded at 3 type CeasarCipher struct { c *ShiftCipher } // NewCaesar creates a new CaesarCipher func NewCaesar() *CeasarCipher { c := new(CeasarCipher) c.c = NewShift(3) return c } // Encode just calls the shift cipher in the caesar cipher func (c *CeasarCipher) Encode(s string) string { return c.c.Encode(s) } // Decode just calls the shift cipher in the caesar cipher func (c *CeasarCipher) Decode(s string) string { return c.c.Decode(s) } // VigenereCipher a cipher where each character can have a different shift width type VigenereCipher struct { key string } // Encode encodes the given string func (c *VigenereCipher) Encode(s string) string { var ret string s = strings.ToLower(s) re := regexp.MustCompile("[^a-z]") s = re.ReplaceAllString(s, "") for i := range s { keyChar := c.key[i%len(c.key)] - 'a' newChar := s[i] + keyChar if newChar < 'a' { newChar = 'z' - ('a' - newChar) + 1 } if newChar > 'z' { newChar = 'a' + (newChar - 'z') - 1 } ret = ret + string(newChar) } return ret } // Decode decodes the given string func (c *VigenereCipher) Decode(s string) string { var ret string s = strings.ToLower(s) re := regexp.MustCompile("[^a-z]") s = re.ReplaceAllString(s, "") for i := range s { keyChar := c.key[i%len(c.key)] - 'a' newChar := s[i] - keyChar if newChar < 'a' { newChar = 'z' - ('a' - newChar) + 1 } if newChar > 'z' { newChar = 'a' + (newChar - 'z') - 1 } ret = ret + string(newChar) } return ret } // NewVigenere returns a new Vigenere Cipher func NewVigenere(key string) *VigenereCipher { re := regexp.MustCompile("[^a-z]") if len(key) < 3 || re.MatchString(key) { return nil } c := new(VigenereCipher) c.key = key return c }