@@ -22,6 +22,9 @@ import Foundation
2222 typealias CC_LONG = size_t
2323#else
2424 import CommonCrypto
25+ #if canImport(CryptoKit)
26+ import CryptoKit
27+ #endif
2528#endif
2629
2730///
@@ -50,18 +53,26 @@ public class Digest: Updatable {
5053 ///
5154 public enum Algorithm {
5255
53- /// Message Digest 2 See: http://en.wikipedia.org/wiki/MD2_(cryptography)
54- case md2
55-
56- /// Message Digest 4
57- case md4
58-
56+ // Only available on Linux as Apple platforms consider them cryptographically insecure
57+ #if os(Linux)
58+ /// Message Digest 4
59+ case md4
60+
61+ /// Message Digest 5
62+ case md5
63+ #endif
64+
5965 /// Message Digest 5
60- case md5
61-
66+ /// - NOTE: Do NOT use for cryptography, considered insecure
67+ case md5_insecure
68+
6269 /// Secure Hash Algorithm 1
6370 case sha1
64-
71+
72+ /// Secure Hash Algorithm 1
73+ /// - NOTE: Do NOT use for cryptography, considered insecure
74+ case sha1_insecure
75+
6576 /// Secure Hash Algorithm 2 224-bit
6677 case sha224
6778
@@ -85,61 +96,61 @@ public class Digest: Updatable {
8596 public init ( using algorithm: Algorithm ) {
8697
8798 switch algorithm {
99+
100+ #if os(Linux)
101+ case . md4:
102+ self . engine = DigestEngineCC < MD4_CTX > ( initializer: MD4_Init, updater: MD4_Update, finalizer: MD4_Final, length: MD4_DIGEST_LENGTH)
103+
104+ case . md5, . md5_insecure:
105+ self . engine = DigestEngineCC < MD5_CTX > ( initializer: MD5_Init, updater: MD5_Update, finalizer: MD5_Final, length: MD5_DIGEST_LENGTH)
106+
107+ #else
88108
89- case . md2:
90- #if os(Linux)
91- fatalError ( " MD2 digest not supported by OpenSSL " )
92- #else
93- engine = DigestEngineCC < CC_MD2_CTX > ( initializer: CC_MD2_Init, updater: CC_MD2_Update, finalizer: CC_MD2_Final, length: CC_MD2_DIGEST_LENGTH)
94- #endif
95-
96- case . md4:
97- #if os(Linux)
98- engine = DigestEngineCC < MD4_CTX > ( initializer: MD4_Init, updater: MD4_Update, finalizer: MD4_Final, length: MD4_DIGEST_LENGTH)
99- #else
100- engine = DigestEngineCC < CC_MD4_CTX > ( initializer: CC_MD4_Init, updater: CC_MD4_Update, finalizer: CC_MD4_Final, length: CC_MD4_DIGEST_LENGTH)
101- #endif
102-
103- case . md5:
104- #if os(Linux)
105- engine = DigestEngineCC < MD5_CTX > ( initializer: MD5_Init, updater: MD5_Update, finalizer: MD5_Final, length: MD5_DIGEST_LENGTH)
106- #else
107- engine = DigestEngineCC < CC_MD5_CTX > ( initializer: CC_MD5_Init, updater: CC_MD5_Update, finalizer: CC_MD5_Final, length: CC_MD5_DIGEST_LENGTH)
108- #endif
109-
109+ case . md5_insecure:
110+ self . engine = DigestEngineMD5Insecure ( )
111+
112+ #endif
113+
110114 case . sha1:
111115 #if os(Linux)
112- engine = DigestEngineCC < SHA_CTX > ( initializer: SHA1_Init, updater: SHA1_Update, finalizer: SHA1_Final, length: SHA_DIGEST_LENGTH)
116+ self . engine = DigestEngineCC < SHA_CTX > ( initializer: SHA1_Init, updater: SHA1_Update, finalizer: SHA1_Final, length: SHA_DIGEST_LENGTH)
113117 #else
114118 engine = DigestEngineCC < CC_SHA1_CTX > ( initializer: CC_SHA1_Init, updater: CC_SHA1_Update, finalizer: CC_SHA1_Final, length: CC_SHA1_DIGEST_LENGTH)
115- #endif
116-
119+ #endif
120+
121+ case . sha1_insecure:
122+ #if os(Linux)
123+ self . engine = DigestEngineCC < SHA_CTX > ( initializer: SHA1_Init, updater: SHA1_Update, finalizer: SHA1_Final, length: SHA_DIGEST_LENGTH)
124+ #else
125+ self . engine = DigestEngineSHA1Insecure ( )
126+ #endif
127+
117128 case . sha224:
118129 #if os(Linux)
119- engine = DigestEngineCC < SHA256_CTX > ( initializer: SHA224_Init, updater: SHA224_Update, finalizer: SHA224_Final, length: SHA224_DIGEST_LENGTH)
130+ self . engine = DigestEngineCC < SHA256_CTX > ( initializer: SHA224_Init, updater: SHA224_Update, finalizer: SHA224_Final, length: SHA224_DIGEST_LENGTH)
120131 #else
121- engine = DigestEngineCC < CC_SHA256_CTX > ( initializer: CC_SHA224_Init, updater: CC_SHA224_Update, finalizer: CC_SHA224_Final, length: CC_SHA224_DIGEST_LENGTH)
132+ self . engine = DigestEngineCC < CC_SHA256_CTX > ( initializer: CC_SHA224_Init, updater: CC_SHA224_Update, finalizer: CC_SHA224_Final, length: CC_SHA224_DIGEST_LENGTH)
122133 #endif
123134
124135 case . sha256:
125136 #if os(Linux)
126- engine = DigestEngineCC < SHA256_CTX > ( initializer: SHA256_Init, updater: SHA256_Update, finalizer: SHA256_Final, length: SHA256_DIGEST_LENGTH)
137+ self . engine = DigestEngineCC < SHA256_CTX > ( initializer: SHA256_Init, updater: SHA256_Update, finalizer: SHA256_Final, length: SHA256_DIGEST_LENGTH)
127138 #else
128- engine = DigestEngineCC < CC_SHA256_CTX > ( initializer: CC_SHA256_Init, updater: CC_SHA256_Update, finalizer: CC_SHA256_Final, length: CC_SHA256_DIGEST_LENGTH)
139+ self . engine = DigestEngineCC < CC_SHA256_CTX > ( initializer: CC_SHA256_Init, updater: CC_SHA256_Update, finalizer: CC_SHA256_Final, length: CC_SHA256_DIGEST_LENGTH)
129140 #endif
130141
131142 case . sha384:
132143 #if os(Linux)
133- engine = DigestEngineCC < SHA512_CTX > ( initializer: SHA384_Init, updater: SHA384_Update, finalizer: SHA384_Final, length: SHA384_DIGEST_LENGTH)
144+ self . engine = DigestEngineCC < SHA512_CTX > ( initializer: SHA384_Init, updater: SHA384_Update, finalizer: SHA384_Final, length: SHA384_DIGEST_LENGTH)
134145 #else
135- engine = DigestEngineCC < CC_SHA512_CTX > ( initializer: CC_SHA384_Init, updater: CC_SHA384_Update, finalizer: CC_SHA384_Final, length: CC_SHA384_DIGEST_LENGTH)
146+ self . engine = DigestEngineCC < CC_SHA512_CTX > ( initializer: CC_SHA384_Init, updater: CC_SHA384_Update, finalizer: CC_SHA384_Final, length: CC_SHA384_DIGEST_LENGTH)
136147 #endif
137148
138149 case . sha512:
139150 #if os(Linux)
140- engine = DigestEngineCC < SHA512_CTX > ( initializer: SHA512_Init, updater: SHA512_Update, finalizer: SHA512_Final, length: SHA512_DIGEST_LENGTH)
151+ self . engine = DigestEngineCC < SHA512_CTX > ( initializer: SHA512_Init, updater: SHA512_Update, finalizer: SHA512_Final, length: SHA512_DIGEST_LENGTH)
141152 #else
142- engine = DigestEngineCC < CC_SHA512_CTX > ( initializer: CC_SHA512_Init, updater: CC_SHA512_Update, finalizer: CC_SHA512_Final, length: CC_SHA512_DIGEST_LENGTH)
153+ self . engine = DigestEngineCC < CC_SHA512_CTX > ( initializer: CC_SHA512_Init, updater: CC_SHA512_Update, finalizer: CC_SHA512_Final, length: CC_SHA512_DIGEST_LENGTH)
143154 #endif
144155 }
145156 }
@@ -269,6 +280,62 @@ private class DigestEngineCC<CTX>: DigestEngine {
269280}
270281
271282
283+ #if !os(Linux)
272284
285+ /**
286+ Wraps the Insecure.MD5 engine as a DigestEngine
287+ */
288+ private class DigestEngineMD5Insecure : DigestEngine {
289+ var engine = Insecure . MD5 ( )
290+
291+ func update( buffer: UnsafeRawPointer , byteCount: CC_LONG ) {
292+ guard byteCount<= Int . max else {
293+ fatalError ( " Cannot support byte count of size: \( byteCount) " )
294+ }
295+ let count = Int ( byteCount)
296+ let bufferPointer = UnsafeRawBufferPointer ( start: buffer, count: count)
297+ engine. update ( bufferPointer: bufferPointer)
298+ }
299+
300+ func final( ) -> [ UInt8 ] {
301+ let digest : Insecure . MD5Digest = self . engine. finalize ( )
302+ let digestLength = Int ( Insecure . MD5Digest. byteCount)
303+ var buffer = Array < UInt8 > ( repeating: 0 , count: digestLength)
304+ digest. withUnsafeBytes { ( rawBuffer: UnsafeRawBufferPointer ) in
305+ for (index, val) in rawBuffer. enumerated ( ) {
306+ buffer [ index] = val
307+ }
308+ }
309+ return buffer
310+ }
311+ }
273312
313+ /**
314+ Wraps the Insecure.SHA1 engine as a DigestEngine
315+ */
316+ private class DigestEngineSHA1Insecure : DigestEngine {
317+ var engine = Insecure . SHA1 ( )
318+
319+ func update( buffer: UnsafeRawPointer , byteCount: CC_LONG ) {
320+ guard byteCount<= Int . max else {
321+ fatalError ( " Cannot support byte count of size: \( byteCount) " )
322+ }
323+ let count = Int ( byteCount)
324+ let bufferPointer = UnsafeRawBufferPointer ( start: buffer, count: count)
325+ engine. update ( bufferPointer: bufferPointer)
326+ }
327+
328+ func final( ) -> [ UInt8 ] {
329+ let digest : Insecure . SHA1Digest = self . engine. finalize ( )
330+ let digestLength = Int ( Insecure . SHA1Digest. byteCount)
331+ var buffer = Array < UInt8 > ( repeating: 0 , count: digestLength)
332+ digest. withUnsafeBytes { ( rawBuffer: UnsafeRawBufferPointer ) in
333+ for (index, val) in rawBuffer. enumerated ( ) {
334+ buffer [ index] = val
335+ }
336+ }
337+ return buffer
338+ }
339+ }
274340
341+ #endif
0 commit comments