-1

I need change this code JavaScript To C#

var CryptoJS = require("crypto-js"); var bytes = CryptoJS.AES.decrypt(ciphertext, secretkey); var originalText = bytes.toString(CryptoJS.enc.Utf8);

Example

Encriypted Json or String:

U2FsdGVkX1+pmKonC+E+MGs9BltH/axDE3IRYIV+vHF0yuteP4JAzuQ/CmmSgY2xkqeAhl02bIL5cJhsE1NOsc79ENadltxt2QEBymquSnbUsuhtxHptgGUXV0XuSPPQAt4/Rk2bDaR7qJw2LJKh4U1/pqeJUlqP2qLdtBTLs7E+W2TVh0/yMAVyuGUctEtx41qOClFzyfPxNydtSO6vzQ+3OOrI4Ov7ZgX07OJIF5sAq+m3pJQspL93UHbKS1w7a4dJUn2s+7JRYASkD9IBsheXI//SiE3yJv3c/dOs3VFDl4ok+m0MkgMwHQ0ELySUx1/UVTY6lefenO2RgASE52ATwIyKy7rdf4GKnrYpU7rdMZwcu1enI8Jpz5Ri3pFioyJSiPPDVKIecDQJ+UsQpsszWA6mQb3YMRhIxJrdcjSGEIHPGTHFEYgVpSO9y4EeGKLvX5oJ0tQDhO+QW1LQszcojRsgFuyFkdAsjNVzRNK3K4qE6Ua8j6t/kyE9i/MW7DQ0nT3d3CozLGS68PdEI34kljArY6Hmrgkt4InvBKdMvfffogKE3NtwBhf/3nK5

Password or Key:

F2Gs3zjSjd3

Out:

[{"file":"https://b-g-eu-9.feetcdn.com:2223/v3-hls-playback/c83527cf3b73ecffcf91595b165e137b7bf0f0ff2cf816d8667161afea2370e71690359b5976a5dc5c03de31f949fb1b200f2bce6c273a4130adf84021cf6552384560a824abbe8461d68ffcd0cebd910f40863d28243932cc345541a0cd0c8e12788b9dd7cfed3537ba53fcaa365bf0afb6fac7ae10374d4d89c7a50d37988df1625da6a6e248a2c6ac5183c26a1b0b1d9e24ecaa036a31c306f7714c3c7b2c/playlist.m3u8","type":"hls"}]

I tried in this page and working nice, but i need implementation for C# .Net

Pls Help

I tried some variant in C# for AES Decryption, but not luck.

2 Answers2

1

The first thing you will need to do is to split the input data into salt and actual ciphertext.

static byte[] Signature = new byte[] { 0x53, 0x61, 0x6c, 0x74, 0x65, 0x64, 0x5f, 0x5f };

byte[] saltedCipher = Convert.FromBase64String(base64Cipher);
if (!Enumerable.SequenceEqual(Signature, saltedCipher.Take(Signature.Length))) return null; // invalid cipher

byte[] salt = saltedCipher.Skip(Signature.Length).Take(8).ToArray();
byte[] cipher = saltedCipher.Skip(Signature.Length + salt.Length).ToArray();

The second step is to generate 48 bytes of data, 32 bytes for the AES key and 16 bytes for the IV, using an algorithm called EvpKDF (this is what CryptoJS uses by default).

byte[] kdfOutput = EvpKDF(passwordBytes, salt, 48);
aes.Key = kdfOutput.Take(32).ToArray();
aes.IV = kdfOutput.Skip(32).Take(16).ToArray();

Finally, the data has to be actually decrypted using AES and the calculated values for Key and IV.

byte[] decrypted = aesDecryptor.TransformFinalBlock(cipher, 0, cipher.Length);
return Encoding.Default.GetString(decrypted);

My full implementation looks like this:

static byte[] Signature = new byte[] { 0x53, 0x61, 0x6c, 0x74, 0x65, 0x64, 0x5f, 0x5f };

static string Decrypt(string base64Cipher, string password)
{
    using (Aes aes = Aes.Create())
    {
        byte[] saltedCipher = Convert.FromBase64String(base64Cipher);
        if (!Enumerable.SequenceEqual(Signature, saltedCipher.Take(Signature.Length))) return null; // invalid cipher

        byte[] salt = saltedCipher.Skip(Signature.Length).Take(8).ToArray();
        byte[] cipher = saltedCipher.Skip(Signature.Length + salt.Length).ToArray();

        byte[] passwordBytes = Encoding.Default.GetBytes(password);

        byte[] kdfOutput = EvpKDF(passwordBytes, salt, 48);
        aes.Key = kdfOutput.Take(32).ToArray();
        aes.IV = kdfOutput.Skip(32).Take(16).ToArray();

        using (ICryptoTransform aesDecryptor = aes.CreateDecryptor())
        {
            byte[] decrypted = aesDecryptor.TransformFinalBlock(cipher, 0, cipher.Length);
            return Encoding.Default.GetString(decrypted);
        }
    }
}

