Skip to content

Commit 9aee70a

Browse files
committed
feat: added exported sha256 function
1 parent e8a8658 commit 9aee70a

7 files changed

Lines changed: 102 additions & 0 deletions

File tree

android/src/main/java/com/sbaiahmed1/reactnativebiometrics/ReactNativeBiometricsSharedImpl.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import java.security.NoSuchProviderException
2525
import java.security.Signature
2626
import java.security.UnrecoverableKeyException
2727
import java.security.cert.CertificateException
28+
import java.security.MessageDigest
2829
import java.security.interfaces.RSAPublicKey
2930
import androidx.core.content.edit
3031

@@ -1378,6 +1379,33 @@ class ReactNativeBiometricsSharedImpl(private val context: ReactApplicationConte
13781379
}
13791380
}
13801381

1382+
fun sha256(data: String, inputEncoding: String?, promise: Promise) {
1383+
try {
1384+
val encoding = inputEncoding ?: "utf8"
1385+
val dataBytes = decodeInputData(data, encoding)
1386+
if (dataBytes == null) {
1387+
promise.resolve(Arguments.createMap().apply {
1388+
putString("hash", "")
1389+
putString("error", "Invalid base64 data")
1390+
})
1391+
return
1392+
}
1393+
1394+
val digest = MessageDigest.getInstance("SHA-256")
1395+
val hashBytes = digest.digest(dataBytes)
1396+
val hashBase64 = BiometricUtils.encodeBase64(hashBytes)
1397+
1398+
promise.resolve(Arguments.createMap().apply {
1399+
putString("hash", hashBase64)
1400+
})
1401+
} catch (e: Exception) {
1402+
promise.resolve(Arguments.createMap().apply {
1403+
putString("hash", "")
1404+
putString("error", e.message ?: "SHA256 failed")
1405+
})
1406+
}
1407+
}
1408+
13811409
fun getKeyAttributes(keyAlias: String?, promise: Promise) {
13821410
val actualKeyAlias = getKeyAlias(keyAlias)
13831411
debugLog("getKeyAttributes called with keyAlias: ${keyAlias ?: "default"}, using: $actualKeyAlias")

android/src/newarch/java/com/sbaiahmed1/reactnativebiometrics/ReactNativeBiometricsModule.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ class ReactNativeBiometricsModule(reactContext: ReactApplicationContext) :
107107
sharedImpl.validateSignature(keyAlias, data, signature, promise)
108108
}
109109

110+
@ReactMethod
111+
override fun sha256(data: String, inputEncoding: String?, promise: Promise) {
112+
sharedImpl.sha256(data, inputEncoding, promise)
113+
}
114+
110115
@ReactMethod
111116
override fun getKeyAttributes(keyAlias: String?, promise: Promise) {
112117
sharedImpl.getKeyAttributes(keyAlias, promise)

android/src/oldarch/java/com/sbaiahmed1/reactnativebiometrics/ReactNativeBiometricsModule.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ class ReactNativeBiometricsModule(reactContext: ReactApplicationContext) :
8181
sharedImpl.validateSignature(keyAlias, data, signature, promise)
8282
}
8383

84+
@ReactMethod
85+
fun sha256(data: String, inputEncoding: String?, promise: Promise) {
86+
sharedImpl.sha256(data, inputEncoding, promise)
87+
}
88+
8489
@ReactMethod
8590
fun getKeyAttributes(keyAlias: String?, promise: Promise) {
8691
sharedImpl.getKeyAttributes(keyAlias, promise)

ios/ReactNativeBiometrics.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,33 @@ class ReactNativeBiometrics: RCTEventEmitter {
10801080
}
10811081
}
10821082

1083+
@objc
1084+
func sha256(_ data: NSString,
1085+
inputEncoding: NSString?,
1086+
resolver resolve: @escaping RCTPromiseResolveBlock,
1087+
rejecter reject: @escaping RCTPromiseRejectBlock) {
1088+
let encoding = (inputEncoding as String?) ?? "utf8"
1089+
1090+
let dataBytes: Data
1091+
if encoding.lowercased() == "base64" {
1092+
guard let decoded = Data(base64Encoded: data as String) else {
1093+
resolve(["hash": "", "error": "Invalid base64 data"])
1094+
return
1095+
}
1096+
dataBytes = decoded
1097+
} else {
1098+
guard let utf8Data = (data as String).data(using: .utf8) else {
1099+
resolve(["hash": "", "error": "UTF-8 encoding failed"])
1100+
return
1101+
}
1102+
dataBytes = utf8Data
1103+
}
1104+
1105+
let hash = SHA256.hash(data: dataBytes)
1106+
let hashData = Data(hash)
1107+
resolve(["hash": hashData.base64EncodedString()])
1108+
}
1109+
10831110
@objc
10841111
func getKeyAttributes(_ keyAlias: NSString?,
10851112
resolver resolve: @escaping RCTPromiseResolveBlock,

ios/ReactNativeBiometricsBridge.mm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ @interface RCT_EXTERN_MODULE(ReactNativeBiometrics, RCTEventEmitter)
101101
resolver:(RCTPromiseResolveBlock)resolve
102102
rejecter:(RCTPromiseRejectBlock)reject)
103103

104+
RCT_EXTERN_METHOD(sha256:
105+
(NSString *)data
106+
inputEncoding:(NSString *)inputEncoding
107+
resolver:(RCTPromiseResolveBlock)resolve
108+
rejecter:(RCTPromiseRejectBlock)reject)
109+
104110
RCT_EXTERN_METHOD(getKeyAttributes:
105111
(NSString *)keyAlias
106112
resolver:(RCTPromiseResolveBlock)resolve

src/NativeReactNativeBiometrics.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,13 @@ export interface Spec extends TurboModule {
134134
valid: boolean;
135135
error?: string;
136136
}>;
137+
sha256(
138+
data: string,
139+
inputEncoding?: 'utf8' | 'base64' | null
140+
): Promise<{
141+
hash: string;
142+
error?: string;
143+
}>;
137144
getKeyAttributes(keyAlias?: string | null): Promise<{
138145
exists: boolean;
139146
attributes?: {

src/index.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,25 @@ export function validateSignature(
437437
});
438438
}
439439

440+
export function sha256(
441+
data: string,
442+
inputEncoding: 'utf8' | 'base64' = 'utf8'
443+
): Promise<Sha256Result> {
444+
logger.debug('Computing SHA256', 'sha256', {
445+
dataLength: data.length,
446+
inputEncoding,
447+
});
448+
return ReactNativeBiometrics.sha256(data, inputEncoding)
449+
.then((result) => {
450+
logger.info('SHA256 completed', 'sha256');
451+
return result;
452+
})
453+
.catch((error) => {
454+
logger.error('SHA256 failed', 'sha256', error);
455+
throw error;
456+
});
457+
}
458+
440459
export function getKeyAttributes(
441460
keyAlias?: string
442461
): Promise<KeyAttributesResult> {
@@ -774,6 +793,11 @@ export type SignatureValidationResult = {
774793
error?: string;
775794
};
776795

796+
export type Sha256Result = {
797+
hash: string;
798+
error?: string;
799+
};
800+
777801
export type KeyAttributesResult = {
778802
exists: boolean;
779803
attributes?: {

0 commit comments

Comments
 (0)