iOS和Android中的AES加密,以及C#.NET中的解密

前端之家收集整理的这篇文章主要介绍了iOS和Android中的AES加密,以及C#.NET中的解密前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
第一件事先前段时间,我需要在 Android中使用简单的AES加密来加密密码,并将其作为密码解密的.net Web服务的参数发送.

以下是我的Android加密:

private static String Encrypt(String text,String key)
        throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] keyBytes= new byte[16];
        byte[] b= key.getBytes("UTF-8");
        int len= b.length;
        if (len > keyBytes.length) len = keyBytes.length;
        System.arraycopy(b,keyBytes,len);
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes,"AES");
        IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
        cipher.init(Cipher.ENCRYPT_MODE,keySpec,ivSpec);

        byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
        String result = Base64.encodeBytes(results);
        return result;
        }

然后我用C#解密它:

public static string Decrypt(string textToDecrypt,string key)
    {
        System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();

        RijndaelManaged rijndaelCipher = new RijndaelManaged();
        rijndaelCipher.Mode = CipherMode.CBC;
        rijndaelCipher.Padding = PaddingMode.PKCS7;

        rijndaelCipher.KeySize = 0x80;
        rijndaelCipher.BlockSize = 0x80;

        string decodedUrl = HttpUtility.UrlDecode(textToDecrypt);
        byte[] encryptedData = Convert.FromBase64String(decodedUrl);
        byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
        byte[] keyBytes = new byte[0x10];
        int len = pwdBytes.Length;
        if (len > keyBytes.Length)
        {
            len = keyBytes.Length;
        }
        Array.Copy(pwdBytes,len);
        rijndaelCipher.Key = keyBytes;
        rijndaelCipher.IV = keyBytes;
        byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData,encryptedData.Length);
        return encoding.GetString(plainText);
    }

这样做就像一个魅力,但是当我在iOS中尝试这样做时,问题就出现了.我是iphone / ipad的新开发应用程序,所以我去搜索它,几乎所有提供的代码示例如下:

- (NSData *)AESEncryptionWithKey:(NSString *)key {
char keyPtr[kCCKeySizeAES128]; // room for terminator (unused)
bzero(keyPtr,sizeof(keyPtr)); // fill with zeroes (for padding)

// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

NSUInteger dataLength = [self length];

size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);

size_t numBytesEncrypted = 0;

CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,kCCAlgorithmAES128,kCCOptionPKCS7Padding,keyPtr,kCCKeySizeAES128,NULL /* initialization vector (optional) */,[self bytes],[self length],/* input */
                                      buffer,bufferSize,/* output */
                                      &numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
    //the returned NSData takes ownership of the buffer and will free it on deallocation
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}

free(buffer); //free the buffer;
return nil;

}

也许我有点太乐观了,当我希望在这里顺利过渡,因为当Android正在扔我的东西像:

“EgQVKvCLS4VKLoR0xEGexA ==”

那么iOS给了我:

"yP42c9gajUra7n0zSEuVJQ=="

希望这只是我忘记的东西,还是一些设置错了?

[UPDATE]结果现在显示在base64编码之后.

解决方法

首先要注意的是,您在此代码中有重大的安全问题.您正在使用字符串密码,并将其放入密钥.如果这个字符串是人性化的,那么你已经大大缩小了你的密钥空间(将AES-128转换为更像AES-40或AES-50,甚至更糟).您需要使用PBKDF2盐和拉伸键.见 Properly encrypting with AES with CommonCrypto进行更全面的讨论.

你也有一个重大的安全问题,因为你使用你的钥匙作为你的IV(见下文更多,这实际上是你的症状的原因).这不是选择IV的正确方法,并使您的密文可以预见.使用相同密钥加密的相同明文将给出相同的结果.这根本就没有Ⅳ. IV需要随机.请参阅上述链接以获得更多的讨论.

现在到你的实际症状问题是你在Java和C#中使用的是IV,但是你在iOS上使用了0(NULL)作为IV(IV不是可选的,你只是传递0).在所有情况下,您都需要使用相同的IV.

猜你在找的iOS相关文章