Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
596 views
in Technique[技术] by (71.8m points)

javascript - Different encryption results using C# and CryptoJS

I encrypt some data using AES in a server application, which is written in C#. I use a predefined key (32 bytes) and IV (16 bytes), for instance...

Key: 81fe1681..6a451c1c
IV:  e83c..ae76

This is my C# code I use to encrypt the data:

async Task<byte[]> Encrypt(string privateKey, string pin, byte[] data)
{
    using (var sha = SHA256.Create())
    {
        byte[] keyHash = sha.ComputeHash(Encoding.UTF8.GetBytes($"{privateKey}"));
        byte[] pinHash = sha.ComputeHash(Encoding.UTF8.GetBytes($"{pin}"));
        using (Aes aes = Aes.Create())
        {
            byte[] key = keyHash.Slice(0, aes.Key.Length);
            byte[] iv = pinHash.Slice(0, aes.IV.Length);
            using (ICryptoTransform transform = aes.CreateEncryptor(key, iv))
            using (var stream = new MemoryStream())
            using (var cryptStream = new CryptoStream(stream, transform, CryptoStreamMode.Write))
            {
                await cryptStream.WriteAsync(data, 0, data.Length);
                await cryptStream.FlushAsync();

                return stream.ToArray();
            }
        }
    }
}

The encrypted result data looks like...

534c..28f5

Now, I want to decrypt the data in a client application using CryptoJS. I use the exact same key and IV information, but decryption seems to fail... at least the decrypted result is always empty.

So, I encrypted the data on the client (of course same key and IV) and in result the ciphered text is different; more precisely it is identical but has more data at the end...

534c..28f5bbd5..ac0e

What is this additional data at the end that I don′t get if I encrypt the data on the server?

If I decrypt the ciphered text that has been encrypted on the client, the decryption works. Just to mention it, mode and padding are default on both server and client, which is CBC and Pkcs7; keysize should be 256. This is the code I use to decrypt the data that has been ciphered by the server:

let keyHash: WordArray = CryptoJS.SHA256(CryptoJS.enc.Utf8.parse(privateKey));
let key: WordArray = CryptoJS.lib.WordArray.create(keyHash.words.slice(0, 8), 32);

let pinHash: WordArray = CryptoJS.SHA256(CryptoJS.enc.Utf8.parse(pin));
let iv: WordArray = CryptoJS.lib.WordArray.create(pinHash.words.slice(0, 4), 16);

let cfg: CryptoJS.lib.IBlockCipherCfg = { iv: iv };
let paramsData: CryptoJS.lib.CipherParamsData = { 
    ciphertext: cipherBuffer
};

let decrypted: WordArray = CryptoJS.AES.decrypt(paramsData, key, cfg);
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

For the write there was a problem with the flushing of the blocks. The FlushFinalBlock() is distinct from the Flush() (or from the FlushAsync()). You have to do them both, or simply dispose the CryptoStream. This will solve the fact that the code wasn't writing the last block of data.

async static Task<byte[]> Encrypt(string privateKey, string pin, byte[] data)
{
    using (var sha = SHA256.Create())
    {
        byte[] keyHash = sha.ComputeHash(Encoding.UTF8.GetBytes($"{privateKey}"));
        byte[] pinHash = sha.ComputeHash(Encoding.UTF8.GetBytes($"{pin}"));
        using (Aes aes = Aes.Create())
        {
            byte[] key = keyHash.Slice(0, aes.Key.Length);
            byte[] iv = pinHash.Slice(0, aes.IV.Length);

            Trace.WriteLine($"Key length: { key.Length }, iv length: { iv.Length }, block mode: { aes.Mode }, padding: { aes.Padding }");

            using (var stream = new MemoryStream())
            using (ICryptoTransform transform = aes.CreateEncryptor(key, iv))
            {
                using (var cryptStream = new CryptoStream(stream, transform, CryptoStreamMode.Write))
                {
                    await cryptStream.WriteAsync(data, 0, data.Length);
                }

                return stream.ToArray();
            }
        }
    }
}

The typescript code seems to be able to decrypt it.

Working fiddle: https://jsfiddle.net/uj58twrr/3/


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...