88 See http://swift.org/CONTRIBUTORS.txt for Swift project authors
99*/
1010
11+ public protocol HashAlgorithm {
12+
13+ /// Hashes the input bytes, returning the digest.
14+ ///
15+ /// - Parameters:
16+ /// - bytes: The input bytes.
17+ /// - Returns: The output digest.
18+ func hash( _ bytes: ByteString ) -> ByteString
19+ }
20+
21+ extension HashAlgorithm {
22+ public func hash( _ string: String ) -> ByteString {
23+ hash ( ByteString ( [ UInt8] ( string. utf8) ) )
24+ }
25+ }
26+
1127/// SHA-256 implementation from Secure Hash Algorithm 2 (SHA-2) set of
1228/// cryptographic hash functions (FIPS PUB 180-2).
13- public final class SHA256 {
29+ public struct SHA256 : HashAlgorithm {
1430
1531 /// The length of the output digest (in bits).
16- let digestLength = 256
32+ private static let digestLength = 256
1733
1834 /// The size of each blocks (in bits).
19- let blockBitSize = 512
35+ private static let blockBitSize = 512
2036
2137 /// The initial hash value.
2238 private static let initalHashValue : [ UInt32 ] = [
@@ -35,60 +51,28 @@ public final class SHA256 {
3551 0x748f82ee , 0x78a5636f , 0x84c87814 , 0x8cc70208 , 0x90befffa , 0xa4506ceb , 0xbef9a3f7 , 0xc67178f2
3652 ]
3753
38- /// The hash that is being computed.
39- private var hash = SHA256 . initalHashValue
40-
41- /// The input that was provided. It will be padded when computing the digest.
42- private var input : [ UInt8 ]
43-
44- /// The result, once computed.
45- private var result : [ UInt8 ] ?
46-
47- public init ( _ input: [ UInt8 ] ) {
48- self . input = input
54+ public init ( ) {
4955 }
5056
51- public init ( _ bytes: ByteString ) {
52- self . input = bytes. contents
53- }
54-
55- public init ( _ string: String ) {
56- self . input = [ UInt8] ( string. utf8)
57- }
58-
59- /// Returns the digest as hexadecimal string.
60- public func digestString( ) -> String {
61- return digest ( ) . reduce ( " " ) {
62- var str = String ( $1, radix: 16 )
63- // The above method does not do zero padding.
64- if str. count == 1 {
65- str = " 0 " + str
66- }
67- return $0 + str
68- }
69- }
70-
71- /// Returns the digest.
72- public func digest( ) -> [ UInt8 ] {
73-
74- // If we already have the result, we're done.
75- if let result = self . result {
76- return result
77- }
57+ public func hash( _ bytes: ByteString ) -> ByteString {
58+ var input = bytes. contents
7859
7960 // Pad the input.
8061 pad ( & input)
8162
8263 // Break the input into N 512-bit blocks.
83- let messageBlocks = input. blocks ( size: blockBitSize / 8 )
64+ let messageBlocks = input. blocks ( size: SHA256 . blockBitSize / 8 )
65+
66+ /// The hash that is being computed.
67+ var hash = SHA256 . initalHashValue
8468
8569 // Process each block.
8670 for block in messageBlocks {
87- process ( block)
71+ process ( block, hash : & hash )
8872 }
8973
9074 // Finally, compute the result.
91- var result = [ UInt8] ( repeating: 0 , count: digestLength / 8 )
75+ var result = [ UInt8] ( repeating: 0 , count: SHA256 . digestLength / 8 )
9276 for (idx, element) in hash. enumerated ( ) {
9377 let pos = idx * 4
9478 result [ pos + 0 ] = UInt8 ( ( element >> 24 ) & 0xff )
@@ -97,12 +81,11 @@ public final class SHA256 {
9781 result [ pos + 3 ] = UInt8 ( element & 0xff )
9882 }
9983
100- self . result = result
101- return result
84+ return ByteString ( result)
10285 }
10386
10487 /// Process and compute hash from a block.
105- private func process( _ block: ArraySlice < UInt8 > ) {
88+ private func process( _ block: ArraySlice < UInt8 > , hash : inout [ UInt32 ] ) {
10689
10790 // Compute message schedule.
10891 var W = [ UInt32] ( repeating: 0 , count: SHA256 . konstants. count)
0 commit comments