├── .gitignore ├── .prettierrc.js ├── LICENSE ├── README.md ├── android ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── tectiv3 │ └── aes │ ├── Aes.java │ └── AesPackage.java ├── index.d.ts ├── index.js ├── ios ├── Aes.xcodeproj │ └── project.pbxproj └── Aes │ ├── Aes.h │ ├── Aes.m │ └── lib │ ├── AesCrypt.h │ └── AesCrypt.m ├── package.json └── react-native-aes.podspec /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | ios/Aes.xcodeproj/xcuserdata/* 3 | ios/Aes.xcodeproj/project.xcworkspace/* 4 | android/.idea/* 5 | android/.gradle/* 6 | android/build/* 7 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 100, 3 | tabWidth: 4, 4 | useTabs: false, 5 | semi: false, 6 | singleQuote: true, 7 | trailingComma: 'es5', 8 | bracketSpacing: true, 9 | jsxBracketSameLine: false, 10 | arrowParens: 'avoid', 11 | proseWrap: 'never', 12 | } 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 tectiv3 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Native AES 2 | 3 | AES encryption/decryption for react-native 4 | 5 | ## Installation 6 | 7 | ```sh 8 | npm install --save react-native-aes-crypto 9 | ``` 10 | 11 | or 12 | 13 | ```sh 14 | yarn add react-native-aes-crypto 15 | ``` 16 | 17 | ### Installation (iOS) 18 | 19 | ##### Using CocoaPods (React Native 0.60 and higher) 20 | 21 | ```sh 22 | cd ios 23 | pod install 24 | ``` 25 | 26 | ##### Using React Native Link (React Native 0.59 and lower) 27 | 28 | Run `react-native link react-native-aes-crypto` after which you should be able to use this library on iOS. 29 | 30 | ### Installation (Android) 31 | 32 | ##### React Native 0.60 and higher 33 | 34 | - Linking is done automatically 35 | 36 | ##### Using React Native Link (React Native 0.59 and lower) 37 | 38 | - In `android/settings.gradle` 39 | 40 | ```gradle 41 | ... 42 | include ':react-native-aes-crypto' 43 | project(':react-native-aes-crypto').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-aes-crypto/android') 44 | ``` 45 | 46 | - In `android/app/build.gradle` 47 | 48 | ```gradle 49 | ... 50 | dependencies { 51 | ... 52 | compile project(':react-native-aes-crypto') 53 | } 54 | ``` 55 | 56 | - register module (in MainApplication.java) 57 | 58 | ```java 59 | ...... 60 | import com.tectiv3.aes.AesPackage; 61 | 62 | ...... 63 | 64 | @Override 65 | protected List getPackages() { 66 | ...... 67 | new AesPackage(), 68 | // or 69 | // packages.add(new AesPackage()); 70 | ...... 71 | } 72 | ``` 73 | 74 | ## Usage 75 | 76 | ### Demo project 77 | 78 | [link](https://github.com/tectiv3/react-native-aes-demo) 79 | 80 | ### Example 81 | 82 | ```js 83 | import { NativeModules, Platform } from 'react-native' 84 | import Aes from 'react-native-aes-crypto' 85 | 86 | const generateKey = (password, salt, cost, length) => Aes.pbkdf2(password, salt, cost, length, 'sha256') 87 | 88 | const encryptData = (text, key) => { 89 | return Aes.randomKey(16).then(iv => { 90 | return Aes.encrypt(text, key, iv, 'aes-256-cbc').then(cipher => ({ 91 | cipher, 92 | iv, 93 | })) 94 | }) 95 | } 96 | 97 | const decryptData = (encryptedData, key) => Aes.decrypt(encryptedData.cipher, key, encryptedData.iv, 'aes-256-cbc') 98 | 99 | try { 100 | generateKey('Arnold', 'salt', 5000, 256).then(key => { 101 | console.log('Key:', key) 102 | encryptData('These violent delights have violent ends', key) 103 | .then(({ cipher, iv }) => { 104 | console.log('Encrypted:', cipher) 105 | 106 | decryptData({ cipher, iv }, key) 107 | .then(text => { 108 | console.log('Decrypted:', text) 109 | }) 110 | .catch(error => { 111 | console.log(error) 112 | }) 113 | 114 | Aes.hmac256(cipher, key).then(hash => { 115 | console.log('HMAC', hash) 116 | }) 117 | }) 118 | .catch(error => { 119 | console.log(error) 120 | }) 121 | }) 122 | } catch (e) { 123 | console.error(e) 124 | } 125 | ``` 126 | 127 | #### Or 128 | 129 | ```js 130 | async function asyncDecrypt(cipher, key, iv) { 131 | try { 132 | var text = await decryptData({ cipher, iv }, key) 133 | console.log(text) 134 | return text 135 | } catch (e) { 136 | console.error(e) 137 | } 138 | } 139 | ``` 140 | 141 | ### methods 142 | 143 | - `encrypt(text, key, iv, algorithm)` 144 | - `decrypt(base64, key, iv, algorithm)` 145 | - `pbkdf2(text, salt, cost, length, algorithm)` 146 | - `hmac256(cipher, key)` 147 | - `hmac512(cipher, key)` 148 | - `sha1(text)` 149 | - `sha256(text)` 150 | - `sha512(text)` 151 | - `randomUuid()` 152 | - `randomKey(length)` 153 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // android/build.gradle 2 | 3 | def safeExtGet(prop, fallback) { 4 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 5 | } 6 | 7 | buildscript { 8 | // The Android Gradle plugin is only required when opening the android folder stand-alone. 9 | // This avoids unnecessary downloads and potential conflicts when the library is included as a 10 | // module dependency in an application project. 11 | if (project == rootProject) { 12 | repositories { 13 | google() 14 | jcenter() 15 | } 16 | dependencies { 17 | classpath 'com.android.tools.build:gradle:4.0.1' 18 | } 19 | } 20 | } 21 | 22 | apply plugin: 'com.android.library' 23 | apply plugin: 'maven-publish' 24 | 25 | // Matches values in recent template from React Native 0.59 / 0.60 26 | // https://github.com/facebook/react-native/blob/0.59-stable/template/android/build.gradle#L5-L9 27 | // https://github.com/facebook/react-native/blob/0.60-stable/template/android/build.gradle#L5-L9 28 | def DEFAULT_COMPILE_SDK_VERSION = 28 29 | def DEFAULT_BUILD_TOOLS_VERSION = "28.0.3" 30 | def DEFAULT_MIN_SDK_VERSION = 16 31 | def DEFAULT_TARGET_SDK_VERSION = 28 32 | 33 | android { 34 | compileSdkVersion safeExtGet('compileSdkVersion', DEFAULT_COMPILE_SDK_VERSION) 35 | buildToolsVersion safeExtGet('buildToolsVersion', DEFAULT_BUILD_TOOLS_VERSION) 36 | defaultConfig { 37 | minSdkVersion safeExtGet('minSdkVersion', DEFAULT_MIN_SDK_VERSION) 38 | targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION) 39 | versionCode 1 40 | versionName "1.0" 41 | } 42 | lintOptions { 43 | abortOnError false 44 | } 45 | namespace = "com.tectiv3.aes" 46 | } 47 | 48 | repositories { 49 | mavenLocal() 50 | maven { 51 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 52 | url "$rootDir/../node_modules/react-native/android" 53 | } 54 | maven { 55 | // Android JSC is installed from npm 56 | url "$rootDir/../node_modules/jsc-android/dist" 57 | } 58 | google() 59 | jcenter() 60 | } 61 | 62 | dependencies { 63 | // ref: 64 | // https://github.com/facebook/react-native/blob/0.61-stable/template/android/app/build.gradle#L192 65 | //noinspection GradleDynamicVersion 66 | implementation 'com.facebook.react:react-native:+' // From node_modules 67 | implementation 'com.madgag.spongycastle:core:1.58.0.0' 68 | implementation 'com.madgag.spongycastle:prov:1.54.0.0' 69 | implementation 'com.madgag.spongycastle:pg:1.54.0.0' 70 | } 71 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /android/src/main/java/com/tectiv3/aes/Aes.java: -------------------------------------------------------------------------------- 1 | package com.tectiv3.aes; 2 | 3 | import android.widget.Toast; 4 | 5 | import java.io.IOException; 6 | import java.io.UnsupportedEncodingException; 7 | import java.security.SecureRandom; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | import java.util.UUID; 12 | 13 | import java.security.MessageDigest; 14 | import java.security.NoSuchAlgorithmException; 15 | import java.security.spec.InvalidKeySpecException; 16 | import java.security.InvalidKeyException; 17 | 18 | import javax.crypto.Cipher; 19 | import javax.crypto.SecretKey; 20 | import javax.crypto.spec.SecretKeySpec; 21 | import javax.crypto.spec.IvParameterSpec; 22 | import javax.crypto.spec.PBEKeySpec; 23 | import javax.crypto.SecretKeyFactory; 24 | import javax.crypto.Mac; 25 | 26 | import org.spongycastle.crypto.Digest; 27 | import org.spongycastle.crypto.digests.SHA1Digest; 28 | import org.spongycastle.crypto.digests.SHA256Digest; 29 | import org.spongycastle.crypto.digests.SHA512Digest; 30 | import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator; 31 | import org.spongycastle.crypto.params.KeyParameter; 32 | import org.spongycastle.util.encoders.Hex; 33 | 34 | import android.util.Base64; 35 | 36 | import com.facebook.react.bridge.NativeModule; 37 | import com.facebook.react.bridge.ReactApplicationContext; 38 | import com.facebook.react.bridge.Promise; 39 | import com.facebook.react.bridge.ReactContext; 40 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 41 | import com.facebook.react.bridge.ReactMethod; 42 | import com.facebook.react.bridge.Callback; 43 | 44 | public class Aes extends ReactContextBaseJavaModule { 45 | 46 | private static final String CIPHER_CBC_ALGORITHM = "AES/CBC/PKCS7Padding"; 47 | private static final String CIPHER_CTR_ALGORITHM = "AES/CTR/PKCS5Padding"; 48 | public static final String HMAC_SHA_256 = "HmacSHA256"; 49 | public static final String HMAC_SHA_512 = "HmacSHA512"; 50 | private static final String KEY_ALGORITHM = "AES"; 51 | 52 | public Aes(ReactApplicationContext reactContext) { 53 | super(reactContext); 54 | } 55 | 56 | @Override 57 | public String getName() { 58 | return "Aes"; 59 | } 60 | 61 | @ReactMethod 62 | public void encrypt(String data, String key, String iv, String algorithm, Promise promise) { 63 | try { 64 | String result = encrypt(data, key, iv, algorithm.toLowerCase().contains("cbc")?CIPHER_CBC_ALGORITHM:CIPHER_CTR_ALGORITHM); 65 | promise.resolve(result); 66 | } catch (Exception e) { 67 | promise.reject("-1", e.getMessage()); 68 | } 69 | } 70 | 71 | @ReactMethod 72 | public void decrypt(String data, String pwd, String iv, String algorithm, Promise promise) { 73 | try { 74 | String strs = decrypt(data, pwd, iv, algorithm.toLowerCase().contains("cbc")?CIPHER_CBC_ALGORITHM:CIPHER_CTR_ALGORITHM); 75 | promise.resolve(strs); 76 | } catch (Exception e) { 77 | promise.reject("-1", e.getMessage()); 78 | } 79 | } 80 | 81 | @ReactMethod(isBlockingSynchronousMethod = true) 82 | public String pbkdf2Sync(String pwd, String salt, Integer cost, Integer length, String algorithm) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeySpecException { 83 | return pbkdf2(pwd, salt, cost, length, algorithm); 84 | } 85 | 86 | @ReactMethod 87 | public void pbkdf2(String pwd, String salt, Integer cost, Integer length, String algorithm, Promise promise) { 88 | try { 89 | String strs = pbkdf2(pwd, salt, cost, length, algorithm); 90 | promise.resolve(strs); 91 | } catch (Exception e) { 92 | promise.reject("-1", e.getMessage()); 93 | } 94 | } 95 | 96 | @ReactMethod 97 | public void hmac256(String data, String pwd, Promise promise) { 98 | try { 99 | String strs = hmacX(data, pwd, HMAC_SHA_256); 100 | promise.resolve(strs); 101 | } catch (Exception e) { 102 | promise.reject("-1", e.getMessage()); 103 | } 104 | } 105 | 106 | @ReactMethod 107 | public void hmac512(String data, String pwd, Promise promise) { 108 | try { 109 | String strs = hmacX(data, pwd, HMAC_SHA_512); 110 | promise.resolve(strs); 111 | } catch (Exception e) { 112 | promise.reject("-1", e.getMessage()); 113 | } 114 | } 115 | 116 | @ReactMethod 117 | public void sha256(String data, Promise promise) { 118 | try { 119 | String result = shaX(data, "SHA-256"); 120 | promise.resolve(result); 121 | } catch (Exception e) { 122 | promise.reject("-1", e.getMessage()); 123 | } 124 | } 125 | 126 | @ReactMethod 127 | public void sha1(String data, Promise promise) { 128 | try { 129 | String result = shaX(data, "SHA-1"); 130 | promise.resolve(result); 131 | } catch (Exception e) { 132 | promise.reject("-1", e.getMessage()); 133 | } 134 | } 135 | 136 | @ReactMethod 137 | public void sha512(String data, Promise promise) { 138 | try { 139 | String result = shaX(data, "SHA-512"); 140 | promise.resolve(result); 141 | } catch (Exception e) { 142 | promise.reject("-1", e.getMessage()); 143 | } 144 | } 145 | 146 | @ReactMethod 147 | public void randomUuid(Promise promise) { 148 | try { 149 | String result = UUID.randomUUID().toString(); 150 | promise.resolve(result); 151 | } catch (Exception e) { 152 | promise.reject("-1", e.getMessage()); 153 | } 154 | } 155 | 156 | @ReactMethod 157 | public void randomKey(Integer length, Promise promise) { 158 | try { 159 | byte[] key = new byte[length]; 160 | SecureRandom rand = new SecureRandom(); 161 | rand.nextBytes(key); 162 | String keyHex = bytesToHex(key); 163 | promise.resolve(keyHex); 164 | } catch (Exception e) { 165 | promise.reject("-1", e.getMessage()); 166 | } 167 | } 168 | 169 | private String shaX(String data, String algorithm) throws Exception { 170 | MessageDigest md = MessageDigest.getInstance(algorithm); 171 | md.update(data.getBytes()); 172 | byte[] digest = md.digest(); 173 | return bytesToHex(digest); 174 | } 175 | 176 | public static String bytesToHex(byte[] bytes) { 177 | final char[] hexArray = "0123456789abcdef".toCharArray(); 178 | char[] hexChars = new char[bytes.length * 2]; 179 | for ( int j = 0; j < bytes.length; j++ ) { 180 | int v = bytes[j] & 0xFF; 181 | hexChars[j * 2] = hexArray[v >>> 4]; 182 | hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 183 | } 184 | return new String(hexChars); 185 | } 186 | private static String pbkdf2(String pwd, String salt, Integer cost, Integer length, String algorithm) 187 | throws NoSuchAlgorithmException, InvalidKeySpecException, UnsupportedEncodingException 188 | { 189 | Digest algorithmDigest = new SHA512Digest(); 190 | if (algorithm.equalsIgnoreCase("sha1")){ 191 | algorithmDigest = new SHA1Digest(); 192 | } 193 | if (algorithm.equalsIgnoreCase("sha256")){ 194 | algorithmDigest = new SHA256Digest(); 195 | } 196 | if (algorithm.equalsIgnoreCase("sha512")){ 197 | algorithmDigest = new SHA512Digest(); 198 | } 199 | PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(algorithmDigest); 200 | gen.init(pwd.getBytes("UTF_8"), salt.getBytes("UTF_8"), cost); 201 | byte[] key = ((KeyParameter) gen.generateDerivedParameters(length)).getKey(); 202 | return bytesToHex(key); 203 | } 204 | 205 | private static String hmacX(String text, String key, String algorithm) 206 | throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException 207 | { 208 | byte[] contentData = text.getBytes("UTF_8"); 209 | byte[] akHexData = Hex.decode(key); 210 | Mac sha_HMAC = Mac.getInstance(algorithm); 211 | SecretKey secret_key = new SecretKeySpec(akHexData, algorithm); 212 | sha_HMAC.init(secret_key); 213 | return bytesToHex(sha_HMAC.doFinal(contentData)); 214 | } 215 | 216 | final static IvParameterSpec emptyIvSpec = new IvParameterSpec(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); 217 | 218 | private static String encrypt(String text, String hexKey, String hexIv, String algorithm) throws Exception { 219 | if (text == null || text.length() == 0) { 220 | return null; 221 | } 222 | 223 | byte[] key = Hex.decode(hexKey); 224 | SecretKey secretKey = new SecretKeySpec(key, KEY_ALGORITHM); 225 | 226 | Cipher cipher = Cipher.getInstance(algorithm); 227 | cipher.init(Cipher.ENCRYPT_MODE, secretKey, hexIv == null ? emptyIvSpec : new IvParameterSpec(Hex.decode(hexIv))); 228 | byte[] encrypted = cipher.doFinal(text.getBytes("UTF-8")); 229 | return Base64.encodeToString(encrypted, Base64.NO_WRAP); 230 | } 231 | 232 | private static String decrypt(String ciphertext, String hexKey, String hexIv, String algorithm) throws Exception { 233 | if(ciphertext == null || ciphertext.length() == 0) { 234 | return null; 235 | } 236 | 237 | byte[] key = Hex.decode(hexKey); 238 | SecretKey secretKey = new SecretKeySpec(key, KEY_ALGORITHM); 239 | 240 | Cipher cipher = Cipher.getInstance(algorithm); 241 | cipher.init(Cipher.DECRYPT_MODE, secretKey, hexIv == null ? emptyIvSpec : new IvParameterSpec(Hex.decode(hexIv))); 242 | byte[] decrypted = cipher.doFinal(Base64.decode(ciphertext, Base64.NO_WRAP)); 243 | return new String(decrypted, "UTF-8"); 244 | } 245 | 246 | } 247 | -------------------------------------------------------------------------------- /android/src/main/java/com/tectiv3/aes/AesPackage.java: -------------------------------------------------------------------------------- 1 | package com.tectiv3.aes; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import com.facebook.react.ReactPackage; 8 | import com.facebook.react.bridge.JavaScriptModule; 9 | import com.facebook.react.bridge.NativeModule; 10 | import com.facebook.react.bridge.ReactApplicationContext; 11 | import com.facebook.react.uimanager.ViewManager; 12 | 13 | import com.tectiv3.aes.Aes; 14 | 15 | public class AesPackage implements ReactPackage { 16 | @Override 17 | public List createNativeModules(ReactApplicationContext reactContext) { 18 | return Arrays.asList( 19 | new Aes(reactContext) 20 | ); 21 | } 22 | 23 | public List> createJSModules() { 24 | return Collections.emptyList(); 25 | } 26 | 27 | @Override 28 | public List createViewManagers(ReactApplicationContext reactContext) { 29 | return Arrays.asList(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'react-native-aes-crypto' { 2 | type Algorithms = 'aes-128-cbc' | 'aes-192-cbc' | 'aes-256-cbc' | 'aes-128-ctr' | 'aes-192-ctr' | 'aes-256-ctr' 3 | type Algorithms_pbkdf2 = 'sha1' | 'sha256' | 'sha512' 4 | 5 | function pbkdf2(password: string, salt: string, cost: number, length: number, algorithm:Algorithms_pbkdf2): Promise 6 | function pbkdf2Sync(password: string, salt: string, cost: number, length: number, algorithm:Algorithms_pbkdf2): string 7 | function encrypt(text: string, key: string, iv: string, algorithm: Algorithms): Promise 8 | function decrypt(ciphertext: string, key: string, iv: string, algorithm: Algorithms): Promise 9 | function hmac256(ciphertext: string, key: string): Promise 10 | function hmac512(ciphertext: string, key: string): Promise 11 | function randomKey(length: number): Promise 12 | function randomUuid(): Promise 13 | function sha1(text: string): Promise 14 | function sha256(text: string): Promise 15 | function sha512(text: string): Promise 16 | } 17 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | import { NativeModules } from 'react-native' 3 | 4 | export default NativeModules.Aes 5 | -------------------------------------------------------------------------------- /ios/Aes.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 32D980E11BE9F11C00FA27E5 /* Aes.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 32D980E01BE9F11C00FA27E5 /* Aes.h */; }; 11 | 32D980E31BE9F11C00FA27E5 /* Aes.m in Sources */ = {isa = PBXBuildFile; fileRef = 32D980E21BE9F11C00FA27E5 /* Aes.m */; }; 12 | 9BE20B5B1E4E1A3700696172 /* AesCrypt.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BE20B5A1E4E1A3700696172 /* AesCrypt.m */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXCopyFilesBuildPhase section */ 16 | 32D980DB1BE9F11C00FA27E5 /* CopyFiles */ = { 17 | isa = PBXCopyFilesBuildPhase; 18 | buildActionMask = 2147483647; 19 | dstPath = "include/$(PRODUCT_NAME)"; 20 | dstSubfolderSpec = 16; 21 | files = ( 22 | 32D980E11BE9F11C00FA27E5 /* Aes.h in CopyFiles */, 23 | ); 24 | runOnlyForDeploymentPostprocessing = 0; 25 | }; 26 | /* End PBXCopyFilesBuildPhase section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 32D980DD1BE9F11C00FA27E5 /* libAes.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAes.a; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 32D980E01BE9F11C00FA27E5 /* Aes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Aes.h; sourceTree = ""; }; 31 | 32D980E21BE9F11C00FA27E5 /* Aes.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Aes.m; sourceTree = ""; }; 32 | 9BE20B591E4E1A3700696172 /* AesCrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AesCrypt.h; sourceTree = ""; }; 33 | 9BE20B5A1E4E1A3700696172 /* AesCrypt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AesCrypt.m; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | 32D980DA1BE9F11C00FA27E5 /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | 32D980D41BE9F11C00FA27E5 = { 48 | isa = PBXGroup; 49 | children = ( 50 | 32D980DF1BE9F11C00FA27E5 /* Aes */, 51 | 32D980DE1BE9F11C00FA27E5 /* Products */, 52 | ); 53 | sourceTree = ""; 54 | }; 55 | 32D980DE1BE9F11C00FA27E5 /* Products */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | 32D980DD1BE9F11C00FA27E5 /* libAes.a */, 59 | ); 60 | name = Products; 61 | sourceTree = ""; 62 | }; 63 | 32D980DF1BE9F11C00FA27E5 /* Aes */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 32D980E01BE9F11C00FA27E5 /* Aes.h */, 67 | 32D980E21BE9F11C00FA27E5 /* Aes.m */, 68 | 32D981161BE9F1B600FA27E5 /* lib */, 69 | ); 70 | path = Aes; 71 | sourceTree = ""; 72 | }; 73 | 32D981161BE9F1B600FA27E5 /* lib */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 9BE20B591E4E1A3700696172 /* AesCrypt.h */, 77 | 9BE20B5A1E4E1A3700696172 /* AesCrypt.m */, 78 | ); 79 | path = lib; 80 | sourceTree = ""; 81 | }; 82 | /* End PBXGroup section */ 83 | 84 | /* Begin PBXNativeTarget section */ 85 | 32D980DC1BE9F11C00FA27E5 /* Aes */ = { 86 | isa = PBXNativeTarget; 87 | buildConfigurationList = 32D980F11BE9F11C00FA27E5 /* Build configuration list for PBXNativeTarget "Aes" */; 88 | buildPhases = ( 89 | 32D980D91BE9F11C00FA27E5 /* Sources */, 90 | 32D980DA1BE9F11C00FA27E5 /* Frameworks */, 91 | 32D980DB1BE9F11C00FA27E5 /* CopyFiles */, 92 | ); 93 | buildRules = ( 94 | ); 95 | dependencies = ( 96 | ); 97 | name = Aes; 98 | productName = Aes; 99 | productReference = 32D980DD1BE9F11C00FA27E5 /* libAes.a */; 100 | productType = "com.apple.product-type.library.static"; 101 | }; 102 | /* End PBXNativeTarget section */ 103 | 104 | /* Begin PBXProject section */ 105 | 32D980D51BE9F11C00FA27E5 /* Project object */ = { 106 | isa = PBXProject; 107 | attributes = { 108 | LastUpgradeCheck = 1020; 109 | ORGANIZATIONNAME = tectiv3; 110 | TargetAttributes = { 111 | 32D980DC1BE9F11C00FA27E5 = { 112 | CreatedOnToolsVersion = 6.4; 113 | }; 114 | }; 115 | }; 116 | buildConfigurationList = 32D980D81BE9F11C00FA27E5 /* Build configuration list for PBXProject "Aes" */; 117 | compatibilityVersion = "Xcode 8.0"; 118 | developmentRegion = en; 119 | hasScannedForEncodings = 0; 120 | knownRegions = ( 121 | en, 122 | Base, 123 | ); 124 | mainGroup = 32D980D41BE9F11C00FA27E5; 125 | productRefGroup = 32D980DE1BE9F11C00FA27E5 /* Products */; 126 | projectDirPath = ""; 127 | projectRoot = ""; 128 | targets = ( 129 | 32D980DC1BE9F11C00FA27E5 /* Aes */, 130 | ); 131 | }; 132 | /* End PBXProject section */ 133 | 134 | /* Begin PBXSourcesBuildPhase section */ 135 | 32D980D91BE9F11C00FA27E5 /* Sources */ = { 136 | isa = PBXSourcesBuildPhase; 137 | buildActionMask = 2147483647; 138 | files = ( 139 | 9BE20B5B1E4E1A3700696172 /* AesCrypt.m in Sources */, 140 | 32D980E31BE9F11C00FA27E5 /* Aes.m in Sources */, 141 | ); 142 | runOnlyForDeploymentPostprocessing = 0; 143 | }; 144 | /* End PBXSourcesBuildPhase section */ 145 | 146 | /* Begin XCBuildConfiguration section */ 147 | 32D980EF1BE9F11C00FA27E5 /* Debug */ = { 148 | isa = XCBuildConfiguration; 149 | buildSettings = { 150 | ALWAYS_SEARCH_USER_PATHS = NO; 151 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 152 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 153 | CLANG_CXX_LIBRARY = "libc++"; 154 | CLANG_ENABLE_MODULES = YES; 155 | CLANG_ENABLE_OBJC_ARC = YES; 156 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 157 | CLANG_WARN_BOOL_CONVERSION = YES; 158 | CLANG_WARN_COMMA = YES; 159 | CLANG_WARN_CONSTANT_CONVERSION = YES; 160 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 161 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 162 | CLANG_WARN_EMPTY_BODY = YES; 163 | CLANG_WARN_ENUM_CONVERSION = YES; 164 | CLANG_WARN_INFINITE_RECURSION = YES; 165 | CLANG_WARN_INT_CONVERSION = YES; 166 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 167 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 168 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 169 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 170 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 171 | CLANG_WARN_STRICT_PROTOTYPES = YES; 172 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 173 | CLANG_WARN_UNREACHABLE_CODE = YES; 174 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 175 | COPY_PHASE_STRIP = NO; 176 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 177 | ENABLE_STRICT_OBJC_MSGSEND = YES; 178 | ENABLE_TESTABILITY = YES; 179 | GCC_C_LANGUAGE_STANDARD = gnu99; 180 | GCC_DYNAMIC_NO_PIC = NO; 181 | GCC_NO_COMMON_BLOCKS = YES; 182 | GCC_OPTIMIZATION_LEVEL = 0; 183 | GCC_PREPROCESSOR_DEFINITIONS = ( 184 | "DEBUG=1", 185 | "$(inherited)", 186 | ); 187 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 188 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 189 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 190 | GCC_WARN_UNDECLARED_SELECTOR = YES; 191 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 192 | GCC_WARN_UNUSED_FUNCTION = YES; 193 | GCC_WARN_UNUSED_VARIABLE = YES; 194 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 195 | MTL_ENABLE_DEBUG_INFO = YES; 196 | ONLY_ACTIVE_ARCH = YES; 197 | SDKROOT = iphoneos; 198 | }; 199 | name = Debug; 200 | }; 201 | 32D980F01BE9F11C00FA27E5 /* Release */ = { 202 | isa = XCBuildConfiguration; 203 | buildSettings = { 204 | ALWAYS_SEARCH_USER_PATHS = NO; 205 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 206 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 207 | CLANG_CXX_LIBRARY = "libc++"; 208 | CLANG_ENABLE_MODULES = YES; 209 | CLANG_ENABLE_OBJC_ARC = YES; 210 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 211 | CLANG_WARN_BOOL_CONVERSION = YES; 212 | CLANG_WARN_COMMA = YES; 213 | CLANG_WARN_CONSTANT_CONVERSION = YES; 214 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 215 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 216 | CLANG_WARN_EMPTY_BODY = YES; 217 | CLANG_WARN_ENUM_CONVERSION = YES; 218 | CLANG_WARN_INFINITE_RECURSION = YES; 219 | CLANG_WARN_INT_CONVERSION = YES; 220 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 221 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 222 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 223 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 224 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 225 | CLANG_WARN_STRICT_PROTOTYPES = YES; 226 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 227 | CLANG_WARN_UNREACHABLE_CODE = YES; 228 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 229 | COPY_PHASE_STRIP = NO; 230 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 231 | ENABLE_NS_ASSERTIONS = NO; 232 | ENABLE_STRICT_OBJC_MSGSEND = YES; 233 | GCC_C_LANGUAGE_STANDARD = gnu99; 234 | GCC_NO_COMMON_BLOCKS = YES; 235 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 236 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 237 | GCC_WARN_UNDECLARED_SELECTOR = YES; 238 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 239 | GCC_WARN_UNUSED_FUNCTION = YES; 240 | GCC_WARN_UNUSED_VARIABLE = YES; 241 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 242 | MTL_ENABLE_DEBUG_INFO = NO; 243 | SDKROOT = iphoneos; 244 | VALIDATE_PRODUCT = YES; 245 | }; 246 | name = Release; 247 | }; 248 | 32D980F21BE9F11C00FA27E5 /* Debug */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | HEADER_SEARCH_PATHS = ( 252 | "$(inherited)", 253 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 254 | "$(SRCROOT)/../../../react-native/React/**", 255 | "$(SRCROOT)/../../../../../node_modules/react-native/React/**", 256 | ); 257 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 258 | OTHER_LDFLAGS = "-ObjC"; 259 | PRODUCT_NAME = "$(TARGET_NAME)"; 260 | SKIP_INSTALL = YES; 261 | }; 262 | name = Debug; 263 | }; 264 | 32D980F31BE9F11C00FA27E5 /* Release */ = { 265 | isa = XCBuildConfiguration; 266 | buildSettings = { 267 | HEADER_SEARCH_PATHS = ( 268 | "$(inherited)", 269 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 270 | "$(SRCROOT)/../../../react-native/React/**", 271 | "$(SRCROOT)/../../../../../node_modules/react-native/React/**", 272 | ); 273 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 274 | OTHER_LDFLAGS = "-ObjC"; 275 | PRODUCT_NAME = "$(TARGET_NAME)"; 276 | SKIP_INSTALL = YES; 277 | }; 278 | name = Release; 279 | }; 280 | /* End XCBuildConfiguration section */ 281 | 282 | /* Begin XCConfigurationList section */ 283 | 32D980D81BE9F11C00FA27E5 /* Build configuration list for PBXProject "Aes" */ = { 284 | isa = XCConfigurationList; 285 | buildConfigurations = ( 286 | 32D980EF1BE9F11C00FA27E5 /* Debug */, 287 | 32D980F01BE9F11C00FA27E5 /* Release */, 288 | ); 289 | defaultConfigurationIsVisible = 0; 290 | defaultConfigurationName = Release; 291 | }; 292 | 32D980F11BE9F11C00FA27E5 /* Build configuration list for PBXNativeTarget "Aes" */ = { 293 | isa = XCConfigurationList; 294 | buildConfigurations = ( 295 | 32D980F21BE9F11C00FA27E5 /* Debug */, 296 | 32D980F31BE9F11C00FA27E5 /* Release */, 297 | ); 298 | defaultConfigurationIsVisible = 0; 299 | defaultConfigurationName = Release; 300 | }; 301 | /* End XCConfigurationList section */ 302 | }; 303 | rootObject = 32D980D51BE9F11C00FA27E5 /* Project object */; 304 | } 305 | -------------------------------------------------------------------------------- /ios/Aes/Aes.h: -------------------------------------------------------------------------------- 1 | // 2 | // Aes.h 3 | // Aes 4 | // 5 | // Created by tectiv3 on 10/02/17. 6 | // Copyright (c) 2017 tectiv3. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | 12 | @interface Aes : NSObject 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /ios/Aes/Aes.m: -------------------------------------------------------------------------------- 1 | // 2 | // Aes.m 3 | // Aes 4 | // 5 | // Created by tectiv3 on 10/02/17. 6 | // Copyright (c) 2017 tectiv3. All rights reserved. 7 | // 8 | 9 | 10 | #import "Aes.h" 11 | #import "AesCrypt.h" 12 | 13 | @implementation Aes 14 | 15 | RCT_EXPORT_MODULE() 16 | 17 | RCT_EXPORT_METHOD(encrypt:(NSString *)data key:(NSString *)key iv:(NSString *)iv algorithm:(NSString *)algorithm 18 | resolver:(RCTPromiseResolveBlock)resolve 19 | rejecter:(RCTPromiseRejectBlock)reject) { 20 | NSError *error = nil; 21 | NSString *base64 = [AesCrypt encrypt:data key:key iv:iv algorithm:algorithm]; 22 | if (base64 == nil) { 23 | reject(@"encrypt_fail", @"Encrypt error", error); 24 | } else { 25 | resolve(base64); 26 | } 27 | } 28 | 29 | RCT_EXPORT_METHOD(decrypt:(NSString *)base64 key:(NSString *)key iv:(NSString *)iv algorithm:(NSString *)algorithm 30 | resolver:(RCTPromiseResolveBlock)resolve 31 | rejecter:(RCTPromiseRejectBlock)reject) { 32 | NSError *error = nil; 33 | NSString *data = [AesCrypt decrypt:base64 key:key iv:iv algorithm:algorithm]; 34 | if (data == nil) { 35 | reject(@"decrypt_fail", @"Decrypt failed", error); 36 | } else { 37 | resolve(data); 38 | } 39 | } 40 | 41 | RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(pbkdf2Sync:(NSString *)password salt:(NSString *)salt 42 | cost:(NSInteger)cost length:(NSInteger)length algorithm:(NSString *)algorithm) { 43 | return [AesCrypt pbkdf2:password salt:salt cost:cost length:length algorithm:algorithm];; 44 | } 45 | 46 | RCT_EXPORT_METHOD(pbkdf2:(NSString *)password salt:(NSString *)salt 47 | cost:(NSInteger)cost length:(NSInteger)length algorithm:(NSString *)algorithm 48 | resolver:(RCTPromiseResolveBlock)resolve 49 | rejecter:(RCTPromiseRejectBlock)reject) { 50 | NSError *error = nil; 51 | NSString *data = [AesCrypt pbkdf2:password salt:salt cost:cost length:length algorithm:algorithm]; 52 | if (data == nil) { 53 | reject(@"keygen_fail", @"Key generation failed", error); 54 | } else { 55 | resolve(data); 56 | } 57 | } 58 | 59 | RCT_EXPORT_METHOD(hmac256:(NSString *)base64 key:(NSString *)key 60 | resolver:(RCTPromiseResolveBlock)resolve 61 | rejecter:(RCTPromiseRejectBlock)reject) { 62 | NSError *error = nil; 63 | NSString *data = [AesCrypt hmac256:base64 key:key]; 64 | if (data == nil) { 65 | reject(@"hmac_fail", @"HMAC error", error); 66 | } else { 67 | resolve(data); 68 | } 69 | } 70 | 71 | RCT_EXPORT_METHOD(hmac512:(NSString *)base64 key:(NSString *)key 72 | resolver:(RCTPromiseResolveBlock)resolve 73 | rejecter:(RCTPromiseRejectBlock)reject) { 74 | NSError *error = nil; 75 | NSString *data = [AesCrypt hmac512:base64 key:key]; 76 | if (data == nil) { 77 | reject(@"hmac_fail", @"HMAC error", error); 78 | } else { 79 | resolve(data); 80 | } 81 | } 82 | 83 | RCT_EXPORT_METHOD(sha1:(NSString *)text 84 | resolver:(RCTPromiseResolveBlock)resolve 85 | rejecter:(RCTPromiseRejectBlock)reject) { 86 | NSError *error = nil; 87 | NSString *data = [AesCrypt sha1:text]; 88 | if (data == nil) { 89 | reject(@"sha1_fail", @"Hash error", error); 90 | } else { 91 | resolve(data); 92 | } 93 | } 94 | 95 | RCT_EXPORT_METHOD(sha256:(NSString *)text 96 | resolver:(RCTPromiseResolveBlock)resolve 97 | rejecter:(RCTPromiseRejectBlock)reject) { 98 | NSError *error = nil; 99 | NSString *data = [AesCrypt sha256:text]; 100 | if (data == nil) { 101 | reject(@"sha256_fail", @"Hash error", error); 102 | } else { 103 | resolve(data); 104 | } 105 | } 106 | 107 | RCT_EXPORT_METHOD(sha512:(NSString *)text 108 | resolver:(RCTPromiseResolveBlock)resolve 109 | rejecter:(RCTPromiseRejectBlock)reject) { 110 | NSError *error = nil; 111 | NSString *data = [AesCrypt sha512:text]; 112 | if (data == nil) { 113 | reject(@"sha512_fail", @"Hash error", error); 114 | } else { 115 | resolve(data); 116 | } 117 | } 118 | 119 | RCT_EXPORT_METHOD(randomUuid:(RCTPromiseResolveBlock)resolve 120 | rejecter:(RCTPromiseRejectBlock)reject) { 121 | NSError *error = nil; 122 | NSString *data = [AesCrypt randomUuid]; 123 | if (data == nil) { 124 | reject(@"uuid_fail", @"Uuid error", error); 125 | } else { 126 | resolve(data); 127 | } 128 | } 129 | 130 | RCT_EXPORT_METHOD(randomKey:(NSInteger)length 131 | resolver:(RCTPromiseResolveBlock)resolve 132 | rejecter:(RCTPromiseRejectBlock)reject) { 133 | NSError *error = nil; 134 | NSString *data = [AesCrypt randomKey:length]; 135 | if (data == nil) { 136 | reject(@"random_fail", @"Random key error", error); 137 | } else { 138 | resolve(data); 139 | } 140 | } 141 | 142 | @end 143 | -------------------------------------------------------------------------------- /ios/Aes/lib/AesCrypt.h: -------------------------------------------------------------------------------- 1 | // 2 | // AesCrypt.h 3 | // 4 | // Created by tectiv3 on 10/02/17. 5 | // Copyright © 2017 tectiv3. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @interface AesCrypt : NSObject 11 | + (NSString *) encrypt: (NSString *)clearText key: (NSString *)key iv: (NSString *)iv algorithm: (NSString *)algorithm; 12 | + (NSString *) decrypt: (NSString *)cipherText key: (NSString *)key iv: (NSString *)iv algorithm: (NSString *)algorithm; 13 | + (NSString *) pbkdf2:(NSString *)password salt: (NSString *)salt cost: (NSInteger)cost length: (NSInteger)length algorithm:(NSString *)algorithm; 14 | + (NSString *) hmac256: (NSString *)input key: (NSString *)key; 15 | + (NSString *) hmac512: (NSString *)input key: (NSString *)key; 16 | + (NSString *) sha1: (NSString *)input; 17 | + (NSString *) sha256: (NSString *)input; 18 | + (NSString *) sha512: (NSString *)input; 19 | + (NSString *) toHex: (NSData *)nsdata; 20 | + (NSString *) randomUuid; 21 | + (NSString *) randomKey: (NSInteger)length; 22 | @end 23 | -------------------------------------------------------------------------------- /ios/Aes/lib/AesCrypt.m: -------------------------------------------------------------------------------- 1 | // 2 | // AesCrypt.m 3 | // 4 | // Created by tectiv3 on 10/02/17. 5 | // Copyright © 2017 tectiv3. All rights reserved. 6 | // 7 | 8 | #import 9 | #import 10 | #import 11 | 12 | #import "AesCrypt.h" 13 | 14 | @implementation AesCrypt 15 | 16 | + (NSString *) toHex:(NSData *)nsdata { 17 | const unsigned char *bytes = (const unsigned char *)nsdata.bytes; 18 | NSMutableString *hex = [NSMutableString new]; 19 | for (NSInteger i = 0; i < nsdata.length; i++) { 20 | [hex appendFormat:@"%02x", bytes[i]]; 21 | } 22 | return [hex copy]; 23 | } 24 | 25 | + (NSData *) fromHex: (NSString *)string { 26 | NSMutableData *data = [[NSMutableData alloc] init]; 27 | unsigned char whole_byte; 28 | char byte_chars[3] = {'\0','\0','\0'}; 29 | for (int i = 0; i < ([string length] / 2); i++) { 30 | byte_chars[0] = [string characterAtIndex:i*2]; 31 | byte_chars[1] = [string characterAtIndex:i*2+1]; 32 | whole_byte = strtol(byte_chars, NULL, 16); 33 | [data appendBytes:&whole_byte length:1]; 34 | } 35 | return data; 36 | } 37 | 38 | + (NSString *) pbkdf2:(NSString *)password salt: (NSString *)salt cost: (NSInteger)cost length: (NSInteger)length algorithm:(NSString *)algorithm{ 39 | // Data of String to generate Hash key(hexa decimal string). 40 | NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; 41 | NSData *saltData = [salt dataUsingEncoding:NSUTF8StringEncoding]; 42 | 43 | // Hash key (hexa decimal) string data length. 44 | NSMutableData *hashKeyData = [NSMutableData dataWithLength:length/8]; 45 | 46 | CCPseudoRandomAlgorithm algorithmL = kCCPRFHmacAlgSHA512; 47 | if([algorithm.lowercaseString isEqualToString:@"sha1"]){ 48 | algorithmL = kCCPRFHmacAlgSHA1; 49 | } 50 | if([algorithm.lowercaseString isEqualToString:@"sha256"]){ 51 | algorithmL = kCCPRFHmacAlgSHA256; 52 | } 53 | if([algorithm.lowercaseString isEqualToString:@"sha512"]){ 54 | algorithmL = kCCPRFHmacAlgSHA512; 55 | } 56 | // Key Derivation using PBKDF2 algorithm. 57 | int status = CCKeyDerivationPBKDF( 58 | kCCPBKDF2, 59 | passwordData.bytes, 60 | passwordData.length, 61 | saltData.bytes, 62 | saltData.length, 63 | algorithmL, 64 | (unsigned int)cost, 65 | hashKeyData.mutableBytes, 66 | hashKeyData.length); 67 | 68 | if (status == kCCParamError) { 69 | NSLog(@"Key derivation error"); 70 | return @""; 71 | } 72 | 73 | return [self toHex:hashKeyData]; 74 | } 75 | 76 | + (NSData *) AESCBC: (NSString *)operation data: (NSData *)data key: (NSString *)key iv: (NSString *)iv algorithm: (NSString *)algorithm { 77 | //convert hex string to hex data 78 | NSData *keyData = [self fromHex:key]; 79 | NSData *ivData = [self fromHex:iv]; 80 | // NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding]; 81 | size_t numBytes = 0; 82 | 83 | NSArray *aesAlgorithms = @[@"aes-128-cbc", @"aes-192-cbc", @"aes-256-cbc"]; 84 | size_t item = [aesAlgorithms indexOfObject:algorithm]; 85 | size_t keyLength; 86 | switch (item) { 87 | case 0: 88 | keyLength = kCCKeySizeAES128; 89 | break; 90 | case 1: 91 | keyLength = kCCKeySizeAES192; 92 | break; 93 | default: 94 | keyLength = kCCKeySizeAES256; 95 | break; 96 | } 97 | 98 | NSMutableData * buffer = [[NSMutableData alloc] initWithLength:[data length] + kCCBlockSizeAES128]; 99 | 100 | CCCryptorStatus cryptStatus = CCCrypt( 101 | [operation isEqualToString:@"encrypt"] ? kCCEncrypt : kCCDecrypt, 102 | kCCAlgorithmAES, 103 | kCCOptionPKCS7Padding, 104 | keyData.bytes, keyLength, 105 | ivData.length ? ivData.bytes : nil, 106 | data.bytes, data.length, 107 | buffer.mutableBytes, buffer.length, 108 | &numBytes); 109 | 110 | if (cryptStatus == kCCSuccess) { 111 | [buffer setLength:numBytes]; 112 | return buffer; 113 | } 114 | NSLog(@"AES error, %d", cryptStatus); 115 | return nil; 116 | } 117 | 118 | + (NSData *) AESCTR: (NSString *)operation data: (NSData *)data key: (NSString *)key iv: (NSString *)iv algorithm: (NSString *)algorithm { 119 | //convert hex string to hex data 120 | NSData *keyData = [self fromHex:key]; 121 | NSData *ivData = [self fromHex:iv]; 122 | // NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding]; 123 | size_t numBytes = 0; 124 | 125 | NSArray *aesAlgorithms = @[@"aes-128-ctr", @"aes-192-ctr", @"aes-256-ctr"]; 126 | size_t item = [aesAlgorithms indexOfObject:algorithm]; 127 | size_t keyLength; 128 | switch (item) { 129 | case 0: 130 | keyLength = kCCKeySizeAES128; 131 | break; 132 | case 1: 133 | keyLength = kCCKeySizeAES192; 134 | break; 135 | default: 136 | keyLength = kCCKeySizeAES256; 137 | break; 138 | } 139 | 140 | NSMutableData * buffer = [[NSMutableData alloc] initWithLength:[data length] + kCCBlockSizeAES128]; 141 | 142 | CCCryptorRef cryptor = NULL; 143 | 144 | CCCryptorStatus cryptStatus = CCCryptorCreateWithMode( 145 | [operation isEqualToString:@"encrypt"] ? kCCEncrypt : kCCDecrypt, 146 | kCCModeCTR, 147 | kCCAlgorithmAES, 148 | ccPKCS7Padding, 149 | ivData.length ? ivData.bytes : nil, 150 | keyData.bytes, 151 | keyLength, 152 | NULL, 153 | 0, 154 | 0, 155 | kCCModeOptionCTR_BE, 156 | &cryptor); 157 | 158 | if (cryptStatus == kCCSuccess) { 159 | //Update Cryptor 160 | CCCryptorStatus update = CCCryptorUpdate(cryptor, 161 | data.bytes, 162 | data.length, 163 | buffer.mutableBytes, 164 | buffer.length, 165 | &numBytes); 166 | if (update == kCCSuccess) 167 | { 168 | //Cut Data Out with nedded length 169 | buffer.length = numBytes; 170 | 171 | //Final Cryptor 172 | CCCryptorStatus final = CCCryptorFinal(cryptor, //CCCryptorRef cryptorRef, 173 | buffer.mutableBytes, //void *dataOut, 174 | buffer.length, // size_t dataOutAvailable, 175 | &numBytes); // size_t *dataOutMoved) 176 | 177 | if (final == kCCSuccess) 178 | { 179 | //Release Cryptor 180 | //CCCryptorStatus release = 181 | CCCryptorRelease(cryptor); //CCCryptorRef cryptorRef 182 | } 183 | return buffer; 184 | } 185 | } 186 | NSLog(@"AES error, %d", cryptStatus); 187 | return nil; 188 | } 189 | 190 | + (NSString *) encrypt: (NSString *)clearText key: (NSString *)key iv: (NSString *)iv algorithm: (NSString *)algorithm { 191 | if ([algorithm containsString:@"ctr"]) { 192 | NSData *result = [self AESCTR:@"encrypt" data:[clearText dataUsingEncoding:NSUTF8StringEncoding] key:key iv:iv algorithm:algorithm]; 193 | return [self toHex:result]; 194 | } 195 | else{ 196 | NSData *result = [self AESCBC:@"encrypt" data:[clearText dataUsingEncoding:NSUTF8StringEncoding] key:key iv:iv algorithm:algorithm]; 197 | return [result base64EncodedStringWithOptions:0]; 198 | } 199 | } 200 | 201 | + (NSString *) decrypt: (NSString *)cipherText key: (NSString *)key iv: (NSString *)iv algorithm: (NSString *)algorithm { 202 | if ([algorithm containsString:@"ctr"]) { 203 | NSData *result = [self AESCTR:@"decrypt" data:[self fromHex:cipherText] key:key iv:iv algorithm:algorithm]; 204 | return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding]; 205 | } 206 | else{ 207 | NSData *result = [self AESCBC:@"decrypt" data:[[NSData alloc] initWithBase64EncodedString:cipherText options:0] key:key iv:iv algorithm:algorithm]; 208 | return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding]; 209 | } 210 | } 211 | 212 | + (NSString *) hmac256: (NSString *)input key: (NSString *)key { 213 | NSData *keyData = [self fromHex:key]; 214 | NSData* inputData = [input dataUsingEncoding:NSUTF8StringEncoding]; 215 | void* buffer = malloc(CC_SHA256_DIGEST_LENGTH); 216 | CCHmac(kCCHmacAlgSHA256, [keyData bytes], [keyData length], [inputData bytes], [inputData length], buffer); 217 | NSData *nsdata = [NSData dataWithBytesNoCopy:buffer length:CC_SHA256_DIGEST_LENGTH freeWhenDone:YES]; 218 | return [self toHex:nsdata]; 219 | } 220 | 221 | + (NSString *) hmac512: (NSString *)input key: (NSString *)key { 222 | NSData *keyData = [self fromHex:key]; 223 | NSData* inputData = [input dataUsingEncoding:NSUTF8StringEncoding]; 224 | void* buffer = malloc(CC_SHA512_DIGEST_LENGTH); 225 | CCHmac(kCCHmacAlgSHA512, [keyData bytes], [keyData length], [inputData bytes], [inputData length], buffer); 226 | NSData *nsdata = [NSData dataWithBytesNoCopy:buffer length:CC_SHA512_DIGEST_LENGTH freeWhenDone:YES]; 227 | return [self toHex:nsdata]; 228 | } 229 | 230 | + (NSString *) sha1: (NSString *)input { 231 | NSData* inputData = [input dataUsingEncoding:NSUTF8StringEncoding]; 232 | NSMutableData *result = [[NSMutableData alloc] initWithLength:CC_SHA1_DIGEST_LENGTH]; 233 | CC_SHA1([inputData bytes], (CC_LONG)[inputData length], result.mutableBytes); 234 | return [self toHex:result]; 235 | } 236 | 237 | + (NSString *) sha256: (NSString *)input { 238 | NSData* inputData = [input dataUsingEncoding:NSUTF8StringEncoding]; 239 | unsigned char* buffer = malloc(CC_SHA256_DIGEST_LENGTH); 240 | CC_SHA256([inputData bytes], (CC_LONG)[inputData length], buffer); 241 | NSData *result = [NSData dataWithBytesNoCopy:buffer length:CC_SHA256_DIGEST_LENGTH freeWhenDone:YES]; 242 | return [self toHex:result]; 243 | } 244 | 245 | + (NSString *) sha512: (NSString *)input { 246 | NSData* inputData = [input dataUsingEncoding:NSUTF8StringEncoding]; 247 | unsigned char* buffer = malloc(CC_SHA512_DIGEST_LENGTH); 248 | CC_SHA512([inputData bytes], (CC_LONG)[inputData length], buffer); 249 | NSData *result = [NSData dataWithBytesNoCopy:buffer length:CC_SHA512_DIGEST_LENGTH freeWhenDone:YES]; 250 | return [self toHex:result]; 251 | } 252 | 253 | + (NSString *) randomUuid { 254 | return [[NSUUID UUID] UUIDString]; 255 | } 256 | 257 | + (NSString *) randomKey: (NSInteger)length { 258 | NSMutableData *data = [NSMutableData dataWithLength:length]; 259 | int result = SecRandomCopyBytes(kSecRandomDefault, length, data.mutableBytes); 260 | if (result != noErr) { 261 | return nil; 262 | } 263 | return [self toHex:data]; 264 | } 265 | 266 | @end 267 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-aes-crypto", 3 | "version": "3.2.1", 4 | "description": "AES crypto native module for react-native", 5 | "main": "index.js", 6 | "types": "index.d.ts", 7 | "author": "tectiv3", 8 | "license": "MIT", 9 | "keywords": [ 10 | "react-native", 11 | "react-component", 12 | "ios", 13 | "android", 14 | "aes", 15 | "crypto", 16 | "mobile", 17 | "async", 18 | "sha1", 19 | "sha256", 20 | "sha512", 21 | "pbkdf2", 22 | "hmac256", 23 | "hmac512", 24 | "uuid" 25 | ], 26 | "homepage": "https://github.com/tectiv3/react-native-aes", 27 | "bugs": { 28 | "url": "https://github.com/tectiv3/react-native-aes/issues" 29 | }, 30 | "repository": { 31 | "type": "git", 32 | "url": "git://github.com/tectiv3/react-native-aes.git" 33 | }, 34 | "scripts": { 35 | "test": "echo \"Error: no test specified\" && exit 1" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /react-native-aes.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | s.name = 'react-native-aes' 4 | s.version = '3.2.1' 5 | s.summary = 'Native module for AES encryption' 6 | s.author = "tectiv3" 7 | s.license = 'MIT' 8 | s.requires_arc = true 9 | s.homepage = "https://github.com/tectiv3/react-native-aes" 10 | s.source = { :git => 'https://github.com/tectiv3/react-native-aes', :tag => "v#{s.version}" } 11 | s.platforms = { :ios => "9.0", :visionos => "1.0" } 12 | s.source_files = "ios/**/*.{h,m}" 13 | 14 | s.dependency "React-Core" 15 | end 16 | --------------------------------------------------------------------------------