Skip to content

Commit 16cd9b1

Browse files
committed
Refactor Android SHA code to match iOS
1 parent f7ccc60 commit 16cd9b1

3 files changed

Lines changed: 97 additions & 115 deletions

File tree

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

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import java.io.IOException;
66
import java.security.SecureRandom;
7+
import java.util.Arrays;
8+
import java.util.ArrayList;
79
import java.util.HashMap;
810
import java.util.Map;
911

@@ -51,31 +53,40 @@ public RCTSha(ReactApplicationContext reactContext) {
5153
super(reactContext);
5254
}
5355

56+
private static ArrayList<String> algorithms = new ArrayList<String>(
57+
Arrays.asList("SHA-1",
58+
"SHA-256",
59+
"SHA-512"));
60+
5461
@Override
5562
public String getName() {
5663
return "RCTSha";
5764
}
5865

66+
private byte[] sha(byte[] data, String algorithm) throws Exception {
67+
if (!algorithms.contains(algorithm)) {
68+
throw new Exception("Invalid algorithm");
69+
}
70+
71+
MessageDigest md = MessageDigest.getInstance(algorithm);
72+
md.update(data);
73+
return md.digest();
74+
}
75+
5976
@ReactMethod
6077
public void shaBase64(String data, String algorithm, Promise promise) throws Exception {
6178
try {
62-
MessageDigest md = MessageDigest.getInstance(algorithm);
63-
md.update(Base64.decode(data, Base64.NO_WRAP));
64-
byte[] digest = md.digest();
65-
79+
byte[] digest = this.sha(Base64.decode(data, Base64.NO_WRAP), algorithm);
6680
promise.resolve(Base64.encodeToString(digest, Base64.NO_WRAP));
6781
} catch (Exception e) {
6882
promise.reject("-1", e.getMessage());
6983
}
7084
}
7185

