react-native-security-suite 0.1.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/LICENSE +1 -2
  2. package/README.md +40 -3
  3. package/android/build.gradle +85 -43
  4. package/android/gradle.properties +5 -0
  5. package/android/src/main/AndroidManifest.xml +1 -3
  6. package/android/src/main/AndroidManifestDeprecated.xml +3 -0
  7. package/android/src/main/java/com/securitysuite/SecuritySuiteModule.java +202 -0
  8. package/android/src/main/java/com/securitysuite/SecuritySuitePackage.java +28 -0
  9. package/android/src/main/java/com/securitysuite/StorageEncryption.java +52 -0
  10. package/ios/DataHashingMethods.swift +196 -0
  11. package/ios/SecuritySuite-Bridging-Header.h +1 -0
  12. package/ios/SecuritySuite.mm +26 -0
  13. package/ios/SecuritySuite.swift +129 -0
  14. package/ios/SecuritySuite.xcodeproj/project.pbxproj +13 -17
  15. package/ios/SecuritySuite.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
  16. package/ios/SecuritySuite.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  17. package/ios/SecuritySuite.xcodeproj/project.xcworkspace/xcuserdata/mohammadnavabi.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  18. package/ios/SecuritySuite.xcodeproj/xcuserdata/mohammadnavabi.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  19. package/ios/StorageEncryption.swift +81 -0
  20. package/lib/commonjs/helpers.js +16 -0
  21. package/lib/commonjs/helpers.js.map +1 -0
  22. package/lib/commonjs/index.js +158 -6
  23. package/lib/commonjs/index.js.map +1 -1
  24. package/lib/module/helpers.js +9 -0
  25. package/lib/module/helpers.js.map +1 -0
  26. package/lib/module/index.js +147 -1
  27. package/lib/module/index.js.map +1 -1
  28. package/lib/typescript/helpers.d.ts +2 -0
  29. package/lib/typescript/helpers.d.ts.map +1 -0
  30. package/lib/typescript/index.d.ts +20 -0
  31. package/lib/typescript/index.d.ts.map +1 -0
  32. package/package.json +54 -33
  33. package/react-native-security-suite.podspec +18 -2
  34. package/src/helpers.ts +8 -0
  35. package/src/index.tsx +203 -3
  36. package/android/src/main/java/com/reactnativesecuritysuite/SecuritySuiteModule.java +0 -38
  37. package/android/src/main/java/com/reactnativesecuritysuite/SecuritySuitePackage.java +0 -28
  38. package/ios/SecuritySuite.m +0 -12
