1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Go】Goでヴィジュネル暗号を書いてみた

Last updated at Posted at 2025-01-10

概要

暗号技術入門 第3版で最初の方に出てくる暗号、ヴィジュネル暗号をGo実装してみた

サンプルコード

package main

import (
    "crypto/rand"
    "fmt"
    "strings"
    "unicode"
)

type VigenereCipher struct {
    Key string
}

func NewVigenereCipher(text string) VigenereCipher {
    return VigenereCipher{Key: generateRandomAlphaKey(len(text))}
}

func generateRandomAlphaKey(length int) string {
    const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    key := make([]byte, length)
    _, err := rand.Read(key)
    if err != nil {
       panic(err)
    }
    for i := 0; i < length; i++ {
       key[i] = charset[key[i]%byte(len(charset))]
    }
    return string(key)
}

func (vc VigenereCipher) EncryptText(text string) string {
    return vc.transformText(text, vc.encryptShift)
}

func (vc VigenereCipher) DecryptText(text string) string {
    return vc.transformText(text, vc.decryptShift)
}

func (vc VigenereCipher) transformText(text string, shiftFunc func(rune, rune, rune) rune) string {
    var result strings.Builder
    keyIndex := 0
    keyLength := len(vc.Key)

    for _, char := range text {
       if unicode.IsLetter(char) { // Unicode上で文字と分類される場合のみを暗号化の対象とする
          base := rune('A')
          if unicode.IsLower(char) { // 暗号化対象の文字が小文字の場合
             base = rune('a')
          }

          // 暗号化対象の文字に対するkeyを取得
          keyChar := rune(vc.Key[keyIndex])
          if unicode.IsLower(char) { // 暗号化対象の文字が小文字の場合、keyを小文字にする
             keyChar = unicode.ToLower(keyChar)
          } else { // 暗号化対象の文字が大文字の場合、keyを大文字にする
             keyChar = unicode.ToUpper(keyChar)
          }

          // 暗号化(復号化)
          newChar := shiftFunc(char, keyChar, base)
          result.WriteRune(newChar)

          keyIndex = (keyIndex + 1) % keyLength
       } else { // 文字以外は暗号化しない
          result.WriteRune(char)
       }
    }
    return result.String()
}

func (vc VigenereCipher) encryptShift(char, keyChar, base rune) rune {
    // ((暗号化対象の文字のオフセット) + (keyの文字のオフセット) + 負の値防止) % 0~25の範囲に収める + 実際の文字コードに戻す
    return ((char-base)+(keyChar-base)+26)%26 + base
}

func (vc VigenereCipher) decryptShift(char, keyChar, base rune) rune {
    return ((char-base)-(keyChar-base)+26)%26 + base
}

func main() {
    textToEncrypt := "Hello World"
    cipher := NewVigenereCipher(textToEncrypt)

    encrypted := cipher.EncryptText(textToEncrypt)
    decrypted := cipher.DecryptText(encrypted)

    fmt.Printf("Original Text: %s\n", textToEncrypt)
    fmt.Printf("Random Key: %s\n", cipher.Key)
    fmt.Printf("Encrypted: %s\n", encrypted)
    fmt.Printf("Decrypted: %s\n", decrypted)
}


// 出力
// Original Text: Hello World
// Random Key: ijPHFQVervo
// Encrypted: Pnast Mjvcy
// Decrypted: Hello World
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?