Home  >  Article  >  Backend Development  >  Decrypt C# string encoded in GO using AES-GSM method

Decrypt C# string encoded in GO using AES-GSM method

PHPz
PHPzforward
2024-02-10 09:39:091114browse

使用 AES-GSM 方法解密在 GO 中编码的 C# 字符串

php editor Xigua introduces you to a method of decrypting C# strings in GO language - AES-GSM. AES-GSM is an advanced encryption standard that combines the advantages of AES (Advanced Encryption Standard) and GSM (Global System for Mobile Communications). By using the AES-GSM method, we can effectively decrypt C# strings encoded in GO, enabling secure transmission and protection of data. This article will introduce the principles and usage steps of AES-GSM in detail to help readers easily master this encryption and decryption technology.

Question content

I have a string encrypted with aes-gcm in go and its passphrase and trying to decrypt it in c#. However, I can't find the correct way to decrypt it in c#. The error I am getting mentions that the size of the iv, the length of the block is not suitable for the c# decryption algorithm. Here are the values ​​in go:

aes encr/decr passphrase:  this-is-a-test-passphrase
input string:  text to encrypt hello world 123
encrypted string:  94b681ef29d9a6d7-e6fa36c4c00977de1745fc63-a1ad0481bdbeeaa02c013a2dce82520ddd762355e18f1e2f20c0ea9d001ece24e9b8216ed4b9c6a06e1ef34c953f80

go code: https://go.dev/play/p/jn8ie61ntzw

This is the decryption code in go

func appdecryptimpl(passphrase, ciphertext string) string {
arr := strings.split(ciphertext, "-")
salt, _ := hex.decodestring(arr[0])
iv, _ := hex.decodestring(arr[1])
data, _ := hex.decodestring(arr[2])
key, _ := appderivekey(passphrase, salt)
b, _ := aes.newcipher(key)
aesgcm, _ := cipher.newgcm(b)
data, _ = aesgcm.open(nil, iv, data, nil)
return string(data)
}

func appderivekey(passphrase string, salt []byte) ([]byte, []byte) {
if salt == nil {
    salt = make([]byte, 8)
    rand.read(salt)
}
return pbkdf2.key([]byte(passphrase), salt, 1000, 32, sha256.new), salt
}

This is the encryption code in go

func AppEncryptImpl(passphrase string, plaintext string) string {
key, salt := appDeriveKey(passphrase, nil)
iv := make([]byte, 12)
rand.Read(iv)
b, _ := aes.NewCipher(key)
aesgcm, _ := cipher.NewGCM(b)
data := aesgcm.Seal(nil, iv, []byte(plaintext), nil)
return hex.EncodeToString(salt) + "-" + hex.EncodeToString(iv) + "-" + hex.EncodeToString(data)
}

I'm trying to replicate the same decrypted login in c# so it will be able to decrypt and generate the final string.

I tried several decryption logics in c#, they can be found here:

  • https://dotnetfiddle.net/32sb5m This function uses the system.security.cryptography namespace but results in the wrong iv size.

  • https://dotnetfiddle.net/wxkuyr A modified version of the above for .net 5 will produce the same results

  • https://dotnetfiddle.net/6iftps Using bouncy castle library causes "mac check in gcm failed" error

  • https://dotnetfiddle.net/8mjs3g An alternative approach using the rfc2898derivebytes method produces an error saying "The calculated authentication token does not match the input authentication token"

Is the method currently being used correct, or is there another way to decrypt aes-gcm in c#? What can be done to bypass these errors when it comes to c#?

Solution

You are close to the last code. go Appends the authentication tag to the end of the generated ciphertext. You extracted it correctly here:

// extract the tag from the encrypted byte array
byte[] tag = new byte[16];
array.copy(encrypteddata, encrypteddata.length - 16, tag, 0, 16);

However, you continue to treat the array with the actual encrypted text authentication token as containing only encrypted text. To fix, extract this too:

public static void Main() {
    // This is the encrypted string that you provided
    string encryptedString = "a6c0952b78967559-2953e738b9b005028bf4f6c0-7b8464d1ed75bc38b4503f6c8d25d6bfc22a19cc1a8a92bc6faa1ed6cd837b97072bc8e16fd95b6cfca67fccbad8fc";

    // This is the passphrase that you provided
    string passphrase = "this-is-a-test-passphrase";

    string[] splitStrs = encryptedString.Split('-');

    byte[] salt = Convert.FromHexString(splitStrs[0]);
    byte[] iv = Convert.FromHexString(splitStrs[1]);
    // this is encrypted data + tag
    byte[] encryptedDataWithTag = Convert.FromHexString(splitStrs[2]);
    // Extract the tag from the encrypted byte array
    byte[] tag = new byte[16];
    // But also extract actual encrypted data
    byte[] encryptedData = new byte[encryptedDataWithTag.Length - 16];
    Array.Copy(encryptedDataWithTag, 0, encryptedData, 0, encryptedData.Length);
    Array.Copy(encryptedDataWithTag, encryptedDataWithTag.Length - 16, tag, 0, 16);
    byte[] key = new Rfc2898DeriveBytes(passphrase, salt, 1000, HashAlgorithmName.SHA256).GetBytes(32);
    // Create an AesGcm object
    AesGcm aesGcm = new AesGcm(key);
    int textLength = encryptedData.Length;
    // Decrypt the ciphertext
    byte[] plaintext = new byte[textLength];
    aesGcm.Decrypt(iv, encryptedData, tag, plaintext);
    // Convert the plaintext to a string and print it
    string decryptedString = Encoding.UTF8.GetString(plaintext);
    Console.WriteLine(decryptedString);
}

The above is the detailed content of Decrypt C# string encoded in GO using AES-GSM method. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete