【问题标题】:String encryption in Objective-C decrypt in C#Objective-C中的字符串加密在C#中解密
【发布时间】:2016-03-19 12:21:06
【问题描述】:

我正在构建一个使用 c# web 服务的 iPhone 应用程序。我的 iPhone 应用程序接收一些数据并对其进行加密并将其传递给 Web 服务。如何在 C# 中解密数据?

我的 iPhone 应用包含以下代码:

NSString *pString = @"Some string to be encoded";
NSString *key = @"My encryption key";

NSData *pData = [pString dataUsingEncoding:NSUTF8StringEncoding];

pData = [pData AES256EncryptWithKey:key];
NSString *pID = [pData base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];

编辑:数据已经存储在网络服务中,所以我不能轻易更改加密方法。 C# 应用程序不在服务器上,因此不可能泄露密钥。

我已尝试使用以下 C# 代码来解密数据:

    static string DecryptString(string encryptedText, string key)
    {
        byte[] encryptedString = Convert.FromBase64String(encryptedText);
        byte[] encryptionKey = Encoding.UTF8.GetBytes(key.Substring(0, 32));

        using (var provider = new AesCryptoServiceProvider())
        {
            provider.Mode = CipherMode.CBC;
            provider.Padding = PaddingMode.PKCS7;
            provider.Key = encryptionKey;
            using (var ms = new MemoryStream(encryptedString))
            {
                // Read the first 16 bytes which is the IV.
                byte[] iv = new byte[16];
                ms.Read(iv, 0, 16);
                provider.IV = iv;

                using (var decryptor = provider.CreateDecryptor())
                {
                    using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                    {
                        using (var sr = new StreamReader(cs))
                        {
                            return sr.ReadToEnd();
                        }
                    }
                }
            }
        }
    }

但是,我得到以下异常:

System.Security.Cryptography.CryptographicException 未处理
HResult=-2146233296 Message=填充无效且不能 删除。

DecryptString 接收到的 encryptedText 长度为 80 字节。

【问题讨论】:

  • @JSWilson 有几个问题: 1. AES 的密钥大小为 128 位、192 位和 256 位,但没有 64 字节(512 位)。 2. iv 通常是块大小的随机数据(AES 为 128 位)并添加到加密数据之前。模式一般是CBC和填充PKCS#7。确保 key 和 iv 是所需的大小。
  • 方法:AES256EncryptWithKey 是一个应用实现,您需要为其提供该代码。
  • 这是我用来加密的:stackoverflow.com/questions/11482470/…
  • @prince 您提供的示例在示例中内置了一个默认 IV,因此它不适用于来自 IOS 的数据。

标签: c# ios objective-c encryption


【解决方案1】:

示例 ObjC 代码默认使用 CBC 调制解调器、PKCS#7 填充和 16 0x00 字节的默认 iv。

C# 还使用 CBC 模式和 PKCS#7 填充。解密代码需要一个 16 字节的 iv 预先添加到加密数据中,并且不存在。

byte[] iv = new byte[16];
ms.Read(iv, 0, 16);
provider.IV = iv;

这需要更改,以便将 iv 设置为 16 个 0x00 字节的数组,并且需要删除 ms.Read(iv, 0, 16) 语句,以便解密函数获取所有加密数据。

注意事项:

  1. 在加密中使用任何东西都是个坏主意,请始终提供正确的长度数据。

  2. 应添加加密数据的身份验证需求,以便确定是否存在不正确的密钥或数据已被篡改。

  3. 确实应该有一个版本号和一个随机 IV 使用并添加到加密之前,因此您应该考虑更正此问题。这说明了为什么通常需要提供和使用版本号。

RNCryptor 涵盖了上述问题。

还需要考虑加密密钥的处理,以确保尽可能安全。

【讨论】:

  • 你是个好人!我尝试用 provider.IV = new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 替换您不喜欢的三行, 0 };然而,这并没有奏效。我编写了相应的 C# 加密例程来检查我的 C# 解密例程。 C# 例程可以很好地协同工作,但不能与 IOS 一起工作。对于相同的数据输入,C# 生成/预期 128 个字节,而 IOS 生成/预期 64 个字节。我需要仔细看看 IOS 例程在做什么。
  • 输入数据的长度是多少,能否举个例子,输入输出?十六进制转储是最好的。输入可能有所不同,可能是 C# 上的 UTF-16 和 iOS 上的 UTF-8。 PKCS#7 填充。 PKCS#7 填充将在加密时添加字节并在解密时删除它们。
  • 请提供用于上述示例的密钥(十六进制或 Base64 格式。上述示例的输入长度为 57 个字节,输出为 89 个 Base64 编码字符,即 64 个解码字节:@ 987654326@。这是有道理的,PKCS#7 填充将添加 7 个字节。
  • 如何将"My encryption key"等密钥字符串转换为加密密钥? C# 方法将根据提供的密钥字符串决定加密密钥的长度,并用 perhaps 空值填充。它甚至可能使用 UTF-16 版本的字符串。 ObjC 代码具有明确指定的密钥长度,并在必要时将填充为空。但是字符串永远不应该用于加密密钥,它必须用于派生密钥,通常现在使用 PBKDF2(基于密码的密钥派生函数),具有相当大的迭代次数和种子。使用默认填充是不好的。
  • Objective-C 代码的行为不像我想象的那样。 IV和钥匙的处理并不令人满意。我将不得不更改 Objective-C 代码并提出相应的 C# 例程。看来我得去RNCryptor了。
【解决方案2】:

您需要首先将 base-64 编码的字符串解码为 byte[] - 请参阅Convert.FromBase64String()。然后你需要使用 Aes 类来解密它 - 有一个example on its documentation page。

【讨论】:

  • 我应该使用什么 AES.Mode 来与 Objective-C 兼容?我从哪里得到静脉注射?我的密钥大小是 64 字节。
  • 参考文档页面很笼统,有几个参数不适用于AES。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
  • 2018-08-17
  • 2010-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多