You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
numberstation/nsdecode.go

96 lines
2.5 KiB

package main
import (
"bufio"
"flag"
"fmt"
"io"
"os"
"strconv"
"strings"
"unicode"
)
// Function to decode number pairs into characters
func decodePair(pair string) rune {
alphabet := " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
num, err := strconv.Atoi(pair)
if err != nil || num < 0 || num >= len(alphabet) {
return rune(-1) // Return -1 if pair is not valid
}
return rune(alphabet[num])
}
// Function to apply the reverse shift and wrap around
func applyReverseShift(value, shift int) int {
shifted := (value - shift) % 37
if shifted < 0 {
shifted += 37
}
return shifted
}
func main() {
// Define command-line flags
shift := flag.Int("s", 0, "Shift amount for the cipher")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [options] <<< \"String\"\n", os.Args[0])
fmt.Fprintf(os.Stderr, " %s [options] < file.txt\n", os.Args[0])
fmt.Fprintf(os.Stderr, " echo \"string\" | %s [options]\n", os.Args[0])
fmt.Fprintf(os.Stderr, "\nDescription:\n")
fmt.Fprintf(os.Stderr, " A companion program to numberstation, intended to make easy work of decrypting very basic ciphers for numbers station projects using the logic of nsencode.\n")
fmt.Fprintf(os.Stderr, "\nOptions:\n")
flag.PrintDefaults() // Print the default flag help information
fmt.Fprintf(os.Stderr, "\nExamples:\n")
fmt.Fprintf(os.Stderr, " %s -s 2 <<< \"22101 12102 11210 20302 22072 122\"\n", os.Args[0])
fmt.Fprintf(os.Stderr, " %s -s 16 < file.txt\n", os.Args[0])
}
flag.Parse()
// Check if there is input from stdin
info, _ := os.Stdin.Stat()
if (info.Mode() & os.ModeCharDevice) != 0 {
flag.Usage()
os.Exit(1)
}
// Read all input from stdin
reader := bufio.NewReader(os.Stdin)
inputBytes, _ := io.ReadAll(reader)
input := string(inputBytes)
// Remove all spaces and line breaks
input = strings.ReplaceAll(input, " ", "")
input = strings.ReplaceAll(input, "\n", "")
input = strings.TrimSpace(input)
var decoded strings.Builder
// Decode the input string
for i := 0; i < len(input); i += 2 {
if i+1 >= len(input) {
break // If there's an odd number of characters, break out
}
pair := input[i : i+2]
num, err := strconv.Atoi(pair)
if err != nil {
continue // Skip invalid pairs
}
shiftedValue := applyReverseShift(num, *shift)
char := decodePair(fmt.Sprintf("%02d", shiftedValue))
if !unicode.IsPrint(char) || char == rune(-1) {
continue // Skip invalid characters
}
decoded.WriteRune(char)
}
// Output the decoded string
fmt.Println(decoded.String())
}