简体   繁体   中英

How to decrypt HEX string with AES-128-GCM in C#

I am trying to retrieve data from my Kamstrup energy meter and pass it on to Home Assistant. I am getting data from the energy meter but it is encrypted. According to the documentation it is encrypted as follows: " Data transport with AES-GCM-128 and key transport AES-128 key wrap (DLMS/COSEM suite 0). "

I have received an encryption key and an authentication key in HEX format. But not sure how to use it. They only provide a very brief example in Python but i am really a long way from translating that into C#.

Microsoft have an example here to decrypt using AES: AES decryption I have tried to build on this to get the data decrypted - but it does not work. I only get a weird string like "(oƒ¸Ž\ãÀ™\\0:⫳\)Ù7ÈS\j\OÏÜ.œ\¨..." (abbreviated but is approximately 480 characters long).

As key and IV i pass the bytes from the authentication key and an encryption key. Not sure how correct that is.

Kamstrup have provided a sample where the use authentication key: "AFB3F93E3E7204EDB3C27F96DBD51AE0" and encryption key "5AD84121D9D20B364B7A11F3C1B5827F" to decrypt the following text:

DB 08 4B 41 4D 45 01 A4 DC 52 82 01 D0 30 00 07 88 E1 A0 39 B2 D1 4C 71 2D D4 D8 C8 44 0D 53 68 E4 33 BD 70 B7 36 81 E9 A9 EF FE 38 F1 75 A3 7D E9 CD E6 4E 8F 78 0D 8F 18 B4 3F C0 59 D8 79 02 F3 D7 47 B8 14 BC D0 6A 47 00 68 78 01 BD 5D 06 61 20 54 50 7D 44 E7 66 98 CC 3E 35 CC 9D E6 2C 28 4C 0D EE A6 35 B9 BF C5 6C E1 FE 5A 3A 1E 5E 27 0B 0C 18 1A CF 02 15 1F CC 59 21 34 D0 4F 02 92 B5 A3 53 38 D7 B7 81 BB 1F 2A 7E 40 71 81 5C EE D5 D4 BA C6 EF AA AF F9 79 EF 96 9D 0D B4 6F 51 E5 E0 FC 00 F5 AD 10 5F BE F9 5F C5 F8 85 46 0B 56 32 55 4A C0 5D 9E B4 F6 5F F2 23 97 2A 47 CF D4 34 B5 F5 E2 D8 53 EA 4C 14 72 75 86 F0 E2 1C 6E E1 25 26 8C B4 DC 7E C5 B1 0F 84 83 C0 10 C8 E6 88 DF 86 58 4D 7C 29 D8 17 31 A4 E0 96 91 41 B6 AD D9 42 E4 0A 96 E3 E2 DC 2F 90 20 BF 9D 58 02 A1 8D C9 85 BB 54 22 F4 70 C0 62 9D 22 DB 6F 16 B6 64 7D B3 C9 F7 27 C1 70 C2 DB 4C 9A 23 0F 82 83 46 E8 6F 56 D3 47 B6 2B FE 28 A5 07 AE 2A 21 9A CC 63 AD 5E E0 6E CB 94 9D C4 FD C2 D2 F8 08 02 7A 4A 4C 67 7C 93 C4 C8 90 9D 7 3 36 D8 B8 B3 79 18 36 C5 55 5E 74 E2 54 82 A4 4A 5F 6D 35 8D CE 84 50 47 8F 8B 2C 5D 56 66 C2 CF 8B D1 90 D4 87 4E 70 7F 5D 4B CD E9 4E 91 35 5A 81 39 C3 E4 1C D5 F0 88 99 B6 5E E9 B5 9F C6 03 72 E4 F9 2B C9 98 26 B8 C1 47 F2 09 5F B3 8A 89 14 09 AA 81 E2 27 07 6C 21 CB 7C AF 73 B3 E8 A4 E2 56 C7 0D 95 47 A9 14 F3 9C 16 93 76 BF 92 2B 08 06 4E C4 FB 31 D4 4E CD 72 1D 1A 15 1E 4E 68 4F 0B 26 85 C4 B6 9D 96 F5 FB 52 D0 B8 12 79

and get

They then recommend using "GuruX DLMS Translator" to get XML data from the decrypted string.

I really am a newbie when it comes to encrypting/decrypting so really not sure what i am doing wrong in the decryption. At first glance it lookes to me as the wrong Encoding in the output. But i have no idea where to change the encoding. I have spend hours now getting almost nowhere.

I have also tried different only decryption tools like " scadacore.com " to just get an idea of the process. But i cannot make that work either.

Code used to decrypt so far.

static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
    {
        // Check arguments.
        if (cipherText == null || cipherText.Length <= 0)
            throw new ArgumentNullException("cipherText");
        if (Key == null || Key.Length <= 0)
            throw new ArgumentNullException("Key");
        if (IV == null || IV.Length <= 0)
            throw new ArgumentNullException("IV");

        // Declare the string used to hold
        // the decrypted text.
        string plaintext = null;

        // Create an Aes object
        // with the specified key and IV.
        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Key = Key;
            aesAlg.IV = IV;
            aesAlg.BlockSize = 128;
            aesAlg.Padding = PaddingMode.None;
            //aesAlg.Mode = CipherMode.
            
            // Create a decryptor to perform the stream transform.
            ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

            // Create the streams used for decryption.
            using (MemoryStream msDecrypt = new MemoryStream(cipherText))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write))
                {
                    csDecrypt.Write(cipherText, 0, cipherText.Length);

                    //using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    //{

                    //    // Read the decrypted bytes from the decrypting stream
                    //    // and place them in a string.
                    //    plaintext = srDecrypt.ReadToEnd();
                    //}
                }

                plaintext = System.Text.Encoding.Default.GetString(msDecrypt.ToArray());
                var plainTextLength = plaintext.Length;
            }
        }

        return plaintext;
    }

Could any of you please point me in the right direction? Any help would be greatly appreciated. I am going nowhere fast.

Thank you!

There is no enough information, but I'm sure that you are using the wrong API. For AES-GCM you should use AesGcm class, like this:

static byte[] Decrypt(byte[] cipherBytes, byte[] encKey, byte[] authTag, byte[] nonce)
{
    byte[] plainBytes = new byte[cipherBytes.Length];

    using (AesGcm aesGcm = new AesGcm(encKey))
    {
        aesGcm.Decrypt(nonce, cipherBytes, authTag, plainBytes);
    }

    return plainBytes;
}

You didn't provide nonce and authentication tag, so I can't test it with your sample data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM