1 // Copyright 2022-present 650 Industries. All rights reserved.
2 
3 import CommonCrypto
4 import ExpoModulesCore
5 
6 public class CryptoModule: Module {
7   public func definition() -> ModuleDefinition {
8     name("ExpoCrypto")
9 
10     function("digestStringAsync", digestString)
11 
12     function("digestString", digestString)
13       .runSynchronously()
14   }
15 }
16 
17 private func digestString(algorithm: DigestAlgorithm, str: String, options: DigestOptions) throws -> String {
18   guard let data = str.data(using: .utf8) else {
19     throw LossyConversionException()
20   }
21 
22   let length = Int(algorithm.digestLength)
23   var digest = [UInt8](repeating: 0, count: length)
24 
25   data.withUnsafeBytes { bytes in
26     let _ = algorithm.digest(bytes.baseAddress, UInt32(data.count), &digest)
27   }
28 
29   switch options.encoding {
30   case .hex:
31     return digest.reduce("") { $0 + String(format: "%02x", $1) }
32   case .base64:
33     return Data(digest).base64EncodedString()
34   }
35 }
36 
37 private class LossyConversionException: Exception {
38   override var reason: String {
39     "Unable to convert given string without losing some information"
40   }
41 }
42