@@ -0,0 +1,196 @@
1
+ //
2
+ // Data+HashingMethods.swift
3
+ //
4
+ // Created by Amir Sepehrom on 5/31/21.
5
+ //
6
+
7
+ import Foundation
8
+ import Security
9
+ import CommonCrypto
10
+
11
+ extension SecKey {
12
+
13
+ fileprivate subscript(attribute attr: CFString) -> Any? {
14
+ let attributes = SecKeyCopyAttributes(self) as? [CFString: Any]
15
+ return attributes?[attr]
16
+ }
17
+
18
+ /// Returns key length.
19
+ public var keySize: Int {
20
+ // swiftlint: disable force_cast
21
+ return self[attribute: kSecAttrKeySizeInBits] as! Int
22
+ }
23
+
24
+ /// Returns encryption method of key.
25
+ public var type: KeyType {
26
+ // swiftlint: disable force_cast
27
+ let type = self[attribute: kSecAttrType] as! CFString
28
+ return KeyType(rawValue: type)!
29
+ }
30
+
31
+ /// Public ASN1 header appropriate for current key.
32
+ fileprivate func asn1Header() throws -> Data {
33
+ return try type.asn1Header(keySize: keySize)
34
+ }
35
+
36
+ /// Exporable key data with ASN1 header.
37
+ public func bytes() throws -> Data {
38
+ return try asn1Header() + rawBytes()
39
+ }
40
+
41
+ /// Raw bytes for key that generated by Security framework.
42
+ public func rawBytes() throws -> Data {
43
+ var error: Unmanaged<CFError>?
44
+
45
+ guard let keyData = SecKeyCopyExternalRepresentation(self, &error) as Data? else {
46
+ throw error?.takeRetainedValue() ?? CryptographyError.invalidKey
47
+ }
48
+ return keyData
49
+ }
50
+
51
+ /// Encryption method
52
+ public enum KeyType: RawRepresentable {
53
+ /// Eliptic curve
54
+ case ec
55
+ /// RSA
56
+ case rsa
57
+
58
+ /// Initilize from kSecAttrKeyType string constant.
59
+ public init?(rawValue: CFString) {
60
+ switch rawValue {
61
+ case kSecAttrKeyTypeEC, kSecAttrKeyTypeECSECPrimeRandom:
62
+ self = .ec
63
+ case kSecAttrKeyTypeRSA:
64
+ self = .rsa
65
+ default:
66
+ return nil
67
+ }
68
+ }
69
+
70
+ /// kSecAttrKeyType counterpart of option.
71
+ public var rawValue: CFString {
72
+ switch self {
73
+ case .ec:
74
+ return kSecAttrKeyTypeECSECPrimeRandom
75
+ case .rsa:
76
+ return kSecAttrKeyTypeRSA
77
+ }
78
+ }
79
+
80
+ /// ASN1 headers for encrypting public keys.
81
+ public struct ASN1 {
82
+ public static let rsa2048 = Data(base64Encoded: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A")!
83
+ public static let rsa4096 = Data(base64Encoded: "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A")!
84
+ public static let ec256 = Data(base64Encoded: "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgA=")!
85
+ public static let ec384 = Data(base64Encoded: "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgA=")!
86
+ public static let ec521 = Data(base64Encoded: "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAA==")!
87
+ }
88
+
89
+ func asn1Header(keySize: Int) throws -> Data {
90
+ switch (self, keySize) {
91
+ case (.ec, 256):
92
+ return ASN1.ec256
93
+ case (.ec, 384):
94
+ return ASN1.ec384
95
+ case (.ec, 521):
96
+ return ASN1.ec521
97
+ case (.rsa, 2048):
98
+ return ASN1.rsa2048
99
+ case (.rsa, 4096):
100
+ return ASN1.rsa4096
101
+ default:
102
+ throw CryptographyError.unsupported
103
+ }
104
+ }
105
+ }
106
+ }
107
+
108
+ public enum CryptographyError: Error {
109
+ /// Key data is not valid or not conform to expected type and length.
110
+ case invalidKey
111
+ /// Encryption failed.
112
+ case failedEncryption
113
+ /// Decryption failed.
114
+ case failedDecryption
115
+ /// Data that passed to encrypt/decrypt is empty.
116
+ case emptyData
117
+ /// Encrypted data is not valid or encrypted with another key type.
118
+ case invalidData
119
+ /// Encryption/Decryption method is not supported.
120
+ case unsupported
121
+
122
+ // Enclave
123
+ /// Private key is not exist on the device enclave.
124
+ case keyNotFound
125
+ /// Operation with private key which saved in enclave is not posssible.
126
+ case notAllowed
127
+ }
128
+
129
+ public enum Digest: String {
130
+ case md5 = "MD5"
131
+ case sha1 = "SHA1"
132
+ case sha256 = "SHA256"
133
+ case sha384 = "SHA384"
134
+ case sha512 = "SHA512"
135
+
136
+ public var length: Int {
137
+ switch self {
138
+ case .md5:
139
+ return Int(CC_MD5_DIGEST_LENGTH)
140
+ case .sha1:
141
+ return Int(CC_SHA1_DIGEST_LENGTH)
142
+ case .sha256:
143
+ return Int(CC_SHA256_DIGEST_LENGTH)
144
+ case .sha384:
145
+ return Int(CC_SHA384_DIGEST_LENGTH)
146
+ case .sha512:
147
+ return Int(CC_SHA512_DIGEST_LENGTH)
148
+ }
149
+ }
150
+
151
+ public var hmacAlgorithm: CCHmacAlgorithm {
152
+ switch self {
153
+ case .md5:
154
+ return CCHmacAlgorithm(kCCHmacAlgMD5)
155
+ case .sha1:
156
+ return CCHmacAlgorithm(kCCHmacAlgSHA1)
157
+ case .sha256:
158
+ return CCHmacAlgorithm(kCCHmacAlgSHA256)
159
+ case .sha384:
160
+ return CCHmacAlgorithm(kCCHmacAlgSHA384)
161
+ case .sha512:
162
+ return CCHmacAlgorithm(kCCHmacAlgSHA512)
163
+ }
164
+ }
165
+ }
166
+
167
+ extension Data {
168
+ /**
169
+ Calculates hash digest of data.
170
+
171
+ - Parameter digest: digest type. Currently only SHA is supported.
172
+ - Returns: A data object with length equal to digest length.
173
+ */
174
+ public func hash(digest: Digest) -> Data {
175
+ guard !isEmpty else { return Data() }
176
+ var result = [UInt8](repeating: 0, count: digest.length)
177
+ self.withUnsafeBytes { (buf: UnsafeRawBufferPointer) -> Void in
178
+ let ptr = buf.baseAddress!
179
+ let dataLen = CC_LONG(buf.count)
180
+ switch digest {
181
+ case .md5:
182
+ CC_MD5(ptr, dataLen, &result)
183
+ case .sha1:
184
+ CC_SHA1(ptr, dataLen, &result)
185
+ case .sha256:
186
+ CC_SHA256(ptr, dataLen, &result)
187
+ case .sha384:
188
+ CC_SHA384(ptr, dataLen, &result)
189
+ case .sha512:
190
+ CC_SHA512(ptr, dataLen, &result)
191
+ }
192
+ }
193
+
194
+ return Data(result)
195
+ }
196
+ }
@@ -1,2 +1,3 @@
1
1
  #import <React/RCTBridgeModule.h>
2
2
  #import <React/RCTViewManager.h>
3
+ #import <CommonCrypto/CommonCrypto.h>
@@ -0,0 +1,26 @@
1
+ #import <React/RCTBridgeModule.h>
2
+
3
+ @interface RCT_EXTERN_MODULE(SecuritySuite, NSObject)
4
+
5
+ RCT_EXTERN_METHOD(getPublicKey:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
6
+
7
+ RCT_EXTERN_METHOD(getSharedKey:(NSString)serverPK withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
8
+
9
+ RCT_EXTERN_METHOD(encrypt:(NSString)input withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
10
+
11
+ RCT_EXTERN_METHOD(decrypt:(NSString)input withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
12
+
13
+ RCT_EXTERN_METHOD(getDeviceId:(RCTResponseSenderBlock)callback)
14
+
15
+ RCT_EXTERN_METHOD(storageEncrypt:(NSString)input withSecretKey:(NSString*)secretKey withHardEncryption:(BOOL)hardEncryption withCallback:(RCTResponseSenderBlock)callback)
16
+
17
+ RCT_EXTERN_METHOD(storageDecrypt:(NSString)input withSecretKey:(NSString*)secretKey withHardEncryption:(BOOL)hardEncryption withCallback:(RCTResponseSenderBlock)callback)
18
+
19
+ RCT_EXTERN_METHOD(deviceHasSecurityRisk:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
20
+
21
+ + (BOOL)requiresMainQueueSetup
22
+ {
23
+ return NO;
24
+ }
25
+
26
+ @end
@@ -1,7 +1,128 @@
1
1
  import IOSSecuritySuite
2
+ import Foundation
3
+ import CryptoKit
4
+ import SwiftUI
2
5
 
6
+ @available(iOS 13.0, *)
3
7
  @objc(SecuritySuite)
4
8
  class SecuritySuite: NSObject {
9
+ var privateKey: String!,
10
+ publicKey: String!,
11
+ sharedKey: String!,
12
+ keyData: Data!
13
+
14
+ @objc(getPublicKey:withRejecter:)
15
+ func getPublicKey(resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
16
+ do {
17
+ privateKey = P256.KeyAgreement.PrivateKey().rawRepresentation.base64EncodedString()
18
+ keyData = Data(base64Encoded: privateKey as! String)!
19
+ publicKey = try? (ASN1.ec256 + [0x04] + P256.KeyAgreement.PrivateKey(rawRepresentation: keyData).publicKey.rawRepresentation).base64EncodedString()
20
+
21
+ resolve(publicKey)
22
+ } catch {
23
+ reject("error", "GET_PUBLIC_KEY_ERROR", nil)
24
+ }
25
+ }
26
+
27
+ @objc(getSharedKey:withResolver:withRejecter:)
28
+ func getSharedKey(serverPK: NSString, resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
29
+ do {
30
+ print("privateKey", privateKey)
31
+ guard let serverPublicKeyData = Data(base64Encoded: serverPK as String),
32
+ let privateKeyData = Data(base64Encoded: privateKey as String) else { return }
33
+
34
+ sharedKey = try? P256.KeyAgreement.PrivateKey(rawRepresentation: privateKeyData).sharedSecretFromKeyAgreement(with: .init(rawRepresentation: serverPublicKeyData.dropFirst(ASN1.ec256.count + 1)))
35
+ .withUnsafeBytes({ Data(buffer: $0.bindMemory(to: UInt8.self)) })
36
+ .base64EncodedString()
37
+
38
+ resolve(sharedKey)
39
+ } catch {
40
+ reject("error", "GET_SHARED_KEY_ERROR", nil)
41
+ }
42
+ }
43
+
44
+ @objc(encrypt:withResolver:withRejecter:)
45
+ func encrypt(input: NSString, resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
46
+ do {
47
+ guard let keyData = Data(base64Encoded: sharedKey) else {
48
+ reject("error", "DECRYPT_SHARED_KEY_ERROR", nil)
49
+ return
50
+ }
51
+ let data = Data((input as String).utf8)
52
+ if keyData == nil {
53
+ reject("error", "keyData is null", nil)
54
+ return
55
+ }
56
+ let key = SymmetricKey(data: keyData)
57
+ let output = try? AES.GCM.seal(data, using: key).combined?.base64EncodedString()
58
+ resolve(output)
59
+ } catch {
60
+ reject("error", "ENCRYPT_ERROR", nil)
61
+ }
62
+ }
63
+
64
+ @objc(decrypt:withResolver:withRejecter:)
65
+ func decrypt(input: NSString, resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
66
+ do {
67
+ guard let keyData = Data(base64Encoded: sharedKey) else {
68
+ reject("error", "DECRYPT_SHARED_KEY_ERROR", nil)
69
+ return
70
+ }
71
+ guard let data = Data(base64Encoded: "\(input)") else {
72
+ reject("error", "INPUT_ERROR", nil)
73
+ return
74
+ }
75
+ let key = SymmetricKey(data: keyData)
76
+ let output = ( try? AES.GCM.open(.init(combined: data), using: key)).map({String(decoding: $0, as: UTF8.self)})
77
+
78
+ resolve(output)
79
+ } catch {
80
+ reject("error", "DECRYPT_ERROR", nil)
81
+ }
82
+ }
83
+
84
+ @objc(storageEncrypt:withSecretKey:withHardEncryption:withCallback:)
85
+ func storageEncrypt(input: NSString, secretKey: NSString, hardEncryption: Bool, callback: RCTResponseSenderBlock) -> Void {
86
+ do {
87
+ var encryptionKey = getDeviceId();
88
+ if secretKey != nil {
89
+ encryptionKey = secretKey as String;
90
+ }
91
+ let storageEncryption: StorageEncryption = StorageEncryption()
92
+ let encrypted = try? storageEncryption.encrypt(plain: "\(input)", encryptionKey: encryptionKey, hardEncryption: hardEncryption)
93
+ callback([encrypted, NSNull()])
94
+ } catch {
95
+ callback([NSNull(), "SOFT_DECRYPT_ERROR"])
96
+ }
97
+ }
98
+
99
+ @objc(storageDecrypt:withSecretKey:withHardEncryption:withCallback:)
100
+ func storageDecrypt(input: NSString, secretKey: NSString, hardEncryption: Bool, callback: RCTResponseSenderBlock) -> Void {
101
+ do {
102
+ var encryptionKey = getDeviceId()
103
+ if secretKey != nil {
104
+ encryptionKey = secretKey as String;
105
+ }
106
+ let storageEncryption: StorageEncryption = StorageEncryption()
107
+ let decrypted = try? storageEncryption.decrypt(decoded: "\(input)", encryptionKey: encryptionKey, hardEncryption: hardEncryption)
108
+ callback([decrypted, NSNull()])
109
+ } catch {
110
+ callback([NSNull(), "SOFT_DECRYPT_ERROR"])
111
+ }
112
+ }
113
+
114
+ @objc(getDeviceId:)
115
+ func getDeviceId(callback: RCTResponseSenderBlock) -> Void {
116
+ do {
117
+ callback([getDeviceId(), NSNull()]);
118
+ } catch {
119
+ callback([NSNull(), "GET_DEVICE_ID_ERROR"]);
120
+ }
121
+ }
122
+
123
+ func getDeviceId() -> String {
124
+ return UIDevice.current.identifierForVendor!.uuidString.replacingOccurrences(of: "-", with: "", options: [], range: nil)
125
+ }
5
126
 
6
127
  @objc(deviceHasSecurityRisk:withRejecter:)
7
128
  func deviceHasSecurityRisk(resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void {
@@ -13,3 +134,11 @@ class SecuritySuite: NSObject {
13
134
  }
14
135
  }
15
136
  }
137
+
138
+ struct ASN1 {
139
+ static let rsa2048 = Data(base64Encoded: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A")!
140
+ static let rsa4096 = Data(base64Encoded: "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A")!
141
+ static let ec256 = Data(base64Encoded: "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgA=")!
142
+ static let ec384 = Data(base64Encoded: "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgA=")!
143
+ static let ec521 = Data(base64Encoded: "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQ=")!
144
+ }
@@ -7,10 +7,9 @@
7
7
  objects = {
8
8
 
9
9
  /* Begin PBXBuildFile section */
10
-
11
- 5E555C0D2413F4C50049A1A2 /* SecuritySuite.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* SecuritySuite.m */; };
12
- F4FF95D7245B92E800C19C63 /* SecuritySuite.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FF95D6245B92E800C19C63 /* SecuritySuite.swift */; };
13
-
10
+ 48C650222A751374001FA3B0 /* StorageEncryption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48C650202A751374001FA3B0 /* StorageEncryption.swift */; };
11
+ 48C650232A751374001FA3B0 /* DataHashingMethods.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48C650212A751374001FA3B0 /* DataHashingMethods.swift */; };
12
+ F4FF95D7245B92E800C19C63 /* SecuritySuite.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FF95D6245B92E800C19C63 /* SecuritySuite.swift */; };
14
13
  /* End PBXBuildFile section */
15
14
 
16
15
  /* Begin PBXCopyFilesBuildPhase section */
@@ -27,11 +26,11 @@
27
26
 
28
27
  /* Begin PBXFileReference section */
29
28
  134814201AA4EA6300B7C361 /* libSecuritySuite.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecuritySuite.a; sourceTree = BUILT_PRODUCTS_DIR; };
30
-
31
- B3E7B5891CC2AC0600A0062D /* SecuritySuite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecuritySuite.m; sourceTree = "<group>"; };
29
+ 48C650202A751374001FA3B0 /* StorageEncryption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageEncryption.swift; sourceTree = "<group>"; };
30
+ 48C650212A751374001FA3B0 /* DataHashingMethods.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataHashingMethods.swift; sourceTree = "<group>"; };
31
+ B3E7B5891CC2AC0600A0062D /* SecuritySuite.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecuritySuite.mm; sourceTree = "<group>"; };
32
32
  F4FF95D5245B92E700C19C63 /* SecuritySuite-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SecuritySuite-Bridging-Header.h"; sourceTree = "<group>"; };
33
33
  F4FF95D6245B92E800C19C63 /* SecuritySuite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecuritySuite.swift; sourceTree = "<group>"; };
34
-
35
34
  /* End PBXFileReference section */
36
35
 
37
36
  /* Begin PBXFrameworksBuildPhase section */
@@ -56,11 +55,11 @@
56
55
  58B511D21A9E6C8500147676 = {
57
56
  isa = PBXGroup;
58
57
  children = (
59
-
60
58
  F4FF95D6245B92E800C19C63 /* SecuritySuite.swift */,
61
- B3E7B5891CC2AC0600A0062D /* SecuritySuite.m */,
59
+ B3E7B5891CC2AC0600A0062D /* SecuritySuite.mm */,
62
60
  F4FF95D5245B92E700C19C63 /* SecuritySuite-Bridging-Header.h */,
63
-
61
+ 48C650212A751374001FA3B0 /* DataHashingMethods.swift */,
62
+ 48C650202A751374001FA3B0 /* StorageEncryption.swift */,
64
63
  134814211AA4EA7D00B7C361 /* Products */,
65
64
  );
66
65
  sourceTree = "<group>";
@@ -122,10 +121,9 @@
122
121
  isa = PBXSourcesBuildPhase;
123
122
  buildActionMask = 2147483647;
124
123
  files = (
125
-
124
+ 48C650232A751374001FA3B0 /* DataHashingMethods.swift in Sources */,
125
+ 48C650222A751374001FA3B0 /* StorageEncryption.swift in Sources */,
126
126
  F4FF95D7245B92E800C19C63 /* SecuritySuite.swift in Sources */,
127
- B3E7B58A1CC2AC0600A0062D /* SecuritySuite.m in Sources */,
128
-
129
127
  );
130
128
  runOnlyForDeploymentPostprocessing = 0;
131
129
  };
@@ -160,6 +158,7 @@
160
158
  COPY_PHASE_STRIP = NO;
161
159
  ENABLE_STRICT_OBJC_MSGSEND = YES;
162
160
  ENABLE_TESTABILITY = YES;
161
+ "EXCLUDED_ARCHS[sdk=*]" = arm64;
163
162
  GCC_C_LANGUAGE_STANDARD = gnu99;
164
163
  GCC_DYNAMIC_NO_PIC = NO;
165
164
  GCC_NO_COMMON_BLOCKS = YES;
@@ -210,6 +209,7 @@
210
209
  COPY_PHASE_STRIP = YES;
211
210
  ENABLE_NS_ASSERTIONS = NO;
212
211
  ENABLE_STRICT_OBJC_MSGSEND = YES;
212
+ "EXCLUDED_ARCHS[sdk=*]" = arm64;
213
213
  GCC_C_LANGUAGE_STANDARD = gnu99;
214
214
  GCC_NO_COMMON_BLOCKS = YES;
215
215
  GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -238,11 +238,9 @@
238
238
  OTHER_LDFLAGS = "-ObjC";
239
239
  PRODUCT_NAME = SecuritySuite;
240
240
  SKIP_INSTALL = YES;
241
-
242
241
  SWIFT_OBJC_BRIDGING_HEADER = "SecuritySuite-Bridging-Header.h";
243
242
  SWIFT_OPTIMIZATION_LEVEL = "-Onone";
244
243
  SWIFT_VERSION = 5.0;
245
-
246
244
  };
247
245
  name = Debug;
248
246
  };
@@ -259,10 +257,8 @@
259
257
  OTHER_LDFLAGS = "-ObjC";
260
258
  PRODUCT_NAME = SecuritySuite;
261
259
  SKIP_INSTALL = YES;
262
-
263
260
  SWIFT_OBJC_BRIDGING_HEADER = "SecuritySuite-Bridging-Header.h";
264
261
  SWIFT_VERSION = 5.0;
265
-
266
262
  };
267
263
  name = Release;
268
264
  };
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Workspace
3
+ version = "1.0">
4
+ </Workspace>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>IDEDidComputeMac32BitWarning</key>
6
+ <true/>
7
+ </dict>
8
+ </plist>
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>SchemeUserState</key>
6
+ <dict>
7
+ <key>SecuritySuite.xcscheme_^#shared#^_</key>
8
+ <dict>
9
+ <key>orderHint</key>
10
+ <integer>0</integer>
11
+ </dict>
12
+ </dict>
13
+ </dict>
14
+ </plist>
@@ -0,0 +1,81 @@
1
+ //
2
+ // SoftEncryption.swift
3
+ // EncryptionSecurity
4
+ //
5
+ // Created by Mohammad on 5/9/1401 AP.
6
+ // Copyright © 1401 AP Facebook. All rights reserved.
7
+ //
8
+
9
+ import Foundation
10
+ import CryptoKit
11
+
12
+ @available(iOS 13.0, *)
13
+ class StorageEncryption {
14
+ let nonce = try! AES.GCM.Nonce(data: Data(base64Encoded: "bj1nixTVoYpSvpdA")!)
15
+
16
+ func encrypt(plain: String, encryptionKey: String, hardEncryption: Bool) throws -> String {
17
+ do {
18
+ guard let encryptionKeyData = Data(base64Encoded: encryptionKey) else {
19
+ return "Could not decode encryptionKey text: \(encryptionKey)"
20
+ }
21
+ guard let plainData = plain.data(using: .utf8) else {
22
+ return "Could not decode plain text: \(plain)"
23
+ }
24
+ let symmetricKey = SymmetricKey(data: encryptionKeyData)
25
+ var encrypted = try AES.GCM.seal(plainData, using: symmetricKey, nonce: nonce, authenticating: ASN1.ec256)
26
+ if (hardEncryption) {
27
+ encrypted = try AES.GCM.seal(plainData, using: symmetricKey)
28
+ }
29
+ return encrypted.combined!.base64EncodedString()
30
+ } catch let error {
31
+ return "Error encrypting message: \(error.localizedDescription)"
32
+ }
33
+ }
34
+
35
+ func decrypt(decoded: String, encryptionKey: String, hardEncryption: Bool) throws -> String {
36
+ do {
37
+ guard let encryptionKeyData = Data(base64Encoded: encryptionKey) else {
38
+ return "Could not decode encryption key: \(encryptionKey)"
39
+ }
40
+ guard let decodedData = Data(base64Encoded: decoded) else {
41
+ return "Could not decode decoded text: \(decoded)"
42
+ }
43
+ let symmetricKey = SymmetricKey(data: encryptionKeyData)
44
+ if (hardEncryption) {
45
+ let sealedBoxToOpen = try AES.GCM.SealedBox(combined: decodedData)
46
+ let decrypted = try AES.GCM.open(sealedBoxToOpen, using: symmetricKey)
47
+ return String(data: decrypted, encoding: .utf8)!
48
+ } else {
49
+ let sealedBoxRestored = try AES.GCM.SealedBox(combined: decodedData)
50
+ let decrypted = try AES.GCM.open(sealedBoxRestored, using: symmetricKey, authenticating: ASN1.ec256)
51
+ return String(data: decrypted, encoding: .utf8)!
52
+ }
53
+ } catch let error {
54
+ return "Error decrypting message: \(error.localizedDescription)"
55
+ }
56
+ }
57
+ }
58
+
59
+ public extension Data {
60
+ init?(hexString: String) {
61
+ let len = hexString.count / 2
62
+ var data = Data(capacity: len)
63
+ var i = hexString.startIndex
64
+ for _ in 0..<len {
65
+ let j = hexString.index(i, offsetBy: 2)
66
+ let bytes = hexString[i..<j]
67
+ if var num = UInt8(bytes, radix: 16) {
68
+ data.append(&num, count: 1)
69
+ } else {
70
+ return nil
71
+ }
72
+ i = j
73
+ }
74
+ self = data
75
+ }
76
+ /// Hexadecimal string representation of `Data` object.
77
+ var hexadecimal: String {
78
+ return map { String(format: "%02x", $0) }
79
+ .joined()
80
+ }
81
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isJsonString = void 0;
7
+ const isJsonString = value => {
8
+ try {
9
+ JSON.parse(value);
10
+ } catch (e) {
11
+ return false;
12
+ }
13
+ return true;
14
+ };
15
+ exports.isJsonString = isJsonString;
16
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["isJsonString","value","JSON","parse","e","exports"],"sourceRoot":"../../src","sources":["helpers.ts"],"mappings":";;;;;;AAAO,MAAMA,YAAY,GAAIC,KAAa,IAAc;EACtD,IAAI;IACFC,IAAI,CAACC,KAAK,CAACF,KAAK,CAAC;EACnB,CAAC,CAAC,OAAOG,CAAC,EAAE;IACV,OAAO,KAAK;EACd;EACA,OAAO,IAAI;AACb,CAAC;AAACC,OAAA,CAAAL,YAAA,GAAAA,YAAA"}