I'm not sure if this is the right place to ask this. But I have no experience with C# and have been tasked to convert a security piece of code to Golang
I was wondering if i'm missing out on something here.
The C# code uses a Rijndael
class to encrypt a bit of data. The key
value and iv
value is written out in the byte code like this
public static byte[] Key = new byte[]{0xx, 0xx, 0xx, 0xx, 0xx,
0xx4, 0xxx, 0xxx, 0xxx, 0xxx, xxx, 0xxx,
0xxx, 0xxx, 0xxx, 0xxx};
public static byte[] IV = new byte[] // save structure as above with 16 in length
then theres a bit of code which does this
Rijndael alg = Rijndael.Create();
alg.Key = Key;
alg.IV = IV;
CryptoStream cs = new CryptoStream(ms,
alg.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(dataWithoutHeader, 0, dataWithoutHeader.Length);
cs.Close();
the function sends out byte[] data
as output
I'm trying to mimic this is golang
like this
func StartEncryption(message []byte) []byte {
var key = []byte {// same as C# }
var iv = []byte{ // same as C# }
var err error
fmt.Printf("
length of key %+v
,
length of iv
%+v
", len(key), len(iv))
// Encrypt
encrypted := make([]byte, len(message))
err = EncryptAESCFB(encrypted, []byte(message), key, iv)
if err != nil {
panic(err)
}
return encrypted
}
The Encryption function
func EncryptAESCFB(dst, src, key, iv []byte) error {
aesBlockEncrypter, err := aes.NewCipher([]byte(key))
if err != nil {
return err
}
aesEncrypter := cipher.NewCFBEncrypter(aesBlockEncrypter, iv)
aesEncrypter.XORKeyStream(dst, src)
return nil
}
The output of this is sent over an API whose output needs to be decrypted. I'm using this below
func decryptMessage(message []byte)error{
var key = []byte{ // same as C# }
var iv = []byte{ // same as C# }
// Remove the head part of the response (45 bytes)
responseBody := message[45:]
decrypted := make([]byte, len(responseBody))
err := DecryptAESCFB(decrypted, responseBody, key, iv)
if err != nil {
fmt.Printf("
error :
%+v
", err)
}
return nil
}
func DecryptAESCFB(dst, src, key, iv []byte) error {
aesBlockDecrypter, err := aes.NewCipher([]byte(key))
if err != nil {
return nil
}
aesDecrypter := cipher.NewCFBDecrypter(aesBlockDecrypter, iv)
aesDecrypter.XORKeyStream(dst, src)
return nil
}
The decryptor gives me gibberish - Am i going wrong somewhere?
My question boils down to 2 questions
Would the C# function using the rijndael
class and the golang functiony yield the same output or should i be doing something more/less
Is the byte array the right data to store the key, IV in - i.e its not the same used in C# when copied to GO
There's a few problems with the code you posted.
Here is an example. Playground Link
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/hex"
"fmt"
"os"
)
var (
key = randBytes(256 / 8)
gcm cipher.AEAD
nonceSize int
)
// Initilze GCM for both encrypting and decrypting on program start.
func init() {
block, err := aes.NewCipher(key)
if err != nil {
fmt.Printf("Error reading key: %s
", err.Error())
os.Exit(1)
}
fmt.Printf("Key: %s
", hex.EncodeToString(key))
gcm, err = cipher.NewGCM(block)
if err != nil {
fmt.Printf("Error initializing AEAD: %s
", err.Error())
os.Exit(1)
}
nonceSize = gcm.NonceSize()
}
func randBytes(length int) []byte {
b := make([]byte, length)
rand.Read(b)
return b
}
func encrypt(plaintext []byte) (ciphertext []byte) {
nonce := randBytes(nonceSize)
c := gcm.Seal(nil, nonce, plaintext, nil)
return append(nonce, c...)
}
func decrypt(ciphertext []byte) (plaintext []byte, err error) {
if len(ciphertext) < nonceSize {
return nil, fmt.Errorf("Ciphertext too short.")
}
nonce := ciphertext[0:nonceSize]
msg := ciphertext[nonceSize:]
return gcm.Open(nil, nonce, msg, nil)
}
func main() {
fmt.Println("Encrypting...")
msg := []byte("The quick brown fox jumped over the lazy dog.")
ciphertext := encrypt(msg)
fmt.Printf("Encrypted message: %v
", ciphertext)
fmt.Println("Decrypting...")
plaintext, err := decrypt(ciphertext)
if err != nil {
// Don't display this message to the end-user, as it could potentially
// give an attacker useful information. Just tell them something like "Failed to decrypt."
fmt.Printf("Error decryping message: %s
", err.Error())
os.Exit(1)
}
fmt.Printf("Decrypted message: %s
", string(plaintext))
}