在iOS上解密AES-128加密数据

时间:2013-11-22 21:39:45

标签: ios encryption aes

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

使用以下方法加密数据

  • 填充:PKCS7Padding
  • KeySize: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;
}

1 个答案:

答案 0 :(得分:2)

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

其他一些问题:

  • 在您的加密器中,您将PBKDF2迭代设置为3.在解密器中,您将它们设置为2.此值非常非常低BTW。它通常至少为1000,更经常至少为10,000。

  • 你的IV是错误的长度。它必须是16个字节。理想情况下,每个消息的IV应该是不同的,并且应该被发送到解密器。如果您有静态IV,则会降低加密的安全性。

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


编辑:(请注意,您仍然使用已被黑客攻击的encryptedDataWithData:版本进行解密。我建议使用上面链接的decryptedDataWithData:方法。您的攻击方式{ {1}}可能会起作用,但仅仅因为它创建的缓冲区太长了。)

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

请注意,您正在使用的RNCryptManager版本中存在错误。在PasswordDeriveBytes中,此行:

AESKeyForPassword:salt:

应该是:

password.length,  // passwordLength