针对.NET、Java(android)和iOS的AES加密

针对.NET、Java(android)和iOS的AES加密,java,android,ios,encryption,aes,Java,Android,Ios,Encryption,Aes,使用本文中的示例,我成功地在一个为我的Android应用程序提供XML提要的.NET应用程序之间实现了AES加密 现在,我正尝试在该应用的iOS版本中使用相同的实现。我发现了一些非常好的用于iOS的AES示例,但到目前为止,似乎没有一个与我当前使用的方案相匹配。据我所知,问题在于C#和Java之间共享的16字节密钥(rawSecretKey)。在iOS示例中,我找不到一个类似的键来设置相同的字节数组。它有密码短语,但没有字节数组 如果有人知道一个很好的例子来说明这种类型的实现,那将非常有帮助。我

使用本文中的示例,我成功地在一个为我的Android应用程序提供XML提要的.NET应用程序之间实现了AES加密

现在,我正尝试在该应用的iOS版本中使用相同的实现。我发现了一些非常好的用于iOS的AES示例,但到目前为止,似乎没有一个与我当前使用的方案相匹配。据我所知,问题在于C#和Java之间共享的16字节密钥(rawSecretKey)。在iOS示例中,我找不到一个类似的键来设置相同的字节数组。它有密码短语,但没有字节数组


如果有人知道一个很好的例子来说明这种类型的实现,那将非常有帮助。我发现的一个iOS示例是,但同样,我不知道如何包含我文章顶部第一个链接中引用的16字节数组。

.Net和iOS都支持PKCS7Padding,但Java不支持(除非使用第三方库)

.Net和Java都支持ISO10126填充,但IOS不支持(除非使用第三方库)

因此,我认为您需要为IOS和Java提供单独的.net加密代码

以下是一些代码示例:

对于IOS:

+ (NSData*)encryptData:(NSData*)data :(NSData*)key :(NSData*)iv
{    
    size_t bufferSize = [data length]*2;
    void *buffer = malloc(bufferSize);
    size_t encryptedSize = 0;    
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,                                          
                                          [key bytes], [key length], [iv bytes], [data bytes], [data length],                                          
                                          buffer, bufferSize, &encryptedSize);  
    if (cryptStatus == kCCSuccess)      
        return [NSData dataWithBytesNoCopy:buffer length:encryptedSize];    
    else
        free(buffer);
    return NULL;
}
对于.NET:

public static byte[] AesEncrypt(byte[] bytes, byte[] key, byte[] iv)
{
    if (bytes == null || bytes.Length == 0 || key == null || key.Length == 0 || iv == null || iv.Length == 0)
        throw new ArgumentNullException();

    using (var memoryStream = new MemoryStream())
    {
        using (var rijndaelManaged = new RijndaelManaged { Key = key, IV = iv, Padding = PaddingMode.PKCS7, Mode = CipherMode.CBC })
        {
            using (var cryptoStream = new CryptoStream(memoryStream, rijndaelManaged.CreateEncryptor(key, iv), CryptoStreamMode.Write))
            {
                cryptoStream.Write(bytes, 0, bytes.Length);
            }
        }
        return memoryStream.ToArray();
    }
}
对于Java:

public static byte[] encrypt(byte[] bytes, byte[] key, byte[] iv)
        throws Exception
{
    Cipher cipher = Cipher.getInstance("AES/CBC/ISO10126Padding");
    cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"),
            new IvParameterSpec(iv));
    return cipher.doFinal(bytes);
}
我只提供用于加密的代码,因为解密代码非常相似,您可以很容易地找到它


如有任何问题,请留下评论。

如果iOS是从密码短语派生密钥,那么是否有可能在Android中复制相同的密钥派生功能?密码短语在不同平台中是一个常量-该特定密钥不是问题。更重要的是,所使用的16字节数组——我发现的iOS示例没有包含该值(或者至少我不够聪明,看不到它)。我也不能改变Android的实现,因为它正在生产中,我们的用户已经使用现有的方法对数据进行了加密。我只需要为iOS.BTW复制它-字节键也是一个常量,它不是从任何东西派生的。我刚刚创建了密钥,它看起来像:私有静态字节[]rawSecretKey={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};您需要查看iOS文档,看看是否有办法传入字节键,而不是密码短语。否则,您需要确定生成现有Android密钥的密码短语,并在iOS中使用该密码短语。我不是iOS专家,所以我在这方面帮不了什么忙。rossum…谢谢你的评论,但我不太确定它们是否是我需要的。我控制密码短语和16字节密钥的值,并且我需要在加密/解密例程中同时使用它们。我可以在iOS中轻松设置密码短语——我只需要告诉iOS 16字节的密钥是什么,就像我在Java和.NET实现中所做的那样。看一下我问题中的第一个链接,您将看到我用作Java和.NET基础的代码。
“PKCS5Padding”
在Java中与PKCS#7填充相同。在标准中,填充算法只在块大小上有所不同(PKCS#5为8字节,PKCS#7为16字节),但在大多数实现中,填充算法与这两种块大小都兼容,在Java(或者更准确地说,Oracle和Bouncy Castle提供程序)中,填充算法当然是如此。@owlstead,正如您所说,“在大多数实现中”。如果块大小不是8字节,则它们不相同。我将试一试:用Java编写的PKCS5和用C#编写的PKCS7,看看它们是否可以相互对话。