Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/121.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 相当于swift bouncycastle的CBCBlockCipherMac_Ios_Swift_Cryptography_Bouncycastle_Cbc Mac - Fatal编程技术网

Ios 相当于swift bouncycastle的CBCBlockCipherMac

Ios 相当于swift bouncycastle的CBCBlockCipherMac,ios,swift,cryptography,bouncycastle,cbc-mac,Ios,Swift,Cryptography,Bouncycastle,Cbc Mac,由于bouncycastle的lbrary,我需要为iOS(swift)重新实现一个针对Android应用程序(kotlin)的加密操作。 kotlin代码是: val mac = "9D3391051A4E774B".hexStringToByteArray() val macKey = "89D7B23D500D492FA01DC53B44864AB8".hexStringToByteArray() val cipheredData = "E77A914D5C94A04B6D8E10BA7A

由于bouncycastle的lbrary,我需要为iOS(swift)重新实现一个针对Android应用程序(kotlin)的加密操作。 kotlin代码是:

val mac = "9D3391051A4E774B".hexStringToByteArray()
val macKey = "89D7B23D500D492FA01DC53B44864AB8".hexStringToByteArray()
val cipheredData = "E77A914D5C94A04B6D8E10BA7A56A015AC2C40167F867A97B6349F29F3100D6D".hexStringToByteArray()

var macBlock = CBCBlockCipherMac(AESEngine(), ISO7816d4Padding())
macBlock.init(KeyParameter(macKey))
macBlock.update(cipheredData, 0, cipheredData.size)
var output = ByteArray(8)
macBlock.doFinal(output, 0)

if(output.toHex() == mac.toHex()) {
    print("equals !!")
} else {
    print("not equals : ${output.toHex()}")
}
此代码有效,从输出中找到的mac与原始的“mac”属性相同

我尝试将swift库CryptoSwift与以下代码一起使用:

let mac = Data(hex: "9D3391051A4E774B")
let macKey = Data(hex: "89D7B23D500D492FA01DC53B44864AB8")
let cipheredData = Data(hex: "E77A914D5C94A04B6D8E10BA7A56A015AC2C40167F867A97B6349F29F3100D6D")

do {
    var output = try CBCMAC(key: macKey.bytes).authenticate(cipheredData.bytes)
    checkOutput(mac: mac, output: output)
} catch {
    debugPrint("Exception \(error)")
}
但这不起作用。CryptoSwift的CBCMAC类背后的算法与bouncycastle的CBLockCiphermac不一样


我还尝试使用苹果的CommonCrypto库,但没有CBCMAC身份验证,只有HMAC。我没有找到任何方法可以轻松地为iOS平台进行CBC-MAC身份验证。

我找到了一个解决方案,在CryptoSwift类中开发真正的CBC-MAC加密:

public func authenticate(_ cipheredBytes: Array<UInt8>, padding: Padding, blockSize: Int) throws -> Array<UInt8> {
    var inBytes = cipheredBytes
    bitPadding(to: &inBytes, blockSize: blockSize)
    let blocks = inBytes.chunked(into: blockSize)

    var lastBlockEncryptionResult : [UInt8] = CBCMAC.Zero
    try blocks.forEach { (block) in
        let aes = try AES(key: Array(key), blockMode: CBC(iv: lastBlockEncryptionResult), padding: padding)
        lastBlockEncryptionResult = try aes.encrypt(block)
    }

    return lastBlockEncryptionResult
}
public func authenticate(\uCipheredBytes:Array,padding:padding,blockSize:Int)抛出->数组{
var inBytes=加密字节
位填充(到:&字节,块大小:块大小)
let blocks=inBytes.chunked(分为:blockSize)
var lastBlockEncryptionResult:[UInt8]=CBCMAC.Zero
在中尝试blocks.forEach{(block)
让aes=尝试aes(键:数组(键),块模式:CBC(iv:lastBlockEncryptionResult),填充:填充)
lastBlockEncryptionResult=尝试aes.encrypt(块)
}
返回lastBlockEncryptionResult
}
用我的初始参数调用此函数可以得到答案:

9d3391051a4e774b7572fb9bca51dc51


所以前8位是好的。

LOL,看起来CBCMAC实际上实现了CMAC。如果你连正确的名字都不知道,你怎么能创建一个加密库呢?CBC-MAC只是用全零IV进行CBC加密,丢弃中间结果,只保留最后一个块,使用位填充。这应该不是很难实现。我已经对此进行了评论和“投票”。哦,我还有趣地用Java实现了CBC-MAC,得到了一个结果,16字节结果中最左边的8字节实际上是
9D3391051A4E774B
,因此您的Android/Kotlin/Bouncy Castle代码返回了正确的结果。CryptoSwift库是错误的,这很容易通过查看源代码来确认。如果我创建真正的CBC-MAC swift类,我会注意到这个主题。第一个(最左侧)字节是CBC-MAC的正确字节,配置的输出大小为64位,是的。正如我的评论和GitHub问题中所指出的,您当然可以有16字节的输出,这通常被认为是默认配置选项(另一个讨论是哪个更安全)。哦,您可能希望在验证期间使用计算结果的时间常数比较。如果您正确地实现了该功能,然后进入下一个可能的陷阱,那就有点遗憾了:)至于您的参数,对于CBC-MAC,只有一种类型的填充,对于AES,块大小是预先知道的(它是128位/16字节),因此,您应该只在框架需要时使用这些参数。这就是我在拉取请求中所做的:)再次感谢您的帮助