From 1367dc53ece02f1ff938eaad23a8820c8c5d8724 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Wed, 10 Jan 2024 13:01:18 -0800 Subject: [PATCH] Fix MD5 to operate over data (#221) --- .../AwsCommonRuntimeKit/crt/Checksums.swift | 4 +-- Source/AwsCommonRuntimeKit/crt/Hash.swift | 33 +++++++++---------- .../crt/ChecksumsTests.swift | 12 +++---- .../crt/HashTests.swift | 16 ++++----- .../http/HTTP2ClientConnectionTests.swift | 4 +-- 5 files changed, 34 insertions(+), 35 deletions(-) diff --git a/Source/AwsCommonRuntimeKit/crt/Checksums.swift b/Source/AwsCommonRuntimeKit/crt/Checksums.swift index a533de84c..66c31e631 100644 --- a/Source/AwsCommonRuntimeKit/crt/Checksums.swift +++ b/Source/AwsCommonRuntimeKit/crt/Checksums.swift @@ -8,7 +8,7 @@ extension Data { /// Computes the CRC32 over data. /// - Parameter previousCrc32: Pass 0 in the previousCrc32 parameter as an initial value unless continuing to update a running crc in a subsequent call. - public func crc32(previousCrc32: UInt32 = 0) -> UInt32 { + public func computeCRC32(previousCrc32: UInt32 = 0) -> UInt32 { self.withUnsafeBytes { bufferPointer in return aws_checksums_crc32(bufferPointer.baseAddress?.assumingMemoryBound(to: UInt8.self), Int32(count), @@ -18,7 +18,7 @@ extension Data { /// Computes the crc32c over data. /// - Parameter previousCrc32c: Pass 0 in the previousCrc32c parameter as an initial value unless continuing to update a running crc in a subsequent call. - public func crc32c(previousCrc32c: UInt32 = 0) -> UInt32 { + public func computeCRC32C(previousCrc32c: UInt32 = 0) -> UInt32 { self.withUnsafeBytes { bufferPointer in return aws_checksums_crc32c(bufferPointer.baseAddress?.assumingMemoryBound(to: UInt8.self), Int32(count), diff --git a/Source/AwsCommonRuntimeKit/crt/Hash.swift b/Source/AwsCommonRuntimeKit/crt/Hash.swift index c52d83437..d4d201e43 100644 --- a/Source/AwsCommonRuntimeKit/crt/Hash.swift +++ b/Source/AwsCommonRuntimeKit/crt/Hash.swift @@ -5,32 +5,31 @@ import struct Foundation.Data import struct Foundation.TimeInterval import AwsCCal -extension String { +extension Data { - /// Computes the md5 hash over input and writes the digest output to 'output'. Use this if you don't need to stream the data you're hashing and you can load + /// Computes the md5 hash over data. Use this if you don't need to stream the data you're hashing and you can load /// the entire input to hash into memory. /// - Parameter truncate: If you specify truncate something other than 0, the output will be truncated to that number of bytes. - public func base64EncodedMD5(truncate: Int = 0) throws -> String { - let bufferSize = 16 - var bufferData = Data(count: bufferSize) - try bufferData.withUnsafeMutableBytes { bufferPointer in - var buffer = aws_byte_buf_from_empty_array(bufferPointer.baseAddress, bufferSize) - guard self.withByteCursorPointer({ strCursorPointer in - aws_md5_compute(allocator.rawValue, strCursorPointer, &buffer, truncate) - }) == AWS_OP_SUCCESS else { - throw CommonRunTimeError.crtError(.makeFromLastError()) + public func computeMD5(truncate: Int = 0) throws -> Data { + try self.withUnsafeBytes { bufferPointer in + var byteCursor = aws_byte_cursor_from_array(bufferPointer.baseAddress, count) + + let bufferSize = 16 + var bufferData = Data(count: bufferSize) + try bufferData.withUnsafeMutableBytes { bufferPointer in + var buffer = aws_byte_buf_from_empty_array(bufferPointer.baseAddress, bufferSize) + guard aws_md5_compute(allocator.rawValue, &byteCursor, &buffer, truncate) == AWS_OP_SUCCESS else { + throw CommonRunTimeError.crtError(.makeFromLastError()) + } } + return bufferData } - return bufferData.base64EncodedString() } -} - -extension Data { /// Computes the sha256 hash over data. /// - Parameter truncate: If you specify truncate something other than 0, the output will be truncated to that number of bytes. For /// example, if you want a SHA256 digest as the first 16 bytes, set truncate to 16. - public func sha256(truncate: Int = 0) throws -> Data { + public func computeSHA256(truncate: Int = 0) throws -> Data { try self.withUnsafeBytes { bufferPointer in var byteCursor = aws_byte_cursor_from_array(bufferPointer.baseAddress, count) let bufferSize = Int(AWS_SHA256_LEN) @@ -48,7 +47,7 @@ extension Data { /// Computes the sha1 hash over data. /// - Parameter truncate: If you specify truncate something other than 0, the output will be truncated to that number of bytes. For /// example, if you want a SHA1 digest as the first 10 bytes, set truncate to 10. - public func sha1(truncate: Int = 0) throws -> Data { + public func computeSHA1(truncate: Int = 0) throws -> Data { try self.withUnsafeBytes { bufferPointer in var byteCursor = aws_byte_cursor_from_array(bufferPointer.baseAddress, count) let bufferSize = Int(AWS_SHA1_LEN) diff --git a/Test/AwsCommonRuntimeKitTests/crt/ChecksumsTests.swift b/Test/AwsCommonRuntimeKitTests/crt/ChecksumsTests.swift index b4b6c58e9..b1dbba4d7 100644 --- a/Test/AwsCommonRuntimeKitTests/crt/ChecksumsTests.swift +++ b/Test/AwsCommonRuntimeKitTests/crt/ChecksumsTests.swift @@ -7,15 +7,15 @@ import AwsCCommon class ChecksumsTests: XCBaseTestCase { func testCRC32() throws { - XCTAssertEqual("".data(using: .utf8)!.crc32(), 0) - XCTAssertEqual("Hello".data(using: .utf8)!.crc32(), 4157704578) - XCTAssertEqual("{\"foo\":\"base64 encoded sha1 checksum\"}".data(using: .utf8)!.crc32(), 1195144130) + XCTAssertEqual("".data(using: .utf8)!.computeCRC32(), 0) + XCTAssertEqual("Hello".data(using: .utf8)!.computeCRC32(), 4157704578) + XCTAssertEqual("{\"foo\":\"base64 encoded sha1 checksum\"}".data(using: .utf8)!.computeCRC32(), 1195144130) } func testCRC32C() throws { - XCTAssertEqual("".data(using: .utf8)!.crc32c(), 0) - XCTAssertEqual("Hello".data(using: .utf8)!.crc32c(), 2178485787) - XCTAssertEqual("{\"foo\":\"base64 encoded sha1 checksum\"}".data(using: .utf8)!.crc32c(), 3565301023) + XCTAssertEqual("".data(using: .utf8)!.computeCRC32C(), 0) + XCTAssertEqual("Hello".data(using: .utf8)!.computeCRC32C(), 2178485787) + XCTAssertEqual("{\"foo\":\"base64 encoded sha1 checksum\"}".data(using: .utf8)!.computeCRC32C(), 3565301023) } } diff --git a/Test/AwsCommonRuntimeKitTests/crt/HashTests.swift b/Test/AwsCommonRuntimeKitTests/crt/HashTests.swift index 310e7fb69..1b087ad35 100644 --- a/Test/AwsCommonRuntimeKitTests/crt/HashTests.swift +++ b/Test/AwsCommonRuntimeKitTests/crt/HashTests.swift @@ -8,27 +8,27 @@ class HashTests: XCBaseTestCase { func testMd5() throws { let hello = "Hello" - let md5 = try hello.base64EncodedMD5() + let md5 = try hello.data(using: .utf8)!.computeMD5().base64EncodedString() XCTAssertEqual(md5, "ixqZU8RhEpaoJ6v4xHgE1w==") } func testMd5Payload() throws { let payload = "{\"foo\":\"base64 encoded md5 checksum\"}" - let md5 = try payload.base64EncodedMD5() + let md5 = try payload.data(using: .utf8)!.computeMD5().base64EncodedString() XCTAssertEqual(md5, "iB0/3YSo7maijL0IGOgA9g==") } func testSha256() throws { let hello = "Hello".data(using: .utf8)! - let sha256 = try! hello.sha256().base64EncodedString() + let sha256 = try! hello.computeSHA256().base64EncodedString() XCTAssertEqual(sha256, "GF+NsyJx/iX1Yab8k4suJkMG7DBO2lGAB9F2SCY4GWk=") } func testSha256EmptyString() throws { let empty = "".data(using: .utf8)! - let sha256 = try! empty.sha256().base64EncodedString() + let sha256 = try! empty.computeSHA256().base64EncodedString() XCTAssertEqual(sha256, "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=") } @@ -36,7 +36,7 @@ class HashTests: XCBaseTestCase { var sha256Data: Data! = nil do { let payload = "{\"foo\":\"base64 encoded sha256 checksum\"}".data(using: .utf8)! - sha256Data = try! payload.sha256() + sha256Data = try! payload.computeSHA256() } XCTAssertEqual(sha256Data.base64EncodedString(), "lBSnDP4sj/yN8eIVOJlv+vC56hw+7JtN0132GiMQXRg=") } @@ -44,19 +44,19 @@ class HashTests: XCBaseTestCase { func testSha1() throws { let hello = "Hello".data(using: .utf8)! - XCTAssertEqual(try! hello.sha1().encodeToHexString(), "f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0") + XCTAssertEqual(try! hello.computeSHA1().encodeToHexString(), "f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0") } func testSha1EmptyString() throws { let empty = "".data(using: .utf8)! - XCTAssertEqual(try! empty.sha1().encodeToHexString(), "da39a3ee5e6b4b0d3255bfef95601890afd80709") + XCTAssertEqual(try! empty.computeSHA1().encodeToHexString(), "da39a3ee5e6b4b0d3255bfef95601890afd80709") } func testSha1PayloadOutOfScope() throws { var sha1Data: Data! = nil do { let payload = "{\"foo\":\"base64 encoded sha1 checksum\"}".data(using: .utf8)! - sha1Data = try! payload.sha1() + sha1Data = try! payload.computeSHA1() } XCTAssertEqual(sha1Data.encodeToHexString(), "bc3c579755c719da780d4429d6e9cf32f0c29c7e") } diff --git a/Test/AwsCommonRuntimeKitTests/http/HTTP2ClientConnectionTests.swift b/Test/AwsCommonRuntimeKitTests/http/HTTP2ClientConnectionTests.swift index db6390efe..fc41097ed 100644 --- a/Test/AwsCommonRuntimeKitTests/http/HTTP2ClientConnectionTests.swift +++ b/Test/AwsCommonRuntimeKitTests/http/HTTP2ClientConnectionTests.swift @@ -114,7 +114,7 @@ class HTTP2ClientConnectionTests: HTTPClientTestFixture { connectionManager: connectionManager, expectedVersion: expectedVersion, requestVersion: .version_2) - let actualSha = try response.body.sha256() + let actualSha = try response.body.computeSHA256() XCTAssertEqual( actualSha.encodeToHexString().uppercased(), "C7FDB5314B9742467B16BD5EA2F8012190B5E2C44A005F7984F89AAB58219534") @@ -129,7 +129,7 @@ class HTTP2ClientConnectionTests: HTTPClientTestFixture { connectionManager: connectionManager, expectedVersion: expectedVersion, requestVersion: .version_1_1) - let actualSha = try response.body.sha256() + let actualSha = try response.body.computeSHA256() XCTAssertEqual( actualSha.encodeToHexString().uppercased(), "C7FDB5314B9742467B16BD5EA2F8012190B5E2C44A005F7984F89AAB58219534")