7286
@ReactMethod
73-
public void sha(String data, String algorithm, Promise promise) throws Exception {
87+
public void shaUtf8(String data, String algorithm, Promise promise) throws Exception {
7488
try {
75-
MessageDigest md = MessageDigest.getInstance(algorithm);
76-
md.update(data.getBytes());
77-
byte[] digest = md.digest();
78-
89+
byte[] digest = data.getBytes();
7990
promise.resolve(Base64.encodeToString(digest, Base64.DEFAULT));
8091
} catch (Exception e) {
8192
promise.reject("-1", e.getMessage());

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.facebook.react.bridge.ReactApplicationContext;
55
import com.facebook.react.bridge.Callback;
66

7+
import com.facebook.react.bridge.Promise;
78
import com.facebook.react.bridge.ReactContextBaseJavaModule;
89

910
import java.security.SecureRandom;
@@ -25,8 +26,12 @@ public String getName() {
2526
}
2627

2728
@ReactMethod
28-
public void randomBytes(int size, Callback success) {
29-
success.invoke(null, getRandomBytes(size));
29+
public void randomBytes(int size, Promise promise) {
30+
try {
31+
promise.resolve(getRandomBytes(size));
32+
} catch (Exception e) {
33+
promise.reject("-1", e.getMessage());
34+
}
3035
}
3136

3237
@Override

index.js

Lines changed: 70 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,158 +1,124 @@
1-
"use strict";
1+
'use strict'
22

3-
import base64js from "base64-js";
4-
import hexLite from "hex-lite";
5-
import { NativeModules } from "react-native";
3+
import base64js from 'base64-js'
4+
import hexLite from 'hex-lite'
5+
import { NativeModules } from 'react-native'
66

7-
function convertArrayBufferToUtf8(arrayBuffer) {
8-
const array = new Uint8Array(arrayBuffer);
9-
const chars = [];
10-
let i = 0;
7+
function convertArrayBufferToUtf8 (arrayBuffer) {
8+
const array = new Uint8Array(arrayBuffer)
9+
const chars = []
10+
let i = 0
1111

1212
while (i < array.length) {
13-
const byte = array[i];
13+
const byte = array[i]
1414
if (byte < 128) {
15-
chars.push(String.fromCharCode(byte));
16-
i++;
15+
chars.push(String.fromCharCode(byte))
16+
i++
1717
} else if (byte > 191 && byte < 224) {
1818
chars.push(
1919
String.fromCharCode(((byte & 0x1f) << 6) | (array[i + 1] & 0x3f))
20-
);
21-
i += 2;
20+
)
21+
i += 2
2222
} else {
2323
chars.push(
2424
String.fromCharCode(
2525
((byte & 0x0f) << 12) |
26-
((array[i + 1] & 0x3f) << 6) |
27-
(array[i + 2] & 0x3f)
26+
((array[i + 1] & 0x3f) << 6) |
27+
(array[i + 2] & 0x3f)
2828
)
29-
);
30-
i += 3;
29+
)
30+
i += 3
3131
}
3232
}
3333

34-
const utf8 = chars.join("");
35-
return utf8;
34+
return chars.join('')
3635
}
3736

38-
function convertUtf8ToArrayBuffer(utf8) {
39-
const bytes = [];
37+
function convertUtf8ToArrayBuffer (utf8) {
38+
const bytes = []
4039

41-
let i = 0;
42-
utf8 = encodeURI(utf8);
40+
let i = 0
41+
utf8 = encodeURI(utf8)
4342
while (i < utf8.length) {
44-
const byte = utf8.charCodeAt(i++);
43+
const byte = utf8.charCodeAt(i++)
4544
if (byte === 37) {
46-
bytes.push(parseInt(utf8.substr(i, 2), 16));
47-
i += 2;
45+
bytes.push(parseInt(utf8.substr(i, 2), 16))
46+
i += 2
4847
} else {
49-
bytes.push(byte);
48+
bytes.push(byte)
5049
}
5150
}
5251

53-
const array = new Uint8Array(bytes);
54-
const arrayBuffer = array.buffer;
55-
return arrayBuffer;
52+
const array = new Uint8Array(bytes)
53+
return array.buffer
5654
}
5755

58-
function convertArrayBufferToBase64(arrayBuffer) {
59-
const byteArray = new Uint8Array(arrayBuffer);
60-
const result = base64js.fromByteArray(byteArray);
61-
return result;
56+
function convertArrayBufferToBase64 (arrayBuffer) {
57+
return base64js.fromByteArray(new Uint8Array(arrayBuffer))
6258
}
6359

64-
function convertBase64ToArrayBuffer(base64) {
65-
const result = base64js.toByteArray(base64).buffer;
66-
return result;
60+
function convertBase64ToArrayBuffer (base64) {
61+
return base64js.toByteArray(base64).buffer
6762
}
6863

69-
function convertArrayBufferToHex(arrayBuffer) {
70-
const result = hexLite.fromBuffer(arrayBuffer);
71-
return result;
72-
}
64+
const convertArrayBufferToHex = hexLite.fromBuffer
7365

74-
function convertHexToArrayBuffer(hex) {
75-
const result = hexLite.toBuffer(hex);
76-
return result;
77-
}
66+
const convertHexToArrayBuffer = hexLite.toBuffer
7867

79-
function randomBytes(length) {
80-
return new Promise((resolve, reject) => {
81-
NativeModules.RNRandomBytes.randomBytes(length, function(err, base64) {
82-
if (err) {
83-
reject(err);
84-
} else {
85-
const result = convertBase64ToArrayBuffer(base64);
86-
resolve(result);
87-
}
88-
});
89-
});
68+
async function randomBytes (length) {
69+
return convertBase64ToArrayBuffer(await NativeModules.RNRandomBytes.randomBytes(length))
9070
}
9171

92-
async function SHAWrapper(data, algorithm) {
72+
async function SHAWrapper (data, algorithm) {
9373
if (typeof data === 'string') {
94-
return NativeModules.Sha.sha(data, algorithm)
74+
return NativeModules.Sha.shaUtf8(data, algorithm)
9575
} else {
96-
const dataBase64 = convertArrayBufferToBase64(data);
76+
const dataBase64 = convertArrayBufferToBase64(data)
9777
const result = await NativeModules.Sha.shaBase64(dataBase64, algorithm)
9878

99-
return convertBase64ToArrayBuffer(result);
79+
return convertBase64ToArrayBuffer(result)
10080
}
10181
}
10282

10383
const AES = {
104-
encrypt: function(textArrayBuffer, keyArrayBuffer, ivArrayBuffer) {
105-
const textBase64 = convertArrayBufferToBase64(textArrayBuffer);
106-
const keyHex = convertArrayBufferToHex(keyArrayBuffer);
107-
const ivHex = convertArrayBufferToHex(ivArrayBuffer);
108-
return new Promise((resolve, reject) => {
109-
NativeModules.Aes.encrypt(textBase64, keyHex, ivHex)
110-
.then(cipherTextBase64 => {
111-
const result = convertBase64ToArrayBuffer(cipherTextBase64);
112-
resolve(result);
113-
})
114-
.catch(error => reject(error));
115-
});
84+
encrypt: async function (textArrayBuffer, keyArrayBuffer, ivArrayBuffer) {
85+
const textBase64 = convertArrayBufferToBase64(textArrayBuffer)
86+
const keyHex = convertArrayBufferToHex(keyArrayBuffer)
87+
const ivHex = convertArrayBufferToHex(ivArrayBuffer)
88+
return convertBase64ToArrayBuffer(await NativeModules.Aes.encrypt(textBase64, keyHex, ivHex))
11689
},
117-
decrypt: function(cipherTextArrayBuffer, keyArrayBuffer, ivArrayBuffer) {
118-
const cipherTextBase64 = convertArrayBufferToBase64(cipherTextArrayBuffer);
119-
const keyHex = convertArrayBufferToHex(keyArrayBuffer);
120-
const ivHex = convertArrayBufferToHex(ivArrayBuffer);
121-
return new Promise((resolve, reject) => {
122-
NativeModules.Aes.decrypt(cipherTextBase64, keyHex, ivHex)
123-
.then(textString => {
124-
const result = convertBase64ToArrayBuffer(textString);
125-
resolve(result);
126-
})
127-
.catch(error => reject(error));
128-
});
90+
decrypt: async function (cipherTextArrayBuffer, keyArrayBuffer, ivArrayBuffer) {
91+
const cipherTextBase64 = convertArrayBufferToBase64(cipherTextArrayBuffer)
92+
const keyHex = convertArrayBufferToHex(keyArrayBuffer)
93+
const ivHex = convertArrayBufferToHex(ivArrayBuffer)
94+
return convertBase64ToArrayBuffer(await NativeModules.Aes.decrypt(cipherTextBase64, keyHex, ivHex))
12995
}
130-
};
96+
}
13197

13298
const SHA = {
13399
sha1: data => SHAWrapper(data, 'SHA-1'),
134100
sha256: data => SHAWrapper(data, 'SHA-256'),
135101
sha512: data => SHAWrapper(data, 'SHA-512')
136-
};
102+
}
137103

138104
const HMAC = {
139-
hmac256: function(textArrayBuffer, keyArrayBuffer) {
140-
const textHex = convertArrayBufferToHex(textArrayBuffer);
141-
const keyHex = convertArrayBufferToHex(keyArrayBuffer);
105+
hmac256: function (textArrayBuffer, keyArrayBuffer) {
106+
const textHex = convertArrayBufferToHex(textArrayBuffer)
107+
const keyHex = convertArrayBufferToHex(keyArrayBuffer)
142108
return new Promise((resolve, reject) => {
143109
NativeModules.Hmac.hmac256(textHex, keyHex)
144110
.then(signatureHex => {
145-
const result = convertHexToArrayBuffer(signatureHex);
146-
resolve(result);
111+
const result = convertHexToArrayBuffer(signatureHex)
112+
resolve(result)
147113
})
148-
.catch(error => reject(error));
149-
});
114+
.catch(error => reject(error))
115+
})
150116
}
151-
};
117+
}
152118

153119
const PBKDF2 = {
154-
hash: function(password, saltArrayBuffer, iterations, keyLength, hash) {
155-
const saltBase64 = convertArrayBufferToBase64(saltArrayBuffer);
120+
hash: function (password, saltArrayBuffer, iterations, keyLength, hash) {
121+
const saltBase64 = convertArrayBufferToBase64(saltArrayBuffer)
156122
return new Promise((resolve, reject) => {
157123
NativeModules.Pbkdf2.hash(
158124
password,
@@ -162,15 +128,15 @@ const PBKDF2 = {
162128
hash
163129
)
164130
.then(hashHex => {
165-
const result = convertHexToArrayBuffer(hashHex);
166-
resolve(result);
131+
const result = convertHexToArrayBuffer(hashHex)
132+
resolve(result)
167133
})
168-
.catch(error => reject(error));
169-
});
134+
.catch(error => reject(error))
135+
})
170136
}
171-
};
137+
}
172138

173-
const RSA = NativeModules.Rsa;
139+
const RSA = NativeModules.Rsa
174140

175141
const utils = {
176142
randomBytes: randomBytes,
@@ -180,7 +146,7 @@ const utils = {
180146
convertBase64ToArrayBuffer: convertBase64ToArrayBuffer,
181147
convertArrayBufferToHex: convertArrayBufferToHex,
182148
convertHexToArrayBuffer: convertHexToArrayBuffer
183-
};
149+
}
184150

185151
export default {
186152
AES: AES,
@@ -189,4 +155,4 @@ export default {
189155
PBKDF2: PBKDF2,
190156
RSA: RSA,
191157
utils: utils
192-
};
158+
}

0 commit comments

Comments
 (0)