Encoding is a major part of cyber security related operations. Sometimes you may need to actually encode payloads or decode data using base64 or in more extreme cases ROT13. Below I have a few frameworks and programs that can actually help you understand encryption, ciphers and encodings.
There are many encodings go has built directly into its standard library and one of the more used encodings is the base set of encodings! The program below takes input text, detects if its a specific base encoding and decodes the text.
For context, bases in this means that it detected, encodes and decodes base64 and base32 strings.
packagemainimport ("encoding/base32""encoding/base64""fmt")typeBaseDecoderstruct { Base64decoded []byte Base32decoded []byte}var ( X error BD BaseDecoder)funcDetectBase32(input string) bool { BD.Base32decoded, X = base32.StdEncoding.DecodeString(input)return X ==nil}funcDetectBase64(input string) bool { BD.Base64decoded, X = base64.StdEncoding.DecodeString(input)return X ==nil}funcEncodeB64(input string) string {return base64.RawStdEncoding.EncodeToString([]byte(input))}funcEncodeB32(input string) string {return base32.StdEncoding.EncodeToString([]byte(input))}funcmain() { base32String :=EncodeB32("foobar") base64String :=EncodeB64("Hello World!") isBase32 :=DetectBase32(base32String) isBase64 :=DetectBase64(base64String)if isBase32 { fmt.Println("[+] Found encoding! (BASE32)["+ base32String +"]") fmt.Println(string(BD.Base32decoded)) }if isBase64 { fmt.Println("[+] Found encoding! (BASE32)["+ base64String +"]") fmt.Println(string(BD.Base64decoded)) }}
This program is very easy to understand as we can see we just call base32 an base64 libraries.
Ciphers are another big part of the cyber security realm especially if you may need to make a secret message and transfer it to someone in a file. However, unlike encryption, ciphers despite being cryptographic can become easily reversed. A program below is going to decode both the vigenere and beacon cipher after generating cipher text.
Sometimes, ciphers can not always do the job, however this is Why golang has a powerful library for encryption algorithms such as AES. More severe cases may require us to say encrypt a file or the data in a file and move it to a specified output file. Well, given how rich golang's standard library is we can easily do so as shown below.
packagemainimport ("bytes""crypto/aes""crypto/cipher""crypto/rand""fmt""io/ioutil""log")funcEncryptFile(key []byte, inputFile string, outputFile string) error { plaintext, x := ioutil.ReadFile(inputFile)if x !=nil {return fmt.Errorf("failed to read input file: %v", x) }// Generate a random initialization vector (IV) iv :=make([]byte, aes.BlockSize)if _, x := rand.Read(iv); x !=nil {return fmt.Errorf("failed to generate IV: %v", x) }// Create the AES cipher block block, x := aes.NewCipher(key)if x !=nil {return fmt.Errorf("failed to create AES cipher block: %v", x) }// Create the AES cipher block mode with the IV mode := cipher.NewCBCEncrypter(block, iv)// Apply padding to the plaintext padding := aes.BlockSize -len(plaintext)%aes.BlockSize paddedPlaintext :=append(plaintext, bytes.Repeat([]byte{byte(padding)}, padding)...)// Encrypt the padded plaintext ciphertext :=make([]byte, len(paddedPlaintext)) mode.CryptBlocks(ciphertext, paddedPlaintext) ciphertext =append(iv, ciphertext...)// Write the encrypted data to the output file with specific permissions// and check errorif x := ioutil.WriteFile(outputFile, ciphertext, 0644); x !=nil {return fmt.Errorf("failed to write encrypted data to output file: %v", x) } fmt.Println("File encrypted successfully.")returnnil}funcmain() {// AES KEY MUST BE BETWEEN 16 and 32 BYTES key := []byte("0123456789abcdef0123456789abcdef") inputFile := os.Args[1] // grab the first argument for the input file outputFile := os.Args[2] // Grab the first argument for the output file x :=EncryptFile(key, inputFile, outputFile)if x !=nil { log.Fatalf("Encryption Error: %v", x) }}
but now we just end up with a file that is completely encrypted and cant be decrypted without a program to do so. Well, this is where the decryption comes into handy! With the same key we can decrypt the same data. Unlike your standard cipher or encoding we cant just reverse the math and then boom our issue is solved, we need an actual key to decrypt the data. This can be done like so.
funcDecryptFile(key []byte, inputFile string, outputFile string) error {// Read the input file ciphertext, x := ioutil.ReadFile(inputFile)if x !=nil {return fmt.Errorf("failed to read input file: %v", x) } iv := ciphertext[:aes.BlockSize] ciphertext = ciphertext[aes.BlockSize:] block, x := aes.NewCipher(key)if x !=nil {return fmt.Errorf("failed to create AES cipher block: %v", x) } mode := cipher.NewCBCDecrypter(block, iv) plaintext :=make([]byte, len(ciphertext)) mode.CryptBlocks(plaintext, ciphertext) padding :=int(plaintext[len(plaintext)-1]) plaintext = plaintext[:len(plaintext)-padding]if x := ioutil.WriteFile(outputFile, plaintext, 0644); x !=nil {return fmt.Errorf("failed to write decrypted data to output file: %v", x) } fmt.Println("File decrypted successfully.")returnnil}
This function once added to our program can be called with the same values. This time instead of calling the input file argument to be our origin input file we would use the output file. This means the call would look like this