来自 bouncycastle 的 CBCBlockCipherMac 等价物 swift
Equivalent of CBCBlockCipherMac from bouncycastle for swift
由于 bouncycastle 的库,我需要为 iOS (swift) 重新实现一个为 Android 应用程序 (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 class 背后的算法与 bouncycastle 的 CBCBlockCipherMac 不同。
我也试过使用苹果的 CommonCrypto 库但是没有 CBCMAC 认证,只有 HMAC。我没有找到任何方法可以轻松地为 iOS 平台进行 CBC-MAC 身份验证。
我找到了解决方案,在 CryptoSwift 中开发真正的 CBC-MAC 加密 class :
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
}
用我的初始参数调用它给出了答案:
9d3391051a4e774b7572fb9bca51dc51
所以前8位是好的。
由于 bouncycastle 的库,我需要为 iOS (swift) 重新实现一个为 Android 应用程序 (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 class 背后的算法与 bouncycastle 的 CBCBlockCipherMac 不同。
我也试过使用苹果的 CommonCrypto 库但是没有 CBCMAC 认证,只有 HMAC。我没有找到任何方法可以轻松地为 iOS 平台进行 CBC-MAC 身份验证。
我找到了解决方案,在 CryptoSwift 中开发真正的 CBC-MAC 加密 class :
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
}
用我的初始参数调用它给出了答案:
9d3391051a4e774b7572fb9bca51dc51
所以前8位是好的。