测试 CryptoKit 的数据验证
Testing CryptoKit's data validation
我想验证一些下载的数据未被修改。我的期望是,如果我修改原始数据,签名将失败。虽然这在某些情况下是正确的 (data2
),但令人惊讶的是在其他情况下却不起作用 (data3
)。使用散列/Digest
returns 相同的结果。
import CryptoKit
let rootKey = P256.Signing.PrivateKey()
let publicKey = rootKey.publicKey
let data = Data(bytes: [0xA, 0xB, 0xC, 0xD], count: 4)
let digest = SHA256.hash(data: data)
let signature = try rootKey.signature(for: data)
let hashSignature = try rootKey.signature(for: digest)
// now alter the data
let data2 = Data(bytes: [0x0, 0xB, 0xC, 0xD], count: 4)
let data3 = Data(bytes: [0xA, 0xB, 0xC, 0xE], count: 4)
publicKey.isValidSignature(signature, for: data) // true, as expected
publicKey.isValidSignature(signature, for: data2) // false, as expected
publicKey.isValidSignature(signature, for: data3) // why is THIS true/valid?
publicKey.isValidSignature(hashSignature, for: SHA256.hash(data: data)) // true
publicKey.isValidSignature(hashSignature, for: SHA256.hash(data: data2)) // false
publicKey.isValidSignature(hashSignature, for: SHA256.hash(data: data3)) // true
为简单起见,使用 CryptoKit
。这在(我的)CommonCrypto
/SecKey...
实现中也失败了。
好的,我发现了问题。您的代码 100% 正确。这个问题是由 Swift 中一些相当有问题的错误引起的 - 我 认为 。聪明的Swift高手请指正赐教!
顺便说一句:我正在使用 Xcode Version 12.2 beta 3 (12B5035g)
数据不平等错误
func testDataInequality() {
func hexString(_ data: Data) -> String {
data.map { String(format: "%02hhx", [=10=]) }.joined()
}
let data = Data(bytes: [0xA, 0xB, 0xC, 0xD], count: 4)
let data3 = Data(bytes: [0xA, 0xB, 0xC, 0xE], count: 4)
XCTAssertEqual(data.count, data3.count)
XCTAssertEqual(data.count, 4)
XCTAssertNotEqual(data, data3, "Expected 'data': \(hexString(data)) to NOT equal: 'data3': \(hexString(data3)), but it did.")
}
这个简单的单元测试失败了,但应该不会失败。意思是,data
和 data3
显然不一样,因为我们看到 [0xA, 0xB, 0xC, 0xD] != [0xA, 0xB, 0xC, 0xE]
。我们使用 XCTAssertNotEqual
断言它们不应该相等,但是这个断言失败了,这意味着 Swift 相信它们是相等的。
我使用嵌套方法hexString
分别打印了data
和data3
的内容,我们在运行测试[=56]时得到这个错误信息=]:
XCTAssertNotEqual failed: ("4 bytes") is equal to ("4 bytes") - Expected 'data': 0a000000 to NOT equal: 'data3': 0a000000, but it did.
我们可以看到 data
和 data3
都错误地取值:0a000000
,如 [0xa, 0x0, 0x0, 0x0]
.
更改为对数据使用已弃用的初始化程序:
@available(swift 4.2)
@available(swift, deprecated: 5, message: "use `init(_:)` instead")
public init<S>(bytes elements: S) where S : Sequence, S.Element == UInt8
而不是您使用的“正确”(未弃用)bytes:count
,我们得到正确的行为....
所以改为:
let data = Data(bytes: [0xA, 0xB, 0xC, 0xD])
let data3 = Data(bytes: [0xA, 0xB, 0xC, 0xE])
然后重新运行 测试,看看它是否有效。
此外,您可以添加这些断言:
XCTAssertEqual(hexString(data), "0a0b0c0d")
XCTAssertEqual(hexString(data3), "0a0b0c0e")
我会确保将此报告为 Swift 错误。
多亏了,我才能够弄清楚我做错了什么。这似乎不是一个错误,而是一个简单的类型转换问题:
let bytes = [UInt8]([0xA, 0xB, 0xC, 0xD])
var foo = Data(bytes: bytes, count: 4)
print(hexString(foo)) // 0a0b0c0d
foo[1] <<= 1
print(hexString(foo)) // 0a160c0d
let bar = Data(bytes: [0xA, 0xB, 0xC, 0xD], count: 32)
print(hexString(bar)) // 0a000000000000000b000000000000000c000000000000000d00000000000000
我在原来的数据中定义了 bytes
,所以它们默认为 Int
a.k.a。 Int64
。提供 4 的数据长度会简单地忽略前 4 个字节数据之后的所有内容。
我想验证一些下载的数据未被修改。我的期望是,如果我修改原始数据,签名将失败。虽然这在某些情况下是正确的 (data2
),但令人惊讶的是在其他情况下却不起作用 (data3
)。使用散列/Digest
returns 相同的结果。
import CryptoKit
let rootKey = P256.Signing.PrivateKey()
let publicKey = rootKey.publicKey
let data = Data(bytes: [0xA, 0xB, 0xC, 0xD], count: 4)
let digest = SHA256.hash(data: data)
let signature = try rootKey.signature(for: data)
let hashSignature = try rootKey.signature(for: digest)
// now alter the data
let data2 = Data(bytes: [0x0, 0xB, 0xC, 0xD], count: 4)
let data3 = Data(bytes: [0xA, 0xB, 0xC, 0xE], count: 4)
publicKey.isValidSignature(signature, for: data) // true, as expected
publicKey.isValidSignature(signature, for: data2) // false, as expected
publicKey.isValidSignature(signature, for: data3) // why is THIS true/valid?
publicKey.isValidSignature(hashSignature, for: SHA256.hash(data: data)) // true
publicKey.isValidSignature(hashSignature, for: SHA256.hash(data: data2)) // false
publicKey.isValidSignature(hashSignature, for: SHA256.hash(data: data3)) // true
为简单起见,使用 CryptoKit
。这在(我的)CommonCrypto
/SecKey...
实现中也失败了。
好的,我发现了问题。您的代码 100% 正确。这个问题是由 Swift 中一些相当有问题的错误引起的 - 我 认为 。聪明的Swift高手请指正赐教!
顺便说一句:我正在使用 Xcode Version 12.2 beta 3 (12B5035g)
数据不平等错误
func testDataInequality() {
func hexString(_ data: Data) -> String {
data.map { String(format: "%02hhx", [=10=]) }.joined()
}
let data = Data(bytes: [0xA, 0xB, 0xC, 0xD], count: 4)
let data3 = Data(bytes: [0xA, 0xB, 0xC, 0xE], count: 4)
XCTAssertEqual(data.count, data3.count)
XCTAssertEqual(data.count, 4)
XCTAssertNotEqual(data, data3, "Expected 'data': \(hexString(data)) to NOT equal: 'data3': \(hexString(data3)), but it did.")
}
这个简单的单元测试失败了,但应该不会失败。意思是,data
和 data3
显然不一样,因为我们看到 [0xA, 0xB, 0xC, 0xD] != [0xA, 0xB, 0xC, 0xE]
。我们使用 XCTAssertNotEqual
断言它们不应该相等,但是这个断言失败了,这意味着 Swift 相信它们是相等的。
我使用嵌套方法hexString
分别打印了data
和data3
的内容,我们在运行测试[=56]时得到这个错误信息=]:
XCTAssertNotEqual failed: ("4 bytes") is equal to ("4 bytes") - Expected 'data': 0a000000 to NOT equal: 'data3': 0a000000, but it did.
我们可以看到 data
和 data3
都错误地取值:0a000000
,如 [0xa, 0x0, 0x0, 0x0]
.
更改为对数据使用已弃用的初始化程序:
@available(swift 4.2)
@available(swift, deprecated: 5, message: "use `init(_:)` instead")
public init<S>(bytes elements: S) where S : Sequence, S.Element == UInt8
而不是您使用的“正确”(未弃用)bytes:count
,我们得到正确的行为....
所以改为:
let data = Data(bytes: [0xA, 0xB, 0xC, 0xD])
let data3 = Data(bytes: [0xA, 0xB, 0xC, 0xE])
然后重新运行 测试,看看它是否有效。
此外,您可以添加这些断言:
XCTAssertEqual(hexString(data), "0a0b0c0d")
XCTAssertEqual(hexString(data3), "0a0b0c0e")
我会确保将此报告为 Swift 错误。
多亏了
let bytes = [UInt8]([0xA, 0xB, 0xC, 0xD])
var foo = Data(bytes: bytes, count: 4)
print(hexString(foo)) // 0a0b0c0d
foo[1] <<= 1
print(hexString(foo)) // 0a160c0d
let bar = Data(bytes: [0xA, 0xB, 0xC, 0xD], count: 32)
print(hexString(bar)) // 0a000000000000000b000000000000000c000000000000000d00000000000000
我在原来的数据中定义了 bytes
,所以它们默认为 Int
a.k.a。 Int64
。提供 4 的数据长度会简单地忽略前 4 个字节数据之后的所有内容。