我工作在AES256能够加密/解密之间的iOS和PHP使用不安全的渠道。
我见过许多类似的问题,围绕着密钥大小、模式(CBC或ECB)、随机iv的使用等。但是在这种情况下,我发现了以下奇怪的行为。
两种环境中的配置:-键:32字节(256位)-块大小:128位(标准)-iv:16字节(用于测试的静态)-模式:CBC
如果我加密一个16或32字节的文本(以匹配AES块大小),Swift和PHP中的结果类似,但不完全相同:
key="12345678901234567890123456789012"明文="12345678901234567890123456789012"iv="1234567890123456"
Swift密码=E5RNNLJKV4QGNGHKMWFVGMHR80NWUVHBVVFCPQ5V2KKYKJTX4KFWMN4HXI4DG0B8 PHP密码=E5RNNLJKV4QGNKMWFGMHR80NWUVHBVVFCPQ5V2I=
如您所见,PHP Base64字符串的密码长度和最后2个字符存在差异。
但如果我使用的文本不是AES128块大小的乘法器,让我们说“Hello World”,机器人环境会报告不同(但大小相同)的密码,如下所示
Swift cipher=bdwO/5C8a plIoIXtuzfA==
PHP密码=oPotHCkxpOwQhIaCz6hNMw==
在这两种情况下(Swift和PHP),无论明文大小,密码都能正确解密。此外,Swift结果与代码的Objective-C版本一致
随附使用的简化代码:
PHP
$key = "12345678901234567890123456789012";
$iv = "1234567890123456";
$plaintext = "Hello World";
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $iv);
$ciphertext_base64 = base64_encode($ciphertext);
echo "ciphertext: ".$ciphertext_base64."</br>";
敏捷的
let keyData: NSData! = (key as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
let keyBytes = UnsafePointer<UInt8>(keyData.bytes)
let keyLength = size_t(kCCKeySizeAES256)
let plainData = (plainText as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
let dataLength = UInt(plainData.length)
let dataBytes = UnsafePointer<UInt8>(plainData.bytes)
var bufferData = NSMutableData(length: Int(dataLength) + kCCBlockSizeAES128)
var bufferPointer = UnsafeMutablePointer<UInt8>(bufferData.mutableBytes)
let bufferLength = size_t(bufferData.length)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options = UInt32(kCCOptionPKCS7Padding)
let ivData: NSData! = (iv as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
let ivPointer = UnsafePointer<UInt8>(ivData.bytes)
var numBytesEncrypted: UInt = 0
var cryptStatus = CCCrypt(operation, algoritm, options, keyBytes, keyLength, ivPointer, dataBytes, dataLength, bufferPointer, bufferLength, &numBytesEncrypted)
bufferData.length = Int(numBytesEncrypted)
let base64cryptString = bufferData.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
println(base64cryptString)
为什么这些不同?
这是由于填充模式的差异。
如果纯文本不是块大小的N倍,PHP使用“零填充”。因此,对于128位块密码(如AES),PHP将0...15字节的值设为00
。对于以块边界结束的明文,它不会添加任何填充字节。
大多数其他语言使用PKCS#7填充,填充到下一个块边界,其中填充字节反映添加的字节数。那就是1。。16个字节,值为1。。16(或六位小数形式的01
到10
)。对于以块边界结尾的纯文本,它将添加16字节的填充。
PKCS#7填充是确定性的,不依赖于纯文本值(它可以由具有任何值的字节组成,而不仅仅是文本);换句话说,它总是可以独立于内容应用和删除。
零填充存在以下问题:以00
字节结尾的纯文本可能会在解填充期间删除这些00
字节。对于ASCII兼容字符串来说,这通常不是问题,因为00
是一个控制字符,通常意味着文件结束(EOF)。
请查看mcrypt_encrypt
上的评论,了解如何将PKCS#7填充应用于PHP。
我正在加密字符串“AAAAAAAAAAAAAAAAAAAAAAAA”(一个16字节的UTF8字符串)使用AES 128 CBC与空白iv和密钥(16 0),并得到不同的结果 在PHP中: 第一位(粗体)与PHP相同,但PHP值有一个额外的“a=”,然后节点值有一个额外的“heuidae8z4dk0hu7p2z+1c” 我承认我对这里发生的事情很不确定--我错过了什么? 编辑...但不是那么不稳定,
我有相同的数据和加密密钥,相同的算法,相同的模式,但不同的结果。 C#代码: 结果:13A6DAD3119F29A8C4BF6D5BD11564E4E1A93F85B7F2AD9E8E97756688754DE32A23ADE41DFD9F76186D8E25E66D0DCF458ECAA026F16463811C48FC814E50B10FF57FDDB0C0761088D1AC4DDDAE74
问题内容: PHP功能: Java函数 } 返回null。 请注意,我们不允许更改PHP代码。有人可以帮助我们在Java中获得相同的结果吗?非常感谢。 问题答案: 如果您不只是简单地将例程中的可能内容吞噬掉,那么您将对发生的事情有了更好的了解。如果函数正在返回,那么显然发生了异常,您需要知道它是什么。 实际上,例外是: 可以肯定的是,您的纯文本长度只有11个Java字符,按照您的默认编码,它将为1
我已经尝试使用cipher.getinstance(“rsa/ecb/pkcs1padding”),但没有给出预期的结果。 感谢所有的帮助。祝你有美好的一天。
我想加密应用程序外的密钥并传递给应用程序。在应用程序中,当使用这些密钥时,必须再次使用加密时使用的密钥解密字符串。 在Swift中解密 AES
本文向大家介绍PHP实现AES256加密算法实例,包括了PHP实现AES256加密算法实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了PHP实现AES256加密算法的方法,是较为常见的一种加密算法。分享给大家供大家参考。具体如下: aes.class.php文件如下: aesctr.class.php文件如下: Demo实例程序如下: 这里再介绍另一使用 PHP mcrypt 加解密方