【问题标题】:Decrypt AES-128 encrypted data on iOS在 iOS 上解密 AES-128 加密数据
【发布时间】:2013-12-07 22:19:10
【问题描述】:

我正在尝试解密 AES 加密数据(在 .NET 中加密),但我的解密结果字符串似乎不可读,并且我没有收到任何错误。

数据使用以下加密方式加密:

  • 填充:PKCS7Padding
  • 密钥大小:128
  • 模式:CBC,

我有 InItVector、PassCode、salt 和 NumberOfPassword (3) 次迭代。

这是我的代码:

//I am retrieving my encrypted data from sqlite database:
NSString *strEncryptedData = [NSString stringWithUTF8String:(char *)sqlite3_column_blob(mysqlStatement, 0)];
NSData *dataToDecrypt = [[NSData alloc] initWithBase64EncodedString:strEncryptedData options:0];

NSString *password = @"somesecurepassword";
NSData *saltData = [@"mysalt" dataUsingEncoding:NSUTF8StringEncoding];
NSData *ivData = [@"myIV16charvalue1" dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;

NSData *decryptedData = [RNCryptManager decryptedDataForData:encoded password:password iv:ivData salt:saltData HMACSalt:NULL HMAC:NULL error:&error];

NSString *str = [[NSString alloc] initWithData:decryptedData encoding:NSASCIIStringEncoding];

NSLog(@"decrypted string: %@", str);

//这里是.NET端加密数据的代码:

static string hashAlgorithm = "SHA1";
static int passwordIterations = 3;
static string initVector = "myIV16charvalue1";
static int keySize = 128;
static string passPhrase = "somesecurepassword";
static string saltValue = "mysalt";

public static string EncryptData(string plainText)
{
    byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
    byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
    byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

    PasswordDeriveBytes password = new PasswordDeriveBytes(
        passPhrase,
        saltValueBytes,
        hashAlgorithm,
        passwordIterations);

    byte[] keyBytes = password.GetBytes(keySize / 8);

    RijndaelManaged symmetricKey = new RijndaelManaged();

    // It is reasonable to set encryption mode to Cipher Block Chaining
    // (CBC). Use default options for other symmetric key parameters.
    symmetricKey.Mode = CipherMode.CBC;
    symmetricKey.BlockSize = 128;
    symmetricKey.Padding = PaddingMode.PKCS7;


    ICryptoTransform encryptor = symmetricKey.CreateEncryptor(
        keyBytes,
        initVectorBytes);
        MemoryStream memoryStream = new MemoryStream();
    CryptoStream cryptoStream = new CryptoStream(memoryStream,
        encryptor,
        CryptoStreamMode.Write);

    // Start encrypting.
    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);

    // Finish encrypting.
    cryptoStream.FlushFinalBlock();
    byte[] cipherTextBytes = memoryStream.ToArray();

    memoryStream.Close();
    cryptoStream.Close();

    string cipherText = Convert.ToBase64String(cipherTextBytes);

    return cipherText;
}

【问题讨论】:

  • 发布.net中加密的代码
  • 在 .net 中添加了加密数据的代码...
  • 你终于找到解决这个问题的方法了吗?

标签: ios encryption aes


【解决方案1】:

这里有几个错误。看起来decryptedDataForData:...RNCryptManager 的修改版,但是已经注入了几个错误。尤其是貌似作者复制了加密方式(encryptedDataForData:...),然后只是改了操作。你不能那样做。解密方法与加密方法不同。在上面的代码中,解密器忽略了传递给它的盐和 IV,并创建了随机的(这是加密器的工作方式,而不是解密器)。

其他一些问题:

  • 在您的加密器中,您将 PBKDF2 迭代设置为 3。在解密器中,您将它们设置为 2。顺便说一句,这个值非常非常低。通常至少为 1000,更常见的是至少 10,000。

  • 您的 IV 长度错误。它必须正好是 16 个字节。理想情况下,IV 对于每条消息都应该不同,并且应该一起发送给解密器。如果你有一个静态 IV,那么你会降低加密的安全性。

  • 虽然不是问题的原因,但盐也应该为每条消息随机发送并发送到解密器。静态盐可以更轻松地执行密码攻击。


编辑:(请注意,您仍在使用encryptedDataWithData: 的破解版本进行解密。我建议使用上面链接的decryptedDataWithData: 方法。您破解encryptedDataWithData: 的方式可能会起作用,但只是因为它创建的缓冲区恰好太长。)

更深层次的问题是您在 C# 中使用了错误的 KDF。您正在使用实现 PBKDF1 的 PasswordDeriveBytes。你应该使用Rfc2898DeriveBytes,它实现了PBKDF2。

请注意,您使用的 RNCryptManager 版本存在错误。在AESKeyForPassword:salt:,这一行:

password.length,  // passwordLength

应该是:

[password lengthOfBytesUsingEncoding:UTF8StringEncoding],

【讨论】:

  • Rob,非常感谢您对我的问题发表评论。是的,“decryptedDataForData”方法是您的文章“使用 CommonCrypto 使用 AES 正确加密”(非常有用的顺便说一句)中的 RNCryptManager (encryptedDataForData) 的修改版本。我已经更新了我的代码以使用提供的 IV/Salt 值,而不是生成随机值。另外,我将 PBKDF2 更改为 3 以匹配加密。 IV 值是 16 个字节,我只是用这篇文章的一些文本替换了它。但是,解密后我仍然得到不可读的字符串,没有错误:(
  • Rob,感谢您的 cmets,我现在使用 RNCryptManager 的 'decryptedDataForData' 方法,但是我仍然得到相同的不可读的解密字符串。我无法控制 .net 加密,有没有办法修改代码以在解密时使用 PBKDF1 而不是 PBKDF2?再次感谢您。
  • CommonCrypto 不提供 PBKDF1 实现。您可以使用提供 C++ 实现的 cryptopp 或 botan(尽管它们对于一个功能来说是相当大的包)。或者您可以搜索可以适应的 C 实现。规范在这里:tools.ietf.org/html/rfc2898#section-5.1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-03
  • 2013-08-24
  • 1970-01-01
  • 2011-02-18
  • 2021-12-20
  • 2020-11-29
相关资源
最近更新 更多