drjltlm156790 2015-05-23 16:33
浏览 156
已采纳

解密在PHP中加密的C#中的数据时如何修复无效密钥大小

I am trying to solve an encryption issue I am having between php and c#.

I have encrypted data using the following php and openssl operation.

$encrypt_method = "AES-256-CBC";
$secret_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$secret_iv = 'XXXXXXXXXXXXXXXX';

$key = hash ('sha256', $secret_key);
$iv = substr (hash ('sha256', $secret_iv), 0, 16);

$output = openssl_encrypt ($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode ($output);

I have tried a couple of methods in C# to decrypt but this is what I am trying now.

public string Encrypt_Decrypt(string action, string value) {
    string secretKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    string secretIV = "XXXXXXXXXXXXXXXX";

    string key = Hash(secretKey);

    string iv = Hash(secretIV).Substring(0,16);

    string retValue = "";

    if (action == "encrypt") {
        retValue = EncryptString(value, key, iv);
    }
    else if (action == "decrypt") {
        retValue = DecryptString(value, key, iv);
    }
}

// Hash to match php hash function
public static string Hash(string unhashedString) {
    return BitConverter.ToString(new SHA256CryptoServiceProvider().ComputeHash(Encoding.Default.GetBytes(unhashedString))).Replace("-", String.Empty).ToLower();
}

    public static string DecryptString(string cipherData, string keyString, string ivString) {
        byte[] key = Encoding.UTF8.GetBytes(keyString);
        Console.WriteLine(key.Length);
        byte[] iv = Encoding.UTF8.GetBytes(ivString);
        Console.WriteLine(iv.Length);
        byte[] cipherCrypt = Convert.FromBase64String(cipherData);


        for (int i = 0; i < cipherCrypt.Length; i++) {
            Console.Write(cipherCrypt[i] + " ");
        }


        try {
            RijndaelManaged crypto = new RijndaelManaged();
            crypto.Key = key;
            crypto.IV = iv;
            crypto.Mode = CipherMode.CBC;
            crypto.KeySize = 256;
            crypto.BlockSize = 128;
            crypto.Padding = PaddingMode.None;

            ICryptoTransform decryptor = crypto.CreateDecryptor(crypto.Key, crypto.IV);

            using (MemoryStream memStream = new MemoryStream(cipherCrypt)) {
                using (CryptoStream cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read)) {
                    using (StreamReader streamReader = new StreamReader(cryptoStream)) {
                        return streamReader.ReadToEnd();
                    }
                }
            }
        }
        catch (CryptographicException e) {
            Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
            return null;
        }
    }

I have tried a couple different encoding types when getting the byte[] for the operation.

I keep getting the following error:

Specified key is not a valid size for this algorithm.

Not sure what I am missing. Any help is appreciated.

Also, I already read through this and tried what the solution suggestion recommended. I got the same resulting error.

UPDATE - 01 I have updated the code here to reflect the code I have changed.

The key length is 32,

The iv length is 16,

The data coming in at "cipherData" is length 32,

When "cipherData" goes through "FromBase64String(cipherData)" it comes out as a 24 byte array. This is causing an issue for the decryptor which wants a 32 byte array.

  • 写回答

1条回答 默认 最新

  • dongshan4878 2015-05-23 18:27
    关注

    There are obviously problems with the key size. The code between PHP and C# seem to match. The problem seems to be that the code is wrong in both cases.

    Let's see how long the key actually is:

    1. Start with a 32 byte key (non-encoded).
    2. Hash the key with SHA-256: 32 bytes (non-encoded).
    3. Encode to hex (integrated into PHP's hash() function by default): 64 bytes.

    AES only supports the following key sizes: 16, 24 and 32 bytes. openssl_encrypt() will only use the first 32 bytes of the hex key silently. So, you need to use the first 32 bytes in C#.

    Note that openssl_encrypt() takes an options argument which denotes that the output is Base64 when OPENSSL_RAW_DATA is not set. It means that the PHP output was encoded twice with Base64. So you need to decode it twice in C#.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题