|
@@ -30,10 +30,15 @@ public class CMAC: Authenticator {
|
|
|
|
|
|
// MARK: Authenticator
|
|
|
|
|
|
+ // AES-CMAC
|
|
|
public func authenticate(_ bytes: Array<UInt8>) throws -> Array<UInt8> {
|
|
|
- let aes = try AES(key: Array(key), blockMode: CBC(iv: CMAC.Zero), padding: .noPadding)
|
|
|
+ let cipher = try AES(key: Array(key), blockMode: CBC(iv: CMAC.Zero), padding: .noPadding)
|
|
|
+ return try self.authenticate(bytes, cipher: cipher)
|
|
|
+ }
|
|
|
|
|
|
- let l = try aes.encrypt(CMAC.Zero)
|
|
|
+ // CMAC using a Cipher
|
|
|
+ public func authenticate(_ bytes: Array<UInt8>, cipher: Cipher) throws -> Array<UInt8> {
|
|
|
+ let l = try cipher.encrypt(CMAC.Zero)
|
|
|
var subKey1 = self.leftShiftOneBit(l)
|
|
|
if (l[0] & 0x80) != 0 {
|
|
|
subKey1 = xor(CMAC.Rb, subKey1)
|
|
@@ -67,11 +72,11 @@ public class CMAC: Authenticator {
|
|
|
var y = Array<UInt8>(repeating: 0x00, count: CMAC.BlockSize)
|
|
|
for block in blocks {
|
|
|
y = xor(block, x)
|
|
|
- x = try aes.encrypt(y)
|
|
|
+ x = try cipher.encrypt(y)
|
|
|
}
|
|
|
// the difference between CMAC and CBC-MAC is that CMAC xors the final block with a secret value
|
|
|
y = self.process(lastBlock: lastBlock, with: x)
|
|
|
- return try aes.encrypt(y)
|
|
|
+ return try cipher.encrypt(y)
|
|
|
}
|
|
|
|
|
|
func process(lastBlock: ArraySlice<UInt8>, with x: [UInt8]) -> [UInt8] {
|