Skip to content

Commit 7e99e02

Browse files
committed
Merge #3116
1 parent 924aaec commit 7e99e02

File tree

7 files changed

+83
-23
lines changed

7 files changed

+83
-23
lines changed
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
Copyright (c) 2020 Apple Inc. and the Swift project authors
4+
Licensed under Apache License v2.0 with Runtime Library Exception
5+
See http://swift.org/LICENSE.txt for license information
6+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
7+
*/
8+
9+
import TSCBasic
10+
11+
extension ByteString {
12+
/// A lowercase, hexadecimal representation of the SHA256 hash
13+
/// generated for the byte string's contents.
14+
///
15+
/// This property uses the CryptoKit implementation of
16+
/// Secure Hashing Algorithm 2 (SHA-2) hashing with a 256-bit digest, when available,
17+
/// falling back on a native implementation in Swift provided by TSCBasic.
18+
public var sha256Checksum: String {
19+
#if canImport(CryptoKit)
20+
if #available(macOS 10.15, *) {
21+
return CryptoKitSHA256().hash(self).hexadecimalRepresentation
22+
}
23+
#endif
24+
25+
return SHA256().hash(self).hexadecimalRepresentation
26+
}
27+
}

Sources/Basics/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors
88

99
add_library(Basics
10+
ByteString+Extensions.swift
1011
ConcurrencyHelpers.swift
1112
Dictionary+Extensions.swift
1213
DispatchTimeInterval+Extensions.swift

Sources/PackageLoading/ManifestLoader.swift

+21-19
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ public final class ManifestLoader: ManifestLoaderProtocol {
557557
key: ManifestCacheKey,
558558
cache: PersistentCacheProtocol
559559
) throws -> ManifestParseResult {
560-
let keyHash = try key.computeHash()
560+
let keyHash = ByteString(encodingAsUTF8: key.sha256Checksum)
561561
let cacheHit = try keyHash.withData {
562562
try cache.get(key: $0)
563563
}.flatMap {
@@ -588,6 +588,7 @@ public final class ManifestLoader: ManifestLoaderProtocol {
588588
let toolsVersion: ToolsVersion
589589
let env: [String: String]
590590
let swiftpmVersion: String
591+
let sha256Checksum: String
591592

592593
init (packageIdentity: PackageIdentity,
593594
manifestPath: AbsolutePath,
@@ -596,37 +597,38 @@ public final class ManifestLoader: ManifestLoaderProtocol {
596597
swiftpmVersion: String,
597598
fileSystem: FileSystem
598599
) throws {
600+
let manifestContents = try fileSystem.readFileContents(manifestPath).contents
601+
let sha256Checksum = try Self.computeSHA256Checksum(packageIdentity: packageIdentity, manifestContents: manifestContents, toolsVersion: toolsVersion, env: env, swiftpmVersion: swiftpmVersion)
602+
599603
self.packageIdentity = packageIdentity
600604
self.manifestPath = manifestPath
601-
self.manifestContents = try fileSystem.readFileContents(manifestPath).contents
605+
self.manifestContents = manifestContents
602606
self.toolsVersion = toolsVersion
603607
self.env = env
604608
self.swiftpmVersion = swiftpmVersion
609+
self.sha256Checksum = sha256Checksum
605610
}
606611

607-
// TODO: is there a way to avoid the dual hashing?
608612
func hash(into hasher: inout Hasher) {
609-
hasher.combine(self.packageIdentity)
610-
hasher.combine(self.manifestContents)
611-
hasher.combine(self.toolsVersion.description)
612-
for key in self.env.keys.sorted(by: >) {
613-
hasher.combine(key)
614-
hasher.combine(env[key]!)
615-
}
616-
hasher.combine(self.swiftpmVersion)
613+
hasher.combine(self.sha256Checksum)
617614
}
618615

619-
// TODO: is there a way to avoid the dual hashing?
620-
func computeHash() throws -> ByteString {
616+
private static func computeSHA256Checksum(
617+
packageIdentity: PackageIdentity,
618+
manifestContents: [UInt8],
619+
toolsVersion: ToolsVersion,
620+
env: [String: String],
621+
swiftpmVersion: String
622+
) throws -> String {
621623
let stream = BufferedOutputByteStream()
622-
stream <<< self.packageIdentity
623-
stream <<< self.manifestContents
624-
stream <<< self.toolsVersion.description
625-
for key in self.env.keys.sorted(by: >) {
624+
stream <<< packageIdentity
625+
stream <<< manifestContents
626+
stream <<< toolsVersion.description
627+
for key in env.keys.sorted(by: >) {
626628
stream <<< key <<< env[key]!
627629
}
628-
stream <<< self.swiftpmVersion
629-
return SHA256().hash(stream.bytes)
630+
stream <<< swiftpmVersion
631+
return stream.bytes.sha256Checksum
630632
}
631633
}
632634

Sources/SourceControl/Repository.swift

+2-3
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@ public struct RepositorySpecifier: Hashable, Codable {
2626
/// unique for each repository.
2727
public var fileSystemIdentifier: String {
2828
// Use first 8 chars of a stable hash.
29-
let hash = SHA256().hash(url).hexadecimalRepresentation
30-
let suffix = hash.dropLast(hash.count - 8)
29+
let suffix = ByteString(encodingAsUTF8: url).sha256Checksum.prefix(8)
3130

32-
return basename + "-" + suffix
31+
return "\(basename)-\(suffix)"
3332
}
3433

3534
/// Returns the cleaned basename for the specifier.

Sources/Workspace/Workspace.swift

+8
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,15 @@ public class Workspace {
311311
self.downloader = downloader
312312
self.netrcFilePath = netrcFilePath
313313
self.archiver = archiver
314+
315+
var checksumAlgorithm = checksumAlgorithm
316+
#if canImport(CryptoKit)
317+
if checksumAlgorithm is SHA256, #available(macOS 10.15, *) {
318+
checksumAlgorithm = CryptoKitSHA256()
319+
}
320+
#endif
314321
self.checksumAlgorithm = checksumAlgorithm
322+
315323
self.isResolverPrefetchingEnabled = isResolverPrefetchingEnabled
316324
self.skipUpdate = skipUpdate
317325
self.enableResolverTrace = enableResolverTrace

Sources/XCBuildSupport/PIF.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1205,7 +1205,7 @@ extension PIF {
12051205
func sign<T: PIFSignableObject & Encodable>(_ obj: T) throws {
12061206
let signatureContent = try encoder.encode(obj)
12071207
let bytes = ByteString(signatureContent)
1208-
obj.signature = SHA256().hash(bytes).hexadecimalRepresentation
1208+
obj.signature = bytes.sha256Checksum
12091209
}
12101210

12111211
let projects = workspace.projects
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2020 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
import Basics
12+
import TSCBasic
13+
import XCTest
14+
15+
final class ByteStringExtensionsTests: XCTestCase {
16+
func testSHA256Checksum() {
17+
let byteString = ByteString(encodingAsUTF8: "abc")
18+
XCTAssertEqual(byteString.contents, [0x61, 0x62, 0x63])
19+
20+
// See https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
21+
XCTAssertEqual(byteString.sha256Checksum, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
22+
}
23+
}

0 commit comments

Comments
 (0)