From 229063d4f52bfac2c0fa0ea27df4de5561de30d6 Mon Sep 17 00:00:00 2001 From: 0xturboblitz Date: Wed, 14 Feb 2024 16:01:55 +0100 Subject: [PATCH 1/3] android photo --- app/App.tsx | 8 +- .../io/tradle/nfc/RNPassportReaderModule.kt | 143 +++++++++--------- app/src/screens/ProveScreen.tsx | 2 +- common/src/utils/types.ts | 5 + 4 files changed, 83 insertions(+), 75 deletions(-) diff --git a/app/App.tsx b/app/App.tsx index 5979708dd..c4bfed7ac 100644 --- a/app/App.tsx +++ b/app/App.tsx @@ -194,6 +194,7 @@ function App(): JSX.Element { dataGroupHashes, eContent, encryptedDigest, + photo } = response; const passportData: PassportData = { @@ -207,6 +208,7 @@ function App(): JSX.Element { dataGroupHashes: dataHashesObjToArray(JSON.parse(dataGroupHashes)), eContent: JSON.parse(eContent), encryptedDigest: JSON.parse(encryptedDigest), + photo: photo, }; console.log('mrz', passportData.mrz); @@ -215,6 +217,10 @@ function App(): JSX.Element { console.log('dataGroupHashes', passportData.dataGroupHashes); console.log('eContent', passportData.eContent); console.log('encryptedDigest', passportData.encryptedDigest); + console.log("photo", { + ...passportData.photo, + base64: passportData.photo.base64.substring(0, 100) + '...' + }) setPassportData(passportData); setStep(Steps.NFC_SCAN_COMPLETED); @@ -247,7 +253,7 @@ function App(): JSX.Element { dateOfBirth: dateOfBirth, dateOfExpiry: dateOfExpiry, }); - console.log('response', response); + // console.log('response', response); console.log('scanned'); handleResponseAndroid(response); } catch (e: any) { diff --git a/app/android/react-native-passport-reader/android/src/main/java/io/tradle/nfc/RNPassportReaderModule.kt b/app/android/react-native-passport-reader/android/src/main/java/io/tradle/nfc/RNPassportReaderModule.kt index 70f0eb7d7..79a706eed 100644 --- a/app/android/react-native-passport-reader/android/src/main/java/io/tradle/nfc/RNPassportReaderModule.kt +++ b/app/android/react-native-passport-reader/android/src/main/java/io/tradle/nfc/RNPassportReaderModule.kt @@ -495,87 +495,84 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext) } override fun onPostExecute(result: Exception?) { - if (scanPromise == null) return + if (scanPromise == null) return - if (result != null) { - // Log.w(TAG, exceptionStack(result)) - if (result is IOException) { - scanPromise?.reject("E_SCAN_FAILED_DISCONNECT", "Lost connection to chip on card") - } else { - scanPromise?.reject("E_SCAN_FAILED", result) - } + if (result != null) { + // Log.w(TAG, exceptionStack(result)) + if (result is IOException) { + scanPromise?.reject("E_SCAN_FAILED_DISCONNECT", "Lost connection to chip on card") + } else { + scanPromise?.reject("E_SCAN_FAILED", result) + } - resetState() - return - } + resetState() + return + } - val mrzInfo = dg1File.mrzInfo + val mrzInfo = dg1File.mrzInfo - // var quality = 100 - // if (opts?.hasKey("quality") == true) { - // quality = (opts?.getDouble("quality") ?: 1.0 * 100).toInt() - // } - val gson = Gson() + val gson = Gson() - val signedDataField = SODFile::class.java.getDeclaredField("signedData") - signedDataField.isAccessible = true - - // val signedData = signedDataField.get(sodFile) as SignedData - - val eContentAsn1InputStream = ASN1InputStream(sodFile.eContent.inputStream()) - // val eContentDecomposed: ASN1Primitive = eContentAsn1InputStream.readObject() - - val passport = Arguments.createMap() - passport.putString("mrz", mrzInfo.toString()) - passport.putString("signatureAlgorithm", sodFile.docSigningCertificate.sigAlgName) // this one is new - - val publicKey = sodFile.docSigningCertificate.publicKey - if (publicKey is RSAPublicKey) { - passport.putString("modulus", publicKey.modulus.toString()) - } else if (publicKey is ECPublicKey) { - // Handle the elliptic curve public key case + val signedDataField = SODFile::class.java.getDeclaredField("signedData") + signedDataField.isAccessible = true - // val w = publicKey.getW() - // passport.putString("publicKeyW", w.toString()) + // val signedData = signedDataField.get(sodFile) as SignedData - // val ecParams = publicKey.getParams() - // passport.putInt("cofactor", ecParams.getCofactor()) - // passport.putString("curve", ecParams.getCurve().toString()) - // passport.putString("generator", ecParams.getGenerator().toString()) - // passport.putString("order", ecParams.getOrder().toString()) - // if (ecParams is ECNamedCurveSpec) { - // passport.putString("curveName", ecParams.getName()) - // } + val eContentAsn1InputStream = ASN1InputStream(sodFile.eContent.inputStream()) + // val eContentDecomposed: ASN1Primitive = eContentAsn1InputStream.readObject() + + val passport = Arguments.createMap() + passport.putString("mrz", mrzInfo.toString()) + passport.putString("signatureAlgorithm", sodFile.docSigningCertificate.sigAlgName) // this one is new + + val publicKey = sodFile.docSigningCertificate.publicKey + if (publicKey is RSAPublicKey) { + passport.putString("modulus", publicKey.modulus.toString()) + } else if (publicKey is ECPublicKey) { + // Handle the elliptic curve public key case + + // val w = publicKey.getW() + // passport.putString("publicKeyW", w.toString()) + + // val ecParams = publicKey.getParams() + // passport.putInt("cofactor", ecParams.getCofactor()) + // passport.putString("curve", ecParams.getCurve().toString()) + // passport.putString("generator", ecParams.getGenerator().toString()) + // passport.putString("order", ecParams.getOrder().toString()) + // if (ecParams is ECNamedCurveSpec) { + // passport.putString("curveName", ecParams.getName()) + // } + + // Old one, probably wrong: + // passport.putString("curveName", (publicKey.parameters as ECNamedCurveSpec).name) + // passport.putString("curveName", (publicKey.parameters.algorithm)) or maybe this + passport.putString("publicKeyQ", publicKey.q.toString()) + } - // Old one, probably wrong: - // passport.putString("curveName", (publicKey.parameters as ECNamedCurveSpec).name) - // passport.putString("curveName", (publicKey.parameters.algorithm)) or maybe this - passport.putString("publicKeyQ", publicKey.q.toString()) - } - - passport.putString("dataGroupHashes", gson.toJson(sodFile.dataGroupHashes)) - passport.putString("eContent", gson.toJson(sodFile.eContent)) - passport.putString("encryptedDigest", gson.toJson(sodFile.encryptedDigest)) - - - // Another way to get signing time is to get into signedData.signerInfos, then search for the ICO identifier 1.2.840.113549.1.9.5 - // passport.putString("signerInfos", gson.toJson(signedData.signerInfos)) - - // Log.d(TAG, "signedData.digestAlgorithms: ${gson.toJson(signedData.digestAlgorithms)}") - // Log.d(TAG, "signedData.signerInfos: ${gson.toJson(signedData.signerInfos)}") - // Log.d(TAG, "signedData.certificates: ${gson.toJson(signedData.certificates)}") - - // val base64 = bitmap?.let { toBase64(it, quality) } - // val photo = Arguments.createMap() - // photo.putString("base64", base64 ?: "") - // photo.putInt("width", bitmap?.width ?: 0) - // photo.putInt("height", bitmap?.height ?: 0) - // passport.putMap("photo", photo) - // passport.putString("dg2File", gson.toJson(dg2File)) - - scanPromise?.resolve(passport) - resetState() - } + passport.putString("dataGroupHashes", gson.toJson(sodFile.dataGroupHashes)) + passport.putString("eContent", gson.toJson(sodFile.eContent)) + passport.putString("encryptedDigest", gson.toJson(sodFile.encryptedDigest)) + + + // Another way to get signing time is to get into signedData.signerInfos, then search for the ICO identifier 1.2.840.113549.1.9.5 + // passport.putString("signerInfos", gson.toJson(signedData.signerInfos)) + + // Log.d(TAG, "signedData.digestAlgorithms: ${gson.toJson(signedData.digestAlgorithms)}") + // Log.d(TAG, "signedData.signerInfos: ${gson.toJson(signedData.signerInfos)}") + // Log.d(TAG, "signedData.certificates: ${gson.toJson(signedData.certificates)}") + + var quality = 100 + val base64 = bitmap?.let { toBase64(it, quality) } + val photo = Arguments.createMap() + photo.putString("base64", base64 ?: "") + photo.putInt("width", bitmap?.width ?: 0) + photo.putInt("height", bitmap?.height ?: 0) + passport.putMap("photo", photo) + // passport.putString("dg2File", gson.toJson(dg2File)) + + scanPromise?.resolve(passport) + resetState() + } } private fun convertDate(input: String?): String? { diff --git a/app/src/screens/ProveScreen.tsx b/app/src/screens/ProveScreen.tsx index daf1bc950..b5eff35e4 100644 --- a/app/src/screens/ProveScreen.tsx +++ b/app/src/screens/ProveScreen.tsx @@ -143,7 +143,7 @@ const ProveScreen: React.FC = ({ h="$12" borderRadius="$10" source={{ - uri: USER + uri: passportData.photo.base64 ?? USER }} /> diff --git a/common/src/utils/types.ts b/common/src/utils/types.ts index 5379310b9..5a34623c1 100644 --- a/common/src/utils/types.ts +++ b/common/src/utils/types.ts @@ -7,4 +7,9 @@ export type PassportData = { dataGroupHashes: DataHash[] | number[]; eContent: number[]; encryptedDigest: number[]; + photo: { + base64: string; + height: number; + width: number; + } }; From 9c3ca776facf5a176973d4db7f6ccc43c7d94577 Mon Sep 17 00:00:00 2001 From: 0xturboblitz Date: Wed, 14 Feb 2024 16:54:33 +0100 Subject: [PATCH 2/3] ios photo display --- app/App.tsx | 9 ++++----- app/ios/PassportReader.swift | 8 ++++++++ app/ios/Podfile | 2 +- app/ios/Podfile.lock | 20 ++++++++++---------- app/src/screens/ProveScreen.tsx | 2 +- common/src/utils/types.ts | 6 +----- 6 files changed, 25 insertions(+), 22 deletions(-) diff --git a/app/App.tsx b/app/App.tsx index c4bfed7ac..2ae10590a 100644 --- a/app/App.tsx +++ b/app/App.tsx @@ -143,6 +143,7 @@ function App(): JSX.Element { console.log('isPACESupported', parsed.isPACESupported) console.log('isChipAuthenticationSupported', parsed.isChipAuthenticationSupported) console.log('residenceAddress', parsed.residenceAddress) + console.log('passportPhoto', parsed.passportPhoto.substring(0, 100) + '...') console.log('parsed.documentSigningCertificate', parsed.documentSigningCertificate) const pem = JSON.parse(parsed.documentSigningCertificate).PEM.replace(/\\\\n/g, '\n') @@ -171,6 +172,7 @@ function App(): JSX.Element { dataGroupHashes: concatenatedDataHashesArraySigned, eContent: signedEContentArray, encryptedDigest: encryptedDigestArray, + photoBase64: "data:image/jpeg;base64," + parsed.passportPhoto, }; console.log('mrz', passportData.mrz); @@ -208,7 +210,7 @@ function App(): JSX.Element { dataGroupHashes: dataHashesObjToArray(JSON.parse(dataGroupHashes)), eContent: JSON.parse(eContent), encryptedDigest: JSON.parse(encryptedDigest), - photo: photo, + photoBase64: photo.base64, }; console.log('mrz', passportData.mrz); @@ -217,10 +219,7 @@ function App(): JSX.Element { console.log('dataGroupHashes', passportData.dataGroupHashes); console.log('eContent', passportData.eContent); console.log('encryptedDigest', passportData.encryptedDigest); - console.log("photo", { - ...passportData.photo, - base64: passportData.photo.base64.substring(0, 100) + '...' - }) + console.log("photoBase64", passportData.photoBase64.substring(0, 100) + '...') setPassportData(passportData); setStep(Steps.NFC_SCAN_COMPLETED); diff --git a/app/ios/PassportReader.swift b/app/ios/PassportReader.swift index 96a82876f..ad24dfada 100644 --- a/app/ios/PassportReader.swift +++ b/app/ios/PassportReader.swift @@ -118,6 +118,14 @@ class PassportReader: NSObject{ ret["phoneNumber"] = passport.phoneNumber ret["personalNumber"] = passport.personalNumber + let passportPhotoData = passport.passportPhoto // [UInt8] + if let passportPhotoData = passport.passportPhoto { + let data = Data(passportPhotoData) + let base64String = data.base64EncodedString() + + ret["passportPhoto"] = base64String + } + // documentSigningCertificate // countrySigningCertificate diff --git a/app/ios/Podfile b/app/ios/Podfile index 54addf801..2782ec758 100644 --- a/app/ios/Podfile +++ b/app/ios/Podfile @@ -34,7 +34,7 @@ target 'ProofOfPassport' do flags = get_default_flags() use_frameworks! - pod 'NFCPassportReader', git: 'https://github.com/0xturboblitz/NFCPassportReader.git', commit: 'd36952eeaa2025ff1a9c9abbc244bd5ff53eb0f9' + pod 'NFCPassportReader', git: 'https://github.com/0xturboblitz/NFCPassportReader.git', commit: '310ecb519655d9ed8b1afc5eb490b2f51a4d3595' pod 'MoproKit', :path => './MoproKit' use_react_native!( diff --git a/app/ios/Podfile.lock b/app/ios/Podfile.lock index 52045f070..a40b47114 100644 --- a/app/ios/Podfile.lock +++ b/app/ios/Podfile.lock @@ -403,7 +403,7 @@ DEPENDENCIES: - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - MoproKit (from `./MoproKit`) - - NFCPassportReader (from `https://github.com/0xturboblitz/NFCPassportReader.git`, commit `d36952eeaa2025ff1a9c9abbc244bd5ff53eb0f9`) + - NFCPassportReader (from `https://github.com/0xturboblitz/NFCPassportReader.git`, commit `310ecb519655d9ed8b1afc5eb490b2f51a4d3595`) - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) @@ -460,7 +460,7 @@ EXTERNAL SOURCES: MoproKit: :path: "./MoproKit" NFCPassportReader: - :commit: d36952eeaa2025ff1a9c9abbc244bd5ff53eb0f9 + :commit: 310ecb519655d9ed8b1afc5eb490b2f51a4d3595 :git: https://github.com/0xturboblitz/NFCPassportReader.git RCT-Folly: :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" @@ -533,7 +533,7 @@ EXTERNAL SOURCES: CHECKOUT OPTIONS: NFCPassportReader: - :commit: d36952eeaa2025ff1a9c9abbc244bd5ff53eb0f9 + :commit: 310ecb519655d9ed8b1afc5eb490b2f51a4d3595 :git: https://github.com/0xturboblitz/NFCPassportReader.git SPEC CHECKSUMS: @@ -555,13 +555,13 @@ SPEC CHECKSUMS: React-Core: 8293312ad137ea82fd2c29deb163dbc24aa4e00e React-CoreModules: 32fab1d62416849a3b6dac6feff9d54e5ddc2d1e React-cxxreact: 55d0f7cb6b4cc09ba9190797f1da87182d1a2fb6 - React-debug: 878f0c4026b30a6240f7a15f8612efcf5d8c3df9 + React-debug: 7e61555c8158126c6cd98c3154381ad3821aaaca React-jsc: 0db8e8cc2074d979c37ffa7b8d7c914833960497 React-jsi: 58677ff4848ceb6aeb9118fe03448a843ea5e16a React-jsiexecutor: 2c15ba1bace70177492368d5180b564f165870fd React-jsinspector: b511447170f561157547bc0bef3f169663860be7 React-logger: c5b527272d5f22eaa09bb3c3a690fee8f237ae95 - React-NativeModulesApple: 3a49a4bc38b979b804525816b781eb6612dba5fa + React-NativeModulesApple: 0438665fc7473be6edc496e823e6ea0b0537b46c React-perflogger: 6bd153e776e6beed54c56b0847e1220a3ff92ba5 React-RCTActionSheet: c0b62af44e610e69d9a2049a682f5dba4e9dff17 React-RCTAnimation: fe7005136b58f58871cab2f70732343b6e330d30 @@ -575,13 +575,13 @@ SPEC CHECKSUMS: React-RCTVibration: ea3a68a49873a54ced927c90923fc6932baf344a React-rncore: 9672a017af4a7da7495d911f0b690cbcae9dd18d React-runtimeexecutor: 369ae9bb3f83b65201c0c8f7d50b72280b5a1dbc - React-runtimescheduler: 116fb55732ddfd96298350528cf13ceaf94759c8 - React-utils: a8681f0d721ff080373ae9e4afb1f380707b55f9 - ReactCommon: df6a7f5665621529ee01b89fb0c3c93eb014f276 + React-runtimescheduler: ec1066a4f2d1152eb1bc3fb61d69376b3bc0dde0 + React-utils: d55ba834beb39f01b0b470ae43478c0a3a024abe + ReactCommon: 68e3a815fbb69af3bb4196e04c6ae7abb306e7a8 RNSVG: 07dbd870b0dcdecc99b3a202fa37c8ca163caec2 SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce -PODFILE CHECKSUM: d401e6efe0c933985349c8c115c7edca8fef3182 +PODFILE CHECKSUM: 7568291077da8ee6387464cd1a7e01559a46ab1f -COCOAPODS: 1.15.0 +COCOAPODS: 1.14.3 diff --git a/app/src/screens/ProveScreen.tsx b/app/src/screens/ProveScreen.tsx index b5eff35e4..b57fd4a1c 100644 --- a/app/src/screens/ProveScreen.tsx +++ b/app/src/screens/ProveScreen.tsx @@ -143,7 +143,7 @@ const ProveScreen: React.FC = ({ h="$12" borderRadius="$10" source={{ - uri: passportData.photo.base64 ?? USER + uri: passportData.photoBase64 ?? USER }} /> diff --git a/common/src/utils/types.ts b/common/src/utils/types.ts index 5a34623c1..21c2c0f59 100644 --- a/common/src/utils/types.ts +++ b/common/src/utils/types.ts @@ -7,9 +7,5 @@ export type PassportData = { dataGroupHashes: DataHash[] | number[]; eContent: number[]; encryptedDigest: number[]; - photo: { - base64: string; - height: number; - width: number; - } + photoBase64: string; }; From 40403c0c5e416a207fbd3df44f4fd502cd654d1a Mon Sep 17 00:00:00 2001 From: 0xturboblitz Date: Wed, 14 Feb 2024 17:09:25 +0100 Subject: [PATCH 3/3] ignore annoying warning cf https://github.com/tamagui/tamagui/issues/1828 --- app/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/index.js b/app/index.js index b3f5872a6..1cee86bff 100644 --- a/app/index.js +++ b/app/index.js @@ -2,7 +2,7 @@ * @format */ -import { AppRegistry } from 'react-native'; +import { AppRegistry, LogBox } from 'react-native'; import App from './App'; import { name as appName } from './app.json'; import { TamaguiProvider } from 'tamagui'; @@ -10,6 +10,9 @@ import { createTamagui } from 'tamagui'; import { config } from '@tamagui/config/v2-native' const tamaguiConfig = createTamagui(config) +LogBox.ignoreLogs([ + /bad setState/, +]) const Root = () => (