70 lines
1.6 KiB
Go
70 lines
1.6 KiB
Go
package main
|
|
|
|
import "fmt"
|
|
|
|
type vkey string
|
|
|
|
func newVigenère(key string) (vkey, bool) {
|
|
v := vkey(upperOnly(key))
|
|
return v, len(v) > 0 // key length 0 invalid
|
|
}
|
|
|
|
func (k vkey) encipher(pt string) string {
|
|
ct := upperOnly(pt)
|
|
for i, c := range ct {
|
|
ct[i] = 'A' + (c-'A'+k[i%len(k)]-'A')%26
|
|
}
|
|
return string(ct)
|
|
}
|
|
|
|
func (k vkey) decipher(ct string) (string, bool) {
|
|
pt := make([]byte, len(ct))
|
|
for i := range pt {
|
|
c := ct[i]
|
|
if c < 'A' || c > 'Z' {
|
|
return "", false // invalid ciphertext
|
|
}
|
|
pt[i] = 'A' + (c-k[i%len(k)]+26)%26
|
|
}
|
|
return string(pt), true
|
|
}
|
|
|
|
// upperOnly extracts letters A-Z, a-z from a string and
|
|
// returns them all upper case in a byte slice.
|
|
// Useful for vkey constructor and encipher function.
|
|
func upperOnly(s string) []byte {
|
|
u := make([]byte, 0, len(s))
|
|
for i := 0; i < len(s); i++ {
|
|
c := s[i]
|
|
if c >= 'A' && c <= 'Z' {
|
|
u = append(u, c)
|
|
} else if c >= 'a' && c <= 'z' {
|
|
u = append(u, c-32)
|
|
}
|
|
}
|
|
return u
|
|
}
|
|
|
|
const testKey = "Vigenère Cipher"
|
|
const testPT = `Beware the Jabberwock, my son!
|
|
The jaws that bite, the claws that catch!`
|
|
|
|
func main() {
|
|
fmt.Println("Supplied key: ", testKey)
|
|
v, ok := newVigenère(testKey)
|
|
if !ok {
|
|
fmt.Println("Invalid key")
|
|
return
|
|
}
|
|
fmt.Println("Effective key:", v)
|
|
fmt.Println("Plain text:", testPT)
|
|
ct := v.encipher(testPT)
|
|
fmt.Println("Enciphered:", ct)
|
|
dt, ok := v.decipher(ct)
|
|
if !ok {
|
|
fmt.Println("Invalid ciphertext")
|
|
return
|
|
}
|
|
fmt.Println("Deciphered:", dt)
|
|
}
|