Skip to content

Commit 636d71b

Browse files
committed
Merge branch 'cjthompson-master'
2 parents b6a4128 + 246bc94 commit 636d71b

11 files changed

Lines changed: 98 additions & 109 deletions

File tree

README.md

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ Testing [repository](https://github.com/ghbutton/react-native-simple-crypto-test
119119
import RNSimpleCrypto from "react-native-simple-crypto";
120120

121121
// -- AES ------------------------------------------------------------- //
122-
123122
const message = "data to encrypt";
124123
const messageArrayBuffer = RNSimpleCrypto.utils.convertUtf8ToArrayBuffer(
125124
message
@@ -150,30 +149,32 @@ console.log("AES decrypt", decrypted);
150149

151150
// -- HMAC ------------------------------------------------------------ //
152151

153-
const signatureArrayBuffer = await RNSimpleCrypto.HMAC.hmac256(message, key);
152+
const keyHmac = await RNSimpleCrypto.utils.randomBytes(32);
153+
const signatureArrayBuffer = await RNSimpleCrypto.HMAC.hmac256(message, keyHmac);
154154

155-
const signatureHex = RNSimpleCrypto.utils.convertArrayBuffertoHex(
155+
const signatureHex = RNSimpleCrypto.utils.convertArrayBufferToHex(
156156
signatureArrayBuffer
157157
);
158158
console.log("HMAC signature", signatureHex);
159159

160160
// -- SHA ------------------------------------------------------------- //
161161

162162
const sha1Hash = await RNSimpleCrypto.SHA.sha1("test");
163-
console.log("SHA1 hash", hash);
163+
console.log("SHA1 hash", sha1Hash);
164164

165-
const sha256Hash = await RNSimpleCrypto.SHA.sha1("test");
165+
const sha256Hash = await RNSimpleCrypto.SHA.sha256("test");
166166
console.log("SHA256 hash", sha256Hash);
167167

168-
const sha512Hash = await RNSimpleCrypto.SHA.sha1("test");
168+
const sha512Hash = await RNSimpleCrypto.SHA.sha512("test");
169169
console.log("SHA512 hash", sha512Hash);
170170

171171
const dataToHash = await RNSimpleCrypto.utils.randomBytes(64);
172172
const sha1ArrayBuffer = await RNSimpleCrypto.SHA.sha1(dataToHash);
173-
console.log('SHA256 hash bytes', [...sha1ArrayBuffer]);
173+
console.log('SHA256 hash bytes', sha1ArrayBuffer);
174174

175175
const sha256ArrayBuffer = await RNSimpleCrypto.SHA.sha256(dataToHash);
176-
console.log('SHA256 hash bytes', [...sha256ArrayBuffer]);
176+
console.log('SHA256 hash bytes', sha256ArrayBuffer);
177+
177178

178179
// -- PBKDF2 ---------------------------------------------------------- //
179180

@@ -182,14 +183,28 @@ const salt = RNSimpleCrypto.utils.randomBytes(8);
182183
const iterations = 4096;
183184
const keyInBytes = 32;
184185
const hash = "SHA1";
185-
const passwordKey = await Pbkdf2.hash(
186+
const passwordKey = await RNSimpleCrypto.PBKDF2.hash(
186187
password,
187188
salt,
188189
iterations,
189190
keyInBytes,
190191
hash
191192
);
192193
console.log("PBKDF2 passwordKey", passwordKey);
194+
const password2 = messageArrayBuffer;
195+
const salt2 = RNSimpleCrypto.utils.randomBytes(8);
196+
const iterations2 = 10000;
197+
const keyInBytes2 = 32;
198+
const hash2 = "SHA256";
199+
200+
const passwordKey2 = await RNSimpleCrypto.PBKDF2.hash(
201+
password2,
202+
salt2,
203+
iterations2,
204+
keyInBytes2,
205+
hash2
206+
);
207+
console.log("PBKDF2 passwordKey", passwordKey2);
193208

194209
// -- RSA ------------------------------------------------------------ //
195210

android/src/main/java/com/pedrouid/crypto/RCTAes.java

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -96,24 +96,13 @@ public void randomKey(Integer length, Promise promise) {
9696
byte[] key = new byte[length];
9797
SecureRandom rand = new SecureRandom();
9898
rand.nextBytes(key);
99-
String keyHex = bytesToHex(key);
99+
String keyHex = Util.bytesToHex(key);
100100
promise.resolve(keyHex);
101101
} catch (Exception e) {
102102
promise.reject("-1", e.getMessage());
103103
}
104104
}
105105

106-
public static String bytesToHex(byte[] bytes) {
107-
final char[] hexArray = "0123456789abcdef".toCharArray();
108-
char[] hexChars = new char[bytes.length * 2];
109-
for ( int j = 0; j < bytes.length; j++ ) {
110-
int v = bytes[j] & 0xFF;
111-
hexChars[j * 2] = hexArray[v >>> 4];
112-
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
113-
}
114-
return new String(hexChars);
115-
}
116-
117106
final static IvParameterSpec emptyIvSpec = new IvParameterSpec(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
118107

119108
private static String encrypt(String textBase64, String hexKey, String hexIv) throws Exception {
@@ -126,8 +115,7 @@ private static String encrypt(String textBase64, String hexKey, String hexIv) th
126115

127116
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
128117
cipher.init(Cipher.ENCRYPT_MODE, secretKey, hexIv == null ? emptyIvSpec : new IvParameterSpec(Hex.decode(hexIv)));
129-
byte [] textBytes = java.util.Base64.getDecoder().decode(textBase64);
130-
byte[] encrypted = cipher.doFinal(textBytes);
118+
byte[] encrypted = cipher.doFinal(Base64.decode(textBase64, Base64.DEFAULT));
131119
return Base64.encodeToString(encrypted, Base64.NO_WRAP);
132120
}
133121

@@ -141,7 +129,7 @@ private static String decrypt(String ciphertext, String hexKey, String hexIv) th
141129

142130
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
143131
cipher.init(Cipher.DECRYPT_MODE, secretKey, hexIv == null ? emptyIvSpec : new IvParameterSpec(Hex.decode(hexIv)));
144-
byte[] decrypted = cipher.doFinal(Base64.decode(ciphertext, Base64.NO_WRAP));
132+
byte[] decrypted = cipher.doFinal(Base64.decode(ciphertext, Base64.DEFAULT));
145133
return Base64.encodeToString(decrypted, Base64.NO_WRAP);
146134
}
147135

android/src/main/java/com/pedrouid/crypto/RCTHmac.java

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,23 +69,12 @@ public void hmac256(String data, String pwd, Promise promise) {
6969
}
7070
}
7171

72-
public static String bytesToHex(byte[] bytes) {
73-
final char[] hexArray = "0123456789abcdef".toCharArray();
74-
char[] hexChars = new char[bytes.length * 2];
75-
for ( int j = 0; j < bytes.length; j++ ) {
76-
int v = bytes[j] & 0xFF;
77-
hexChars[j * 2] = hexArray[v >>> 4];
78-
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
79-
}
80-
return new String(hexChars);
81-
}
82-
8372
private static String hmac256(String text, String key) throws NoSuchAlgorithmException, InvalidKeyException {
8473
byte[] contentData = Hex.decode(text);
8574
byte[] akHexData = Hex.decode(key);
8675
Mac sha256_HMAC = Mac.getInstance(HMAC_SHA_256);
8776
SecretKey secret_key = new SecretKeySpec(akHexData, HMAC_SHA_256);
8877
sha256_HMAC.init(secret_key);
89-
return bytesToHex(sha256_HMAC.doFinal(contentData));
78+
return Util.bytesToHex(sha256_HMAC.doFinal(contentData));
9079
}
9180
}
Lines changed: 21 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,25 @@
11
package com.pedrouid.crypto;
22

3-
import android.widget.Toast;
4-
5-
import java.io.IOException;
6-
import java.security.SecureRandom;
7-
import java.util.HashMap;
8-
import java.util.Map;
9-
10-
import java.util.UUID;
11-
12-
import java.security.MessageDigest;
13-
import java.security.NoSuchAlgorithmException;
14-
import java.security.spec.InvalidKeySpecException;
15-
import java.security.InvalidKeyException;
16-
17-
import java.nio.charset.StandardCharsets;
3+
import android.util.Base64;
184

19-
import javax.crypto.Cipher;
20-
import javax.crypto.SecretKey;
21-
import javax.crypto.spec.SecretKeySpec;
22-
import javax.crypto.spec.IvParameterSpec;
23-
import javax.crypto.spec.PBEKeySpec;
24-
import javax.crypto.SecretKeyFactory;
25-
import javax.crypto.Mac;
5+
import com.facebook.react.bridge.Promise;
6+
import com.facebook.react.bridge.ReactApplicationContext;
7+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
8+
import com.facebook.react.bridge.ReactMethod;
269

2710
import org.spongycastle.crypto.ExtendedDigest;
11+
import org.spongycastle.crypto.PBEParametersGenerator;
2812
import org.spongycastle.crypto.digests.SHA1Digest;
2913
import org.spongycastle.crypto.digests.SHA224Digest;
3014
import org.spongycastle.crypto.digests.SHA256Digest;
3115
import org.spongycastle.crypto.digests.SHA384Digest;
32-
import org.spongycastle.crypto.digests.SHA384Digest;
3316
import org.spongycastle.crypto.digests.SHA512Digest;
3417
import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator;
35-
import org.spongycastle.crypto.PBEParametersGenerator;
3618
import org.spongycastle.crypto.params.KeyParameter;
37-
import org.spongycastle.util.encoders.Hex;
3819

39-
import android.util.Base64;
40-
41-
import com.facebook.react.bridge.NativeModule;
42-
import com.facebook.react.bridge.ReactApplicationContext;
43-
import com.facebook.react.bridge.Promise;
44-
import com.facebook.react.bridge.ReactContext;
45-
import com.facebook.react.bridge.ReactContextBaseJavaModule;
46-
import com.facebook.react.bridge.ReactMethod;
47-
import com.facebook.react.bridge.Callback;
20+
import java.security.NoSuchAlgorithmException;
21+
import java.util.HashMap;
22+
import java.util.Map;
4823

4924
public class RCTPbkdf2 extends ReactContextBaseJavaModule {
5025

@@ -58,27 +33,18 @@ public String getName() {
5833
}
5934

6035
@ReactMethod
61-
public void hash(String pwd, String saltBase64, Integer iterations, Integer keyLen, String hash, Promise promise) {
36+
public void hash(String pwdBase64, String saltBase64, Integer iterations, Integer keyLen, String hash, Promise promise) {
6237
try {
63-
String strs = pbkdf2(pwd, saltBase64, iterations, keyLen, hash);
64-
promise.resolve(strs);
38+
byte[] pwdBytes = Base64.decode(pwdBase64, Base64.DEFAULT);
39+
byte[] saltBytes = Base64.decode(saltBase64, Base64.DEFAULT);
40+
byte[] digest = pbkdf2(pwdBytes, saltBytes, iterations, keyLen, hash);
41+
promise.resolve(Base64.encodeToString(digest, Base64.NO_WRAP));
6542
} catch (Exception e) {
6643
promise.reject("-1", e.getMessage());
6744
}
6845
}
6946

70-
public static String bytesToHex(byte[] bytes) {
71-
final char[] hexArray = "0123456789abcdef".toCharArray();
72-
char[] hexChars = new char[bytes.length * 2];
73-
for ( int j = 0; j < bytes.length; j++ ) {
74-
int v = bytes[j] & 0xFF;
75-
hexChars[j * 2] = hexArray[v >>> 4];
76-
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
77-
}
78-
return new String(hexChars);
79-
}
80-
81-
private static String pbkdf2(String pwd, String salt, Integer iterations, Integer keyLen, String hash) throws NoSuchAlgorithmException, InvalidKeySpecException {
47+
private static byte[] pbkdf2(byte[] pwd, byte[] salt, Integer iterations, Integer keyLen, String hash) throws NullPointerException, NoSuchAlgorithmException {
8248
Map<String, ExtendedDigest> algMap = new HashMap<String, ExtendedDigest>();
8349
algMap.put("SHA1", new SHA1Digest());
8450
algMap.put("SHA224", new SHA224Digest());
@@ -87,10 +53,12 @@ private static String pbkdf2(String pwd, String salt, Integer iterations, Intege
8753
algMap.put("SHA512", new SHA512Digest());
8854
ExtendedDigest alg = algMap.get(hash);
8955

56+
if (alg == null) {
57+
throw new NoSuchAlgorithmException("Specified hash algorithm is not supported");
58+
}
59+
9060
PBEParametersGenerator gen = new PKCS5S2ParametersGenerator(alg);
91-
byte[] saltBytes = Base64.decode(salt, Base64.DEFAULT);
92-
gen.init(pwd.getBytes(StandardCharsets.UTF_8), saltBytes, iterations);
93-
byte[] key = ((KeyParameter) gen.generateDerivedParameters(keyLen * 8)).getKey();
94-
return bytesToHex(key);
61+
gen.init(pwd, salt, iterations);
62+
return ((KeyParameter) gen.generateDerivedParameters(keyLen * 8)).getKey();
9563
}
9664
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.pedrouid.crypto;
2+
3+
class Util {
4+
static String bytesToHex(byte[] bytes) {
5+
final char[] hexArray = "0123456789abcdef".toCharArray();
6+
char[] hexChars = new char[bytes.length * 2];
7+
for ( int j = 0; j < bytes.length; j++ ) {
8+
int v = bytes[j] & 0xFF;
9+
hexChars[j * 2] = hexArray[v >>> 4];
10+
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
11+
}
12+
return new String(hexChars);
13+
}
14+
}

index.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ declare module "react-native-simple-crypto" {
3838

3939
export namespace PBKDF2 {
4040
export function hash(
41-
password: string,
42-
salt: ArrayBuffer,
41+
password: string | ArrayBuffer,
42+
salt: string | ArrayBuffer,
4343
iterations: number,
4444
keyLen: number,
45-
hash: "SHA1" | "SHA224" | "SHA256" | "SHA384" | "SHA512"
45+
algorithm: "SHA1" | "SHA224" | "SHA256" | "SHA384" | "SHA512"
4646
): Promise<ArrayBuffer>;
4747
}
4848

index.js

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,16 +111,27 @@ const HMAC = {
111111
};
112112

113113
const PBKDF2 = {
114-
hash: async function (password, saltArrayBuffer, iterations, keyLength, hash) {
115-
const saltBase64 = convertArrayBufferToBase64(saltArrayBuffer);
116-
const hashHex = await NativeModules.Pbkdf2.hash(
117-
password,
118-
saltBase64,
114+
hash: async function (password, salt, iterations, keyLength, algorithm) {
115+
let passwordToHash = password;
116+
let saltToHash = salt;
117+
118+
if (typeof password === 'string') {
119+
passwordToHash = convertUtf8ToArrayBuffer(password);
120+
}
121+
122+
if (typeof salt === 'string') {
123+
saltToHash = convertUtf8ToArrayBuffer(salt);
124+
}
125+
126+
const digest = await NativeModules.Pbkdf2.hash(
127+
convertArrayBufferToBase64(passwordToHash),
128+
convertArrayBufferToBase64(saltToHash),
119129
iterations,
120130
keyLength,
121-
hash
131+
algorithm
122132
);
123-
return (convertHexToArrayBuffer(hashHex));
133+
134+
return convertBase64ToArrayBuffer(digest);
124135
}
125136
};
126137

ios/RCTCrypto.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@
254254
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
255255
GCC_WARN_UNUSED_FUNCTION = YES;
256256
GCC_WARN_UNUSED_VARIABLE = YES;
257-
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
257+
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
258258
MTL_ENABLE_DEBUG_INFO = YES;
259259
ONLY_ACTIVE_ARCH = YES;
260260
SDKROOT = iphoneos;
@@ -300,7 +300,7 @@
300300
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
301301
GCC_WARN_UNUSED_FUNCTION = YES;
302302
GCC_WARN_UNUSED_VARIABLE = YES;
303-
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
303+
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
304304
MTL_ENABLE_DEBUG_INFO = NO;
305305
SDKROOT = iphoneos;
306306
VALIDATE_PRODUCT = YES;

ios/RCTCrypto/RCTPbkdf2.m

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ @implementation RCTPbkdf2
55

66
RCT_EXPORT_MODULE()
77

8-
RCT_EXPORT_METHOD(hash:(NSString *)password saltBase64:(NSString *)saltBase64 iterations:(int)iterations keyLen:(int)keyLen hash:(NSString *)hash
8+
RCT_EXPORT_METHOD(hash:(NSString *)password
9+
salt:(NSString *)salt
10+
iterations:(int)iterations
11+
keyLen:(int)keyLen
12+
algorithm:(NSString *)algorithm
913
resolver:(RCTPromiseResolveBlock)resolve
1014
rejecter:(RCTPromiseRejectBlock)reject) {
1115
NSError *error = nil;
12-
NSString *data = [Pbkdf2 hash:password saltBase64:saltBase64 iterations:iterations keyLen:keyLen hash:hash];
16+
NSString *data = [Pbkdf2 hash:password salt:salt iterations:iterations keyLen:keyLen algorithm:algorithm];
1317
if (data == nil) {
1418
reject(@"keygen_fail", @"Key generation failed", error);
1519
} else {

ios/RCTCrypto/lib/Pbkdf2.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#import <Foundation/Foundation.h>
22

33
@interface Pbkdf2 : NSObject
4-
+ (NSString *) hash:(NSString *)password saltBase64: (NSString *)saltBase64 iterations: (int)iterations keyLen: (int)keyLen hash: (NSString *)hash;
4+
+ (NSString *) hash:(NSString *)password salt: (NSString *)salt iterations: (int)iterations keyLen: (int)keyLen algorithm: (NSString *)algorithm;
55
@end

0 commit comments

Comments
 (0)