static byte[] EvpKDF(byte[] password, byte[] salt, int targetSize)
{
    using (MD5 md5 = MD5.Create())
    {
        byte[] output = new byte[targetSize];
        byte[] buffer = null;

        int outputSize = 0;
        while (outputSize < targetSize)
        {
            if (buffer != null)
                buffer = md5.ComputeHash(buffer.Concat(password).Concat(salt).ToArray());
            else buffer = md5.ComputeHash(password.Concat(salt).ToArray());

            Array.Copy(buffer, 0, output, outputSize, buffer.Length);
            outputSize += buffer.Length;
        }

        return output;
    }
}

Note that this implementation is not perfect, there is much to improve, but it should be decent for small amounts of data like you provided as an example.

Konsl
  • 11
  • 2
-1

Well i found this work 100%

public static string DecryptAes(string encryptedString, string passphrase)
    {
        // encryptedString is a base64-encoded string starting with "Salted__" followed by a 8-byte salt and the
        // actual ciphertext. Split them here to get the salted and the ciphertext
        var base64Bytes = Convert.FromBase64String(encryptedString);
        var saltBytes = base64Bytes[8..16];
        var cipherTextBytes = base64Bytes[16..];

        // get the byte array of the passphrase
        var passphraseBytes = Encoding.UTF8.GetBytes(passphrase);

        // derive the key and the iv from the passphrase and the salt, using 1 iteration
        // (cryptojs uses 1 iteration by default)
        DeriveKeyAndIv(passphraseBytes, saltBytes, 1, out var keyBytes, out var ivBytes);

        // create the AES decryptor
        using var aes = Aes.Create();
        aes.Key = keyBytes;
        aes.IV = ivBytes;
        // here are the config that cryptojs uses by default
        // https://cryptojs.gitbook.io/docs/#ciphers
        aes.KeySize = 256;
        aes.Padding = PaddingMode.PKCS7;
        aes.Mode = CipherMode.CBC;
        var decryptor = aes.CreateDecryptor(keyBytes, ivBytes);

        // example code on MSDN https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.aes?view=net-5.0
        using var msDecrypt = new MemoryStream(cipherTextBytes);
        using var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
        using var srDecrypt = new StreamReader(csDecrypt);

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

    /// <summary>
    /// <para>C# equivalent method of EVP_BytesToKey in OpenSSL
    /// https://stackoverflow.com/questions/8008253/c-sharp-version-of-openssl-evp-bytestokey-method</para>
    /// <para>Generate the Key and the IV from the input Passphrase and the Salt</para>
    /// </summary>
    /// <param name="passphrase"></param>
    /// <param name="salt"></param>
    /// <param name="iterations">How many iterations to perform hash</param>
    /// <param name="key">The output 32 byte key</param>
    /// <param name="iv">The output 16 byte iv</param>
    private static void DeriveKeyAndIv(byte[] passphrase, byte[] salt, int iterations, out byte[] key, out byte[] iv)
    {
        var hashList = new List<byte>();

        var preHashLength = passphrase.Length + (salt?.Length ?? 0);
        var preHash = new byte[preHashLength];

        Buffer.BlockCopy(passphrase, 0, preHash, 0, passphrase.Length);
        if (salt != null)
            Buffer.BlockCopy(salt, 0, preHash, passphrase.Length, salt.Length);

        var hash = MD5.Create();
        var currentHash = hash.ComputeHash(preHash);

        for (var i = 1; i < iterations; i++)
        {
            currentHash = hash.ComputeHash(currentHash);
        }

        hashList.AddRange(currentHash);

        while (hashList.Count < 48) // for 32-byte key and 16-byte iv
        {
            preHashLength = currentHash.Length + passphrase.Length + (salt?.Length ?? 0);
            preHash = new byte[preHashLength];

            Buffer.BlockCopy(currentHash, 0, preHash, 0, currentHash.Length);
            Buffer.BlockCopy(passphrase, 0, preHash, currentHash.Length, passphrase.Length);
            if (salt != null)
                Buffer.BlockCopy(salt, 0, preHash, currentHash.Length + passphrase.Length, salt.Length);

            currentHash = hash.ComputeHash(preHash);

            for (var i = 1; i < iterations; i++)
            {
                currentHash = hash.ComputeHash(currentHash);
            }

            hashList.AddRange(currentHash);
        }

        hash.Clear();
        key = new byte[32];
        iv = new byte[16];
        hashList.CopyTo(0, key, 0, 32);
        hashList.CopyTo(32, iv, 0, 16);
    }

Thx to Tony Tran tmtxt

CryptoJsStaticHelper.cs

  • Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. **Would you kindly [edit] your answer to include additional details for the benefit of the community?** – Jeremy Caney May 19 '23 at 00:33
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 19 '23 at 04:20