@@ -30,8 +30,29 @@ extension HashAlgorithm {
30
30
31
31
/// SHA-256 implementation from Secure Hash Algorithm 2 (SHA-2) set of
32
32
/// cryptographic hash functions (FIPS PUB 180-2).
33
+ /// Uses CryptoKit where available
33
34
public struct SHA256 : HashAlgorithm {
35
+ private let underlying : HashAlgorithm
34
36
37
+ public init ( ) {
38
+ #if canImport(CryptoKit)
39
+ if #available( macOS 10 . 15 , iOS 13 , tvOS 13 , watchOS 6 , * ) {
40
+ self . underlying = _CryptoKitSHA256 ( )
41
+ } else {
42
+ self . underlying = InternalSHA256 ( )
43
+ }
44
+ #else
45
+ self . underlying = InternalSHA256 ( )
46
+ #endif
47
+ }
48
+ public func hash( _ bytes: ByteString ) -> ByteString {
49
+ self . underlying. hash ( bytes)
50
+ }
51
+ }
52
+
53
+ /// SHA-256 implementation from Secure Hash Algorithm 2 (SHA-2) set of
54
+ /// cryptographic hash functions (FIPS PUB 180-2).
55
+ struct InternalSHA256 : HashAlgorithm {
35
56
/// The length of the output digest (in bits).
36
57
private static let digestLength = 256
37
58
@@ -65,18 +86,18 @@ public struct SHA256: HashAlgorithm {
65
86
pad ( & input)
66
87
67
88
// Break the input into N 512-bit blocks.
68
- let messageBlocks = input. blocks ( size: SHA256 . blockBitSize / 8 )
89
+ let messageBlocks = input. blocks ( size: Self . blockBitSize / 8 )
69
90
70
91
/// The hash that is being computed.
71
- var hash = SHA256 . initalHashValue
92
+ var hash = Self . initalHashValue
72
93
73
94
// Process each block.
74
95
for block in messageBlocks {
75
96
process ( block, hash: & hash)
76
97
}
77
98
78
99
// Finally, compute the result.
79
- var result = [ UInt8] ( repeating: 0 , count: SHA256 . digestLength / 8 )
100
+ var result = [ UInt8] ( repeating: 0 , count: Self . digestLength / 8 )
80
101
for (idx, element) in hash. enumerated ( ) {
81
102
let pos = idx * 4
82
103
result [ pos + 0 ] = UInt8 ( ( element >> 24 ) & 0xff )
@@ -92,7 +113,7 @@ public struct SHA256: HashAlgorithm {
92
113
private func process( _ block: ArraySlice < UInt8 > , hash: inout [ UInt32 ] ) {
93
114
94
115
// Compute message schedule.
95
- var W = [ UInt32] ( repeating: 0 , count: SHA256 . konstants. count)
116
+ var W = [ UInt32] ( repeating: 0 , count: Self . konstants. count)
96
117
for t in 0 ..< W . count {
97
118
switch t {
98
119
case 0 ... 15 :
@@ -119,10 +140,10 @@ public struct SHA256: HashAlgorithm {
119
140
var h = hash [ 7 ]
120
141
121
142
// Run the main algorithm.
122
- for t in 0 ..< SHA256 . konstants. count {
143
+ for t in 0 ..< Self . konstants. count {
123
144
let Σ1 = e. rotateRight ( by: 6 ) ^ e. rotateRight ( by: 11 ) ^ e. rotateRight ( by: 25 )
124
145
let ch = ( e & f) ^ ( ~ e & g)
125
- let t1 = h &+ Σ1 &+ ch &+ SHA256 . konstants [ t] &+ W [ t]
146
+ let t1 = h &+ Σ1 &+ ch &+ Self . konstants [ t] &+ W [ t]
126
147
127
148
let Σ0 = a. rotateRight ( by: 2 ) ^ a. rotateRight ( by: 13 ) ^ a. rotateRight ( by: 22 )
128
149
let maj = ( a & b) ^ ( a & c) ^ ( b & c)
@@ -173,23 +194,30 @@ public struct SHA256: HashAlgorithm {
173
194
}
174
195
}
175
196
176
- /// Wraps CryptoKit.SHA256 to provide a HashAlgorithm conformance to it.
197
+ #if canImport(CryptoKit)
198
+ @available ( * , deprecated, message: " use SHA256 which abstract over platform differences " )
177
199
@available ( macOS 10 . 15 , iOS 13 , tvOS 13 , watchOS 6 , * )
178
200
public struct CryptoKitSHA256 : HashAlgorithm {
179
- public init ( ) {
201
+ let underlying = _CryptoKitSHA256 ( )
202
+ public init ( ) { }
203
+ public func hash( _ bytes: ByteString ) -> ByteString {
204
+ self . underlying. hash ( bytes)
180
205
}
206
+ }
181
207
208
+ /// Wraps CryptoKit.SHA256 to provide a HashAlgorithm conformance to it.
209
+ @available ( macOS 10 . 15 , iOS 13 , tvOS 13 , watchOS 6 , * )
210
+ struct _CryptoKitSHA256 : HashAlgorithm {
211
+ public init ( ) {
212
+ }
182
213
public func hash( _ bytes: ByteString ) -> ByteString {
183
- #if canImport(CryptoKit)
184
214
return bytes. withData { data in
185
215
let digest = CryptoKit . SHA256. hash ( data: data)
186
216
return ByteString ( digest)
187
217
}
188
- #else
189
- fatalError ( " not supported on this platform " )
190
- #endif
191
218
}
192
219
}
220
+ #endif
193
221
194
222
// MARK:- Helpers
195
223
0 commit comments