Vigenère cipher implementation
June 17, 2020
A note about go implementation of Vigenère cipher.
Go code from Get programming with Go:
func decipher() {
cipherText := "CSOITEUIWUIZNSROCNKFD"
keyword := "GOLANG"
message := ""
keyIndex := 0
for i := 0; i < len(cipherText); i++ {
// A=0, B=1, ... Z=25
c := cipherText[i] - 'A'
k := keyword[keyIndex] - 'A'
// cipher letter - key letter
c = (c-k+26)%26 + 'A'
message += string(c)
// increment keyIndex
keyIndex++
keyIndex %= len(keyword)
}
fmt.Println(message)
}Since I’m such a loser who couldn’t grasp this piece of code at first glance, I need to write it down to harden my memorize. As you can see, My ad-hoc solution below is rather straightforward, it simply use the keyword to divide ciphertext to get exact number of times that capable of using whole keyword to decrypt ciphertext; after that, use partial keyword to decrypt what is left from ciphertext accordingly. But it can’t satisfy its original requirements.
Cause both ciphertext and keyword were consiste of Capitalize Character, c := cipherText[i] - 'A' and k := keyword[keyIndex] - 'A' set ciphertext and keyword to A=0, B=1, ... Z=25 format respectively. Now, procced to decipher. code c - k litreally stands for shift c back by k. While (c - k + 26) % 26 in whole is to deal with situation when a given character is subpass maximum character which is Z, then cipher need to wrap back.
When difference bewteen
candfis no more than 26,(c - k + 26) % 26is equal to literal result ofc-z.When difference bewteen
candfis surpass 26, say it’s 28, then it needs wrap back, simplist way is to subtract 26 from it, but it will need an if condition to branch such a situation. What(c - k + 26) % 26actually mean is(c' - k' + 26 + 26) % 26, so it’s actually doing a wrap back.
In the case of 28, what we really want to get is 28 - 26 = 2 . Place it into code is (2 + 26 + 26) % 26, hence we will get 2 from this code.
Same logic apply to keyIndex %= len(keyword):
Among execution, value of keyIndex after exection of keyIndex++ is from 0 all the way to length of keyword. What keyIndex %= len(keyword) do is keep keyIndex at a iteration of 0, 1, 2, 3, 4, 5, 0, 1 … till the end of ciphertext.
My ad-hoc code:
func decipher() {
cipherText := "CSOITEUIWUIZNSROCNKFD"
keyword := "GOLANG"
message := ""
whole := len(cipherText) / len(keyword)
i := 0
for ; i < whole*len(keyword); i += 6 {
for j := 0; j < len(keyword); j++ {
// fmt.Printf("%c %c\n", cipherText[j+i], keyword[j])
p := int(cipherText[j+i]) - int(keyword[j]) + int('A')
if p < 'A' {
p += 26
}
fmt.Printf("%c %c %c\n", cipherText[j+i], keyword[j], p)
message = message + fmt.Sprintf("%c", p)
}
fmt.Println("")
}
for j := 0; j < len(keyword); j++ {
if i+j < len(cipherText) {
// fmt.Printf("%c %c\n", cipherText[i+j], keyword[j])
p := int(cipherText[i+j]) - int(keyword[j]) + int('A')
if p < 'A' {
p += 26
}
fmt.Printf("%c %c %c\n", cipherText[i+j], keyword[j], p)
message = message + fmt.Sprintf("%c", p)
}
}
fmt.Println(message)
}After analysis of the decipher process, the cipher process is just the reverse computation of the decipher code.
Here is my cipher code:
package main
import (
"fmt"
"strings"
)
func main() {
plainText := "your message goes here"
keyword := "GOLANG"
plainText = strings.Replace(plainText, " ", "", -1)
plainText = strings.ToUpper(plainText)
message := ""
keyIndex := 0
for i := 0; i < len(plainText); i++ {
fmt.Printf("%c %v\n", plainText[i], keyIndex)
p := plainText[i] - 'A' // [1]
k := keyword[keyIndex] - 'A' // [2]
c := (p+k+26)%26 + 'A' // [3]
keyIndex++
keyIndex %= len(keyword)
message += string(c)
}
fmt.Printf("%v\n", message)
}Line [1] and Line [2] shift plaintext and keyword in a format like A=0, B=1, ... Z=25. Line [3] encrypt plaintext by using keyword, and plus 'A' to shift it back to original ascii format.
Result:
$ go run cipher.go
Y 0
O 1
U 2
R 3
M 4
E 5
S 0
S 1
A 2
G 3
E 4
G 5
O 0
E 1
S 2
H 3
E 4
R 5
E 0
ECFRZKYGLGRMUSDHRXKWritten by nnfewl, a noob. Follow me on Twitter