Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
344
Task/One-time-pad/Go/one-time-pad.go
Normal file
344
Task/One-time-pad/Go/one-time-pad.go
Normal file
|
|
@ -0,0 +1,344 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/big"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
const (
|
||||
charsPerLine = 48
|
||||
chunkSize = 6
|
||||
cols = 8
|
||||
demo = true // would normally be set to false
|
||||
)
|
||||
|
||||
type fileType int
|
||||
|
||||
const (
|
||||
otp fileType = iota
|
||||
enc
|
||||
dec
|
||||
)
|
||||
|
||||
var scnr = bufio.NewScanner(os.Stdin)
|
||||
|
||||
func check(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func toAlpha(s string) string {
|
||||
var filtered []rune
|
||||
for _, r := range s {
|
||||
if unicode.IsUpper(r) {
|
||||
filtered = append(filtered, r)
|
||||
}
|
||||
}
|
||||
return string(filtered)
|
||||
}
|
||||
|
||||
func isOtpRelated(s string) bool {
|
||||
return strings.HasSuffix(s, ".1tp") || strings.HasSuffix(s, "1tp_cpy") ||
|
||||
strings.HasSuffix(s, ".1tp_enc") || strings.HasSuffix(s, "1tp_dec")
|
||||
}
|
||||
|
||||
func makePad(nLines int) string {
|
||||
nChars := nLines * charsPerLine
|
||||
bytes := make([]byte, nChars)
|
||||
/* generate random upper case letters */
|
||||
max := big.NewInt(26)
|
||||
for i := 0; i < nChars; i++ {
|
||||
n, err := rand.Int(rand.Reader, max)
|
||||
check(err)
|
||||
bytes[i] = byte(65 + n.Uint64())
|
||||
}
|
||||
return inChunks(string(bytes), nLines, otp)
|
||||
}
|
||||
|
||||
func vigenere(text, key string, encrypt bool) string {
|
||||
bytes := make([]byte, len(text))
|
||||
var ci byte
|
||||
for i, c := range text {
|
||||
if encrypt {
|
||||
ci = (byte(c) + key[i] - 130) % 26
|
||||
} else {
|
||||
ci = (byte(c) + 26 - key[i]) % 26
|
||||
}
|
||||
bytes[i] = ci + 65
|
||||
}
|
||||
temp := len(bytes) % charsPerLine
|
||||
if temp > 0 { // pad with random characters so each line is a full one
|
||||
max := big.NewInt(26)
|
||||
for i := temp; i < charsPerLine; i++ {
|
||||
n, err := rand.Int(rand.Reader, max)
|
||||
check(err)
|
||||
bytes = append(bytes, byte(65+n.Uint64()))
|
||||
}
|
||||
}
|
||||
ft := enc
|
||||
if !encrypt {
|
||||
ft = dec
|
||||
}
|
||||
return inChunks(string(bytes), len(bytes)/charsPerLine, ft)
|
||||
}
|
||||
|
||||
func inChunks(s string, nLines int, ft fileType) string {
|
||||
nChunks := len(s) / chunkSize
|
||||
remainder := len(s) % chunkSize
|
||||
chunks := make([]string, nChunks)
|
||||
for i := 0; i < nChunks; i++ {
|
||||
chunks[i] = s[i*chunkSize : (i+1)*chunkSize]
|
||||
}
|
||||
if remainder > 0 {
|
||||
chunks = append(chunks, s[nChunks*chunkSize:])
|
||||
}
|
||||
var sb strings.Builder
|
||||
for i := 0; i < nLines; i++ {
|
||||
j := i * cols
|
||||
sb.WriteString(" " + strings.Join(chunks[j:j+cols], " ") + "\n")
|
||||
}
|
||||
ss := " file\n" + sb.String()
|
||||
switch ft {
|
||||
case otp:
|
||||
return "# OTP" + ss
|
||||
case enc:
|
||||
return "# Encrypted" + ss
|
||||
default: // case dec:
|
||||
return "# Decrypted" + ss
|
||||
}
|
||||
}
|
||||
|
||||
func menu() int {
|
||||
fmt.Println(`
|
||||
1. Create one time pad file.
|
||||
|
||||
2. Delete one time pad file.
|
||||
|
||||
3. List one time pad files.
|
||||
|
||||
4. Encrypt plain text.
|
||||
|
||||
5. Decrypt cipher text.
|
||||
|
||||
6. Quit program.
|
||||
`)
|
||||
choice := 0
|
||||
for choice < 1 || choice > 6 {
|
||||
fmt.Print("Your choice (1 to 6) : ")
|
||||
scnr.Scan()
|
||||
choice, _ = strconv.Atoi(scnr.Text())
|
||||
check(scnr.Err())
|
||||
}
|
||||
return choice
|
||||
}
|
||||
|
||||
func main() {
|
||||
for {
|
||||
choice := menu()
|
||||
fmt.Println()
|
||||
switch choice {
|
||||
case 1: // Create OTP
|
||||
fmt.Println("Note that encrypted lines always contain 48 characters.\n")
|
||||
fmt.Print("OTP file name to create (without extension) : ")
|
||||
scnr.Scan()
|
||||
fileName := scnr.Text() + ".1tp"
|
||||
nLines := 0
|
||||
for nLines < 1 || nLines > 1000 {
|
||||
fmt.Print("Number of lines in OTP (max 1000) : ")
|
||||
scnr.Scan()
|
||||
nLines, _ = strconv.Atoi(scnr.Text())
|
||||
}
|
||||
check(scnr.Err())
|
||||
key := makePad(nLines)
|
||||
file, err := os.Create(fileName)
|
||||
check(err)
|
||||
_, err = file.WriteString(key)
|
||||
check(err)
|
||||
file.Close()
|
||||
fmt.Printf("\n'%s' has been created in the current directory.\n", fileName)
|
||||
if demo {
|
||||
// a copy of the OTP file would normally be on a different machine
|
||||
fileName2 := fileName + "_cpy" // copy for decryption
|
||||
file, err := os.Create(fileName2)
|
||||
check(err)
|
||||
_, err = file.WriteString(key)
|
||||
check(err)
|
||||
file.Close()
|
||||
fmt.Printf("'%s' has been created in the current directory.\n", fileName2)
|
||||
fmt.Println("\nThe contents of these files are :\n")
|
||||
fmt.Println(key)
|
||||
}
|
||||
case 2: // Delete OTP
|
||||
fmt.Println("Note that this will also delete ALL associated files.\n")
|
||||
fmt.Print("OTP file name to delete (without extension) : ")
|
||||
scnr.Scan()
|
||||
toDelete1 := scnr.Text() + ".1tp"
|
||||
check(scnr.Err())
|
||||
toDelete2 := toDelete1 + "_cpy"
|
||||
toDelete3 := toDelete1 + "_enc"
|
||||
toDelete4 := toDelete1 + "_dec"
|
||||
allToDelete := []string{toDelete1, toDelete2, toDelete3, toDelete4}
|
||||
deleted := 0
|
||||
fmt.Println()
|
||||
for _, name := range allToDelete {
|
||||
if _, err := os.Stat(name); !os.IsNotExist(err) {
|
||||
err = os.Remove(name)
|
||||
check(err)
|
||||
deleted++
|
||||
fmt.Printf("'%s' has been deleted from the current directory.\n", name)
|
||||
}
|
||||
}
|
||||
if deleted == 0 {
|
||||
fmt.Println("There are no files to delete.")
|
||||
}
|
||||
case 3: // List OTPs
|
||||
fmt.Println("The OTP (and related) files in the current directory are:\n")
|
||||
files, err := ioutil.ReadDir(".") // already sorted by file name
|
||||
check(err)
|
||||
for _, fi := range files {
|
||||
name := fi.Name()
|
||||
if !fi.IsDir() && isOtpRelated(name) {
|
||||
fmt.Println(name)
|
||||
}
|
||||
}
|
||||
case 4: // Encrypt
|
||||
fmt.Print("OTP file name to use (without extension) : ")
|
||||
scnr.Scan()
|
||||
keyFile := scnr.Text() + ".1tp"
|
||||
if _, err := os.Stat(keyFile); !os.IsNotExist(err) {
|
||||
file, err := os.Open(keyFile)
|
||||
check(err)
|
||||
bytes, err := ioutil.ReadAll(file)
|
||||
check(err)
|
||||
file.Close()
|
||||
lines := strings.Split(string(bytes), "\n")
|
||||
le := len(lines)
|
||||
first := le
|
||||
for i := 0; i < le; i++ {
|
||||
if strings.HasPrefix(lines[i], " ") {
|
||||
first = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if first == le {
|
||||
fmt.Println("\nThat file has no unused lines.")
|
||||
continue
|
||||
}
|
||||
lines2 := lines[first:] // get rid of comments and used lines
|
||||
|
||||
fmt.Println("Text to encrypt :-\n")
|
||||
scnr.Scan()
|
||||
text := toAlpha(strings.ToUpper(scnr.Text()))
|
||||
check(scnr.Err())
|
||||
tl := len(text)
|
||||
nLines := tl / charsPerLine
|
||||
if tl%charsPerLine > 0 {
|
||||
nLines++
|
||||
}
|
||||
if len(lines2) >= nLines {
|
||||
key := toAlpha(strings.Join(lines2[0:nLines], ""))
|
||||
encrypted := vigenere(text, key, true)
|
||||
encFile := keyFile + "_enc"
|
||||
file2, err := os.Create(encFile)
|
||||
check(err)
|
||||
_, err = file2.WriteString(encrypted)
|
||||
check(err)
|
||||
file2.Close()
|
||||
fmt.Printf("\n'%s' has been created in the current directory.\n", encFile)
|
||||
for i := first; i < first+nLines; i++ {
|
||||
lines[i] = "-" + lines[i][1:]
|
||||
}
|
||||
file3, err := os.Create(keyFile)
|
||||
check(err)
|
||||
_, err = file3.WriteString(strings.Join(lines, "\n"))
|
||||
check(err)
|
||||
file3.Close()
|
||||
if demo {
|
||||
fmt.Println("\nThe contents of the encrypted file are :\n")
|
||||
fmt.Println(encrypted)
|
||||
}
|
||||
} else {
|
||||
fmt.Println("Not enough lines left in that file to do encryption.")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("\nThat file does not exist.")
|
||||
}
|
||||
case 5: // Decrypt
|
||||
fmt.Print("OTP file name to use (without extension) : ")
|
||||
scnr.Scan()
|
||||
keyFile := scnr.Text() + ".1tp_cpy"
|
||||
check(scnr.Err())
|
||||
if _, err := os.Stat(keyFile); !os.IsNotExist(err) {
|
||||
file, err := os.Open(keyFile)
|
||||
check(err)
|
||||
bytes, err := ioutil.ReadAll(file)
|
||||
check(err)
|
||||
file.Close()
|
||||
keyLines := strings.Split(string(bytes), "\n")
|
||||
le := len(keyLines)
|
||||
first := le
|
||||
for i := 0; i < le; i++ {
|
||||
if strings.HasPrefix(keyLines[i], " ") {
|
||||
first = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if first == le {
|
||||
fmt.Println("\nThat file has no unused lines.")
|
||||
continue
|
||||
}
|
||||
keyLines2 := keyLines[first:] // get rid of comments and used lines
|
||||
|
||||
encFile := keyFile[0:len(keyFile)-3] + "enc"
|
||||
if _, err := os.Stat(encFile); !os.IsNotExist(err) {
|
||||
file2, err := os.Open(encFile)
|
||||
check(err)
|
||||
bytes, err := ioutil.ReadAll(file2)
|
||||
check(err)
|
||||
file2.Close()
|
||||
encLines := strings.Split(string(bytes), "\n")[1:] // exclude comment line
|
||||
nLines := len(encLines)
|
||||
if len(keyLines2) >= nLines {
|
||||
encrypted := toAlpha(strings.Join(encLines, ""))
|
||||
key := toAlpha(strings.Join(keyLines2[0:nLines], ""))
|
||||
decrypted := vigenere(encrypted, key, false)
|
||||
decFile := keyFile[0:len(keyFile)-3] + "dec"
|
||||
file3, err := os.Create(decFile)
|
||||
check(err)
|
||||
_, err = file3.WriteString(decrypted)
|
||||
check(err)
|
||||
file3.Close()
|
||||
fmt.Printf("\n'%s' has been created in the current directory.\n", decFile)
|
||||
for i := first; i < first+nLines; i++ {
|
||||
keyLines[i] = "-" + keyLines[i][1:]
|
||||
}
|
||||
file4, err := os.Create(keyFile)
|
||||
check(err)
|
||||
_, err = file4.WriteString(strings.Join(keyLines, "\n"))
|
||||
check(err)
|
||||
file4.Close()
|
||||
if demo {
|
||||
fmt.Println("\nThe contents of the decrypted file are :\n")
|
||||
fmt.Println(decrypted)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fmt.Println("Not enough lines left in that file to do decryption.")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("\nThat file does not exist.")
|
||||
}
|
||||
case 6: // Quit program
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue