factor out keychain logic

This commit is contained in:
0xturboblitz
2024-05-22 01:23:22 +09:00
parent 4eb39188f8
commit 95ad1578cf
3 changed files with 61 additions and 38 deletions

View File

@@ -21,6 +21,7 @@ import { scan } from '../utils/nfcScanner';
import useNavigationStore from '../stores/navigationStore';
import NfcScreen from './NfcScreen';
import CameraScreen from './CameraScreen';
import { mockPassportData_sha256WithRSAEncryption_65537 } from '../../../common/src/utils/mockPassportData';
const MainScreen: React.FC = () => {
const [NFCScanIsOpen, setNFCScanIsOpen] = useState(false);
@@ -37,6 +38,8 @@ const MainScreen: React.FC = () => {
update,
clearPassportDataFromStorage,
clearSecretFromStorage,
registerCommitment,
secret
} = useUserStore()
const {
@@ -45,7 +48,8 @@ const MainScreen: React.FC = () => {
step,
setStep,
selectedTab,
hideData
hideData,
toast
} = useNavigationStore();
const handleRestart = () => {
@@ -58,8 +62,16 @@ const MainScreen: React.FC = () => {
}
const handleSkip = () => {
registerCommitment(
secret,
mockPassportData_sha256WithRSAEncryption_65537
)
update({
passportData: mockPassportData_sha256WithRSAEncryption_65537
})
setStep(Steps.NFC_SCAN_COMPLETED);
deleteMrzFields();
toast?.show("Using mock passport data!", { type: "info" })
}
const handleHideData = () => {

View File

@@ -10,13 +10,14 @@ import * as Keychain from 'react-native-keychain';
import * as amplitude from '@amplitude/analytics-react-native';
import useNavigationStore from './navigationStore';
import { Steps } from '../utils/utils';
import { ethers } from 'ethers';
import { downloadZkey } from '../utils/zkeyDownload';
import { generateCircuitInputsRegister } from '../../../common/src/utils/generateInputs';
import { PASSPORT_ATTESTATION_ID, RPC_URL } from '../../../common/src/constants/constants';
import { generateProof } from '../utils/prover';
import { formatSigAlg } from '../../../common/src/utils/utils';
import { sendRegisterTransaction } from '../utils/transactions';
import { loadPassportData, loadSecret, loadSecretOrCreateIt, storePassportData } from '../utils/keychain';
import { ethers } from 'ethers';
interface UserState {
passportNumber: string
@@ -53,23 +54,21 @@ const useUserStore = create<UserState>((set, get) => ({
downloadZkey("register_sha256WithRSAEncryption_65537"); // might move after nfc scanning
downloadZkey("disclose");
const passportDataCreds = await Keychain.getGenericPassword({ service: "passportData" });
if (!passportDataCreds) {
const secret = await loadSecretOrCreateIt();
set({ secret });
const passportData = await loadPassportData();
if (!passportData) {
console.log("No passport data found, starting onboarding flow")
return;
}
const secretCreds = await Keychain.getGenericPassword({ service: "secret" })
const secret = (secretCreds as Keychain.UserCredentials).password
console.log("Setting passportData, secret and registered boolean to true, skipping onboarding")
console.log("skipping onboarding")
set({
passportData: JSON.parse(passportDataCreds.password),
secret,
passportData: JSON.parse(passportData),
registered: true,
});
useNavigationStore.getState().setStep(Steps.NFC_SCAN_COMPLETED); // this currently means go to app selection screen
useNavigationStore.getState().setStep(Steps.NFC_SCAN_COMPLETED); // this means go to app selection screen
// TODO: check if the commitment is already registered, if not retry registering it
@@ -82,37 +81,22 @@ const useUserStore = create<UserState>((set, get) => ({
// - Check presence of secret. If there is none, create one and store it
// - Store the passportData and try registering the commitment in the background
registerPassportData: async (passportData) => {
const secretCreds = await Keychain.getGenericPassword({ service: "secret" });
const secret = await loadSecret() as string;
if (secretCreds && secretCreds.password) {
// This should only ever happen if the user deletes the passport data in the options
console.log("secret is already registered, let's keep it.")
} else {
const randomWallet = ethers.Wallet.createRandom();
const secret = randomWallet.privateKey;
await Keychain.setGenericPassword("secret", secret, { service: "secret" });
const alreadyStoredPassportData = await loadPassportData();
if (alreadyStoredPassportData) {
console.log("passportData is already stored, this should never happen in prod")
console.log("replacing it with the new one")
}
const newSecretCreds = await Keychain.getGenericPassword({ service: "secret" })
const secret = (newSecretCreds as Keychain.UserCredentials).password
const passportDataCreds = await Keychain.getGenericPassword({ service: "passportData" });
if (passportDataCreds && passportDataCreds.password) {
console.log("passportData is already registered, this should never happen in prod")
}
await Keychain.setGenericPassword("passportData", JSON.stringify(passportData), { service: "passportData" });
await storePassportData(passportData)
set({ passportData });
get().registerCommitment(
secret,
passportData
)
set({
passportData,
secret
});
},
registerCommitment: async (secret, passportData) => {
@@ -165,9 +149,7 @@ const useUserStore = create<UserState>((set, get) => ({
throw new Error("Transaction failed");
}
set({
registered: true,
});
set({ registered: true });
} catch (error: any) {
console.error(error);
toast?.show('Error', {

29
app/src/utils/keychain.ts Normal file
View File

@@ -0,0 +1,29 @@
import * as Keychain from 'react-native-keychain';
import { ethers } from 'ethers';
import { PassportData } from '../../../common/src/utils/types';
export async function loadSecretOrCreateIt() {
const secret = await loadSecret()
if (secret) {
return secret
}
console.log("No secret found, creating one")
const randomWallet = ethers.Wallet.createRandom();
const newSecret = randomWallet.privateKey;
await Keychain.setGenericPassword("secret", newSecret, { service: "secret" });
return newSecret
}
export async function loadSecret() {
const secretCreds = await Keychain.getGenericPassword({ service: "secret" })
return secretCreds === false ? false : secretCreds.password
}
export async function loadPassportData() {
const passportDataCreds = await Keychain.getGenericPassword({ service: "passportData" });
return passportDataCreds === false ? false : passportDataCreds.password
}
export async function storePassportData(passportData: PassportData) {
await Keychain.setGenericPassword("passportData", JSON.stringify(passportData), { service: "passportData" });
}