diff --git a/README.md b/README.md index 92be712..3894684 100644 --- a/README.md +++ b/README.md @@ -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: @@ -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: diff --git a/android/src/main/java/com/sha256lib/Sha256Module.java b/android/src/main/java/com/sha256lib/Sha256Module.java index c262b63..60bd6a0 100644 --- a/android/src/main/java/com/sha256lib/Sha256Module.java +++ b/android/src/main/java/com/sha256lib/Sha256Module.java @@ -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; @@ -28,6 +29,15 @@ 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")); @@ -35,6 +45,13 @@ String buildHash(final String toHash, final String algo, final Integer length) t 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) { @@ -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 { @@ -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()); + } + } + } diff --git a/ios/sha256.m b/ios/sha256.m index 27dcd0a..b701fe7 100644 --- a/ios/sha256.m +++ b/ios/sha256.m @@ -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) @@ -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) @@ -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 diff --git a/sha256.d.ts b/sha256.d.ts index dc8fc66..143b114 100644 --- a/sha256.d.ts +++ b/sha256.d.ts @@ -1,4 +1,6 @@ declare module 'react-native-sha256' { export const sha1: (input: string) => Promise; + export const sha1Bytes: (input: Array) => Promise; export const sha256: (input: string) => Promise; + export const sha256Bytes: (input: Array) => Promise; } diff --git a/sha256.js b/sha256.js index 4709577..5d2eadd 100644 --- a/sha256.js +++ b/sha256.js @@ -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); +}