Skip to content

Add methods to get the hash of a byte array #57

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pod install
Import the lib into your project:

```javascript
import { sha256 } from 'react-native-sha256';
import { sha256, sha256Bytes } from 'react-native-sha256';
```

Build a sha256-hash:
Expand All @@ -40,6 +40,15 @@ sha256("Test").then( hash => {
})
```

```javascript
const message = new Uint8Array(8);
const bytes = Array.from(message);

sha256Bytes(message).then( hash => {
console.log(hash);
})
```

# File-Hashes

If you need to calculate SHA-256 hashes from a file, use this method of react-native-fs:
Expand Down
45 changes: 45 additions & 0 deletions android/src/main/java/com/sha256lib/Sha256Module.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.Promise;

Expand All @@ -28,13 +29,29 @@ public String getName() {
return "sha256Lib";
}

private static byte[] readableArrayToByteArray(ReadableArray readableArray) {
byte[] arr = new byte[readableArray.size()];
for (int i = 0; i < readableArray.size(); ++i) {
arr[i] = (byte) readableArray.getInt(i);
}

return arr;
}

String buildHash(final String toHash, final String algo, final Integer length) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance(algo);
md.update(toHash.getBytes("UTF-8"));
byte[] digest = md.digest();
return String.format("%0" + length.toString() + "x", new java.math.BigInteger(1, digest));
}

String buildHashWithBytes(final ReadableArray toHash, final String algo, final Integer length) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance(algo);
byte[] arr = Sha256Module.readableArrayToByteArray(toHash);
md.update(arr);
byte[] digest = md.digest();
return String.format("%0" + length.toString() + "x", new java.math.BigInteger(1, digest));
}

@ReactMethod
public void sha256(final String toHash, Promise promise) {
Expand All @@ -50,6 +67,20 @@ public void sha256(final String toHash, Promise promise) {
}
}

@ReactMethod
public void sha256Bytes(final ReadableArray toHash, Promise promise) {
try {
String hash = buildHashWithBytes(toHash, "SHA-256", 64);
promise.resolve(hash);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
promise.reject("sha256", e.getMessage());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
promise.reject("sha256", e.getMessage());
}
}

@ReactMethod
public void sha1(final String toHash, Promise promise) {
try {
Expand All @@ -64,4 +95,18 @@ public void sha1(final String toHash, Promise promise) {
}
}

@ReactMethod
public void sha1Bytes(final ReadableArray toHash, Promise promise) {
try {
String hash = buildHashWithBytes(toHash, "SHA-1", 40);
promise.resolve(hash);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
promise.reject("sha1", e.getMessage());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
promise.reject("sha1", e.getMessage());
}
}

}
53 changes: 53 additions & 0 deletions ios/sha256.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,31 @@ - (NSString*) calcHash: (NSString*) subject withDigestFunction: (DIGEST_FUNCTION
return ret;
}

- (NSString*) calcHashWithBytes: (NSArray *) subject withDigestFunction: (DIGEST_FUNCTION) digest withDigestLength: (int) digestLength {
NSUInteger count = [subject count];
unsigned char *array = (unsigned char *) malloc(count);

if (array == nil) return nil;

for (int i = 0; i < count; ++i) {
array[i] = [[subject objectAtIndex: i] unsignedCharValue];
}

unsigned char result[digestLength];

digest(array, count, result);

free(array);

NSMutableString *ret = [NSMutableString stringWithCapacity:digestLength * 2];
for(int i = 0; i < digestLength; i++)
{
[ret appendFormat:@"%02x",result[i]];
}

return ret;
}

RCT_EXPORT_METHOD(sha1: (NSString *) data
resolver: (RCTPromiseResolveBlock) resolve
rejecter: (RCTPromiseRejectBlock) reject)
Expand All @@ -41,6 +66,20 @@ - (NSString*) calcHash: (NSString*) subject withDigestFunction: (DIGEST_FUNCTION
resolve(ret);
}

RCT_EXPORT_METHOD(sha1Bytes: (NSArray *) data
resolver: (RCTPromiseResolveBlock) resolve
rejecter: (RCTPromiseRejectBlock) reject)

{
NSString *ret = [self calcHashWithBytes:data withDigestFunction:CC_SHA1 withDigestLength: CC_SHA1_DIGEST_LENGTH];

if (ret) {
resolve(ret);
} else {
reject(@"error", @"out of memory", nil);
}
}

RCT_EXPORT_METHOD(sha256: (NSString *) data
resolver: (RCTPromiseResolveBlock) resolve
rejecter: (RCTPromiseRejectBlock) reject)
Expand All @@ -50,4 +89,18 @@ - (NSString*) calcHash: (NSString*) subject withDigestFunction: (DIGEST_FUNCTION
resolve(ret);
}

RCT_EXPORT_METHOD(sha256Bytes: (NSArray *) data
resolver: (RCTPromiseResolveBlock) resolve
rejecter: (RCTPromiseRejectBlock) reject)

{
NSString *ret = [self calcHashWithBytes:data withDigestFunction:CC_SHA256 withDigestLength: CC_SHA256_DIGEST_LENGTH];

if (ret) {
resolve(ret);
} else {
reject(@"error", @"out of memory", nil);
}
}

@end
2 changes: 2 additions & 0 deletions sha256.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
declare module 'react-native-sha256' {
export const sha1: (input: string) => Promise<string>;
export const sha1Bytes: (input: Array) => Promise<string>;
export const sha256: (input: string) => Promise<string>;
export const sha256Bytes: (input: Array) => Promise<string>;
}
8 changes: 8 additions & 0 deletions sha256.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ export function sha256(data: string) {
return sha256Lib.sha256(data);
}

export function sha256Bytes(data: Array) {
return sha256Lib.sha256Bytes(data);
}

export function sha1(data: string) {
return sha256Lib.sha1(data);
}

export function sha1Bytes(data: Array) {
return sha256Lib.sha1Bytes(data);
}