【问题标题】:Cannot AES decrypt data in C# that was enccrypted in Objective-C无法 AES 解密在 Objective-C 中加密的 C# 中的数据
【发布时间】:2015-11-09 19:36:49
【问题描述】:

我有一个 iOS 应用程序,它发送加密数据,然后在 C# 中解密。我检查了十六进制密钥和接收到的数据是否相同,但我仍然得到 Bad PKCS7 padding。长度 0 无效。

我的 Objective-C 调用是

  +(NSData*) encryptData: (NSData*) data
               key: (NSString*) key
{
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256+1]; // 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 = [data length];

//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);

size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                      keyPtr, kCCKeySizeAES256,
                                      NULL /* initialization vector (optional) */,
                                      [data bytes], dataLength, /* 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;

}

我的 keysize 是 256,blocksize 是 128,padding 是 pkcs7,IV 是 null,mode 是 CBC(默认)。

我要解密的 C# 代码是

            using (MemoryStream memoryStream = new MemoryStream(outputBytes))
        {
            AesManaged algo = GetCryptoAlgorithm(GetRawBrokerKey());
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream, algo.CreateDecryptor(), CryptoStreamMode.Read))
            {
                using (StreamReader srDecrypt = new StreamReader(cryptoStream))
                {
                    plaintext = srDecrypt.ReadToEnd();
                }
            }
        }

    private static AesManaged GetCryptoAlgorithm()
    {
        return GetCryptoAlgorithm(null);
    }
    private static AesManaged GetCryptoAlgorithm(byte[] key)
    {
        AesManaged algorithm = new AesManaged();

        //set the mode, padding and block size
        algorithm.Padding = PaddingMode.PKCS7;
        algorithm.Mode = CipherMode.CBC;
        algorithm.KeySize = 256;
        algorithm.BlockSize = 128;
        if (key != null)
        {
            algorithm.Key = key;
        }

        algorithm.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        return algorithm;
    }

我尝试使用 C# 进行加密,并使用相同的密钥查看不同的十六进制输出。 c# encryption - 42AC7494606333309287768F47DFB35B

    static byte[] EncryptStringToBytes_Aes(string plainText, byte[] key)
    {
        // Check arguments. 
        if (plainText == null || plainText.Length <= 0)
            throw new ArgumentNullException("plainText");

        byte[] encrypted;
        AesManaged algorithm = new AesManaged();

        //set the mode, padding and block size
        algorithm.Padding = PaddingMode.PKCS7;
        algorithm.Mode = CipherMode.CBC;
        algorithm.KeySize = 256;
        algorithm.BlockSize = 128;
        if (key != null)
        {
            algorithm.Key = key;
        }

        algorithm.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        // Create a decrytor to perform the stream transform.
        ICryptoTransform encryptor = algorithm.CreateEncryptor();

            // Create the streams used for encryption. 
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        //Write all data to the stream.
                        swEncrypt.Write(plainText);
                    }

                    encrypted = msEncrypt.ToArray();
                }
            }


        string hex = BitConverter.ToString(encrypted);
        Console.WriteLine("c# encryption - " + hex.Replace("-", ""));

        // Return the encrypted bytes from the memory stream. 
        return encrypted;

    }

有什么想法可能会出错吗?我认为,我似乎正在遵循有关模式和 IV 的默认值的所有在线建议。

【问题讨论】:

  • Hex 在加密/解密调用之前转储 Objective-C 和 C++ 中的参数(密钥和数据),您应该会发现问题。如果是字符串,则可能存在关键问题。另一个明显的区别是传递数据与流的指针。调用没有明显错误。
  • 我在 c# 中的十六进制值是加密的有效载荷十六进制 - DB1FB055E7961F6D2648110B1A8854CA 密钥十六进制 - 708B797DDB28D167CCC19F71ED2920447C743B9BFD5B878FA5CA7A0FC35659E4
  • 我在 Objective-C 中的十六进制值是 --key hex = 加密数据 hex =
  • 对不起,我犯了一个愚蠢的错误,填充是在未加密的数据上,所以可能没有填充错误。
  • 随机数据无法转换为 unicode 字符串,所以使用 Base64 编码或 hex 编码。除了 Base64 编码之外,不需要密钥字符串。

标签: c# objective-c encryption interop aes


【解决方案1】:

在GetCryptoAlgorithm中,需要将私钥传递给GetCryptoAlgorithm。

【讨论】:

  • 密钥似乎是通过调用GetRawBrokerKey() providing the key 传递的。在对称密钥加密中,密钥不称为“私钥”,只是“密钥”。
猜你喜欢
相关资源
最近更新 更多
热门标签