我正在尝试使用与Java中使用的算法相同的算法在Swift3中生成密钥。
这是Java中的代码:
private int createKey()
{
long steps = 15041892;
// Put steps value into byte array
byte[] buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(Long.reverseBytes(steps)).array();
//Encode with HMACSHA256
Key sk = new SecretKeySpec(buffer, HASH_ALGORITHM);
Mac mac = null;
try {
mac = Mac.getInstance(sk.getAlgorithm());
mac.init(sk);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
byte[] hashDevId = mac.doFinal(("fcd5dc0295c5e3e").getBytes());
//Take the least 4 significant bits of H and use it as an offset, O.
int bCodeDevId = Truncate(hashDevId);
//The token is the lowest N digits of I in base 10.If the result has fewer digits than N, pad it with zeroes from the left.
//Reduction modulo 10^Digit
int keyDevId = bCodeDevId % (int) Math.pow(10, 8);
return keyDevId;
}
private int Truncate(byte[] hash)
{
int truncationOffset = hash[hash.length - 1] & 0xF;
int binaryCode = ((hash[truncationOffset] & 0x7F) << 24) |
((hash[truncationOffset + 1] & 0xFF) << 16) |
((hash[truncationOffset + 2] & 0xFF) << 8) |
(hash[truncationOffset + 3] & 0xFF);
return binaryCode;
}
在Swift中我使用OTPGenerator,它基于相同的逻辑。以下是使用的主要功能。
func generateOTPForCounter(_ counter: UInt64) -> String? {
counter = 15041892
self.secretKey = "fcd5dc0295c5e3e".data(using: String.Encoding.utf8)!
var newCounter = counter.bigEndian
let counterData = Data(bytes: &newCounter, count: MemoryLayout.size(ofValue: newCounter))
var bigEndian = counter.bigEndian
let count = MemoryLayout<UInt64>.size
let bytePtr = withUnsafePointer(to: &bigEndian) {
$0.withMemoryRebound(to: UInt8.self, capacity: count) {
UnsafeBufferPointer(start: $0, count: count)
}
}
let byteArray = Array(bytePtr)
let algorithm: CCHmacAlgorithm = self.algorithm.algorithm //CCHmacAlgorithm(kCCHmacAlgSHA256)
let hashPtr = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(self.algorithm.hashLength)) //CC_SHA256_DIGEST_LENGTH
defer { hashPtr.deallocate(capacity: Int(self.algorithm.hashLength)) }
self.secretKey.withUnsafeBytes { secretBytes in
counterData.withUnsafeBytes { counterBytes in
CCHmac(algorithm, secretBytes, self.secretKey.count, counterBytes, counterData.count, hashPtr)
}
}
let hash = Data(bytes: hashPtr, count: Int(self.algorithm.hashLength))
var truncatedHash = hash.withUnsafeBytes { (ptr: UnsafePointer<UInt8>) -> UInt32 in
let offset = ptr[hash.count - 1] & 0x0f
let truncatedHashPtr = ptr + Int(offset)
return truncatedHashPtr.withMemoryRebound(to: UInt32.self, capacity: 1) {
$0.pointee
}
}
truncatedHash = UInt32(bigEndian: truncatedHash)
truncatedHash = truncatedHash & 0x7fffffff
let pinValue = truncatedHash % UInt32(self.pinModeTable[self.pinLength])
return String(format: "%0*u", self.pinLength, pinValue) //self.pinLength = 8
}
因此在Swift中我获得了键01019962的这个值,而在Java 94966159中
提前致谢。