add auth
This commit is contained in:
parent
349b817fb9
commit
b542c32e6d
|
@ -8,6 +8,7 @@
|
|||
"name": "KeycardExit",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "^1.5.0",
|
||||
"@react-native-async-storage/async-storage": "^2.0.0",
|
||||
"react": "18.3.1",
|
||||
"react-native": "0.75.3",
|
||||
|
@ -3111,6 +3112,18 @@
|
|||
"eslint-scope": "5.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@noble/hashes": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz",
|
||||
"integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^14.21.3 || >=16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
"android-build-dev": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res && cd android && gradlew assembleDebug"
|
||||
},
|
||||
"dependencies": {
|
||||
"@noble/hashes": "^1.5.0",
|
||||
"@react-native-async-storage/async-storage": "^2.0.0",
|
||||
"react": "18.3.1",
|
||||
"react-native": "0.75.3",
|
||||
|
|
52
src/Main.tsx
52
src/Main.tsx
|
@ -12,6 +12,8 @@ import NFCModal from './NFCModal';
|
|||
//@ts-ignore
|
||||
import Keycard from "react-native-status-keycard";
|
||||
import Dialpad from './components/Dialpad';
|
||||
import { sha256 } from '@noble/hashes/sha256';
|
||||
import { bytesToHex } from '@noble/hashes/utils';
|
||||
|
||||
enum Step {
|
||||
Discovery,
|
||||
|
@ -25,6 +27,7 @@ enum Step {
|
|||
const Main = () => {
|
||||
const PIN_MAX_RETRY = 3;
|
||||
const WALLET_DERIVATION_PATH = "m/84'/0'/0'/0/0";
|
||||
const LOGIN_ENDPOINT = "https://exit.logos.co/keycard/auth";
|
||||
|
||||
const [isModalVisible, setIsModalVisible] = useState<boolean>(false);
|
||||
const [step, setStep] = useState(Step.Discovery);
|
||||
|
@ -36,8 +39,8 @@ const Main = () => {
|
|||
const mnemonicRef = useRef("");
|
||||
const isListeningCard = useRef(false);
|
||||
const walletKey = useRef("");
|
||||
const sessionId = useRef("")
|
||||
const challenge = useRef("")
|
||||
const sessionRef = useRef("")
|
||||
const challengeRef = useRef("")
|
||||
|
||||
const getPairings = async () => {
|
||||
const pairingJSON = await AsyncStorage.getItem("pairings");
|
||||
|
@ -68,12 +71,29 @@ const Main = () => {
|
|||
return null
|
||||
}
|
||||
|
||||
const loginRequest = async () => {
|
||||
var req = {'session-id': sessionRef.current};
|
||||
|
||||
const identChallenge = bytesToHex(sha256('Keycard auth' + challengeRef.current));
|
||||
const data = await Keycard.verifyCard(identChallenge);
|
||||
req['keycard-auth'] = data['tlv-data'];
|
||||
|
||||
const walletChallenge = bytesToHex(sha256('Wallet auth' + challengeRef.current));
|
||||
req['wallet-auth'] = await Keycard.signWithPath(pinRef.current, WALLET_DERIVATION_PATH, walletChallenge);
|
||||
|
||||
challengeRef.current = "";
|
||||
sessionRef.current = "";
|
||||
|
||||
return JSON.stringify(req);
|
||||
}
|
||||
|
||||
const keycardConnectHandler = async () => {
|
||||
if (!isListeningCard.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
var newPinCounter = pinCounter;
|
||||
var loginReq = "";
|
||||
|
||||
try {
|
||||
const appInfo = await Keycard.getApplicationInfo();
|
||||
|
@ -108,6 +128,9 @@ const Main = () => {
|
|||
walletKey.current = await Keycard.exportKeyWithPath(pinRef.current, WALLET_DERIVATION_PATH);
|
||||
setStep(Step.Home);
|
||||
break;
|
||||
case Step.Home:
|
||||
loginReq = await loginRequest();
|
||||
break;
|
||||
case Step.FactoryReset:
|
||||
await Keycard.factoryReset();
|
||||
setStep(Step.Discovery);
|
||||
|
@ -141,6 +164,27 @@ const Main = () => {
|
|||
|
||||
await Keycard.stopNFC("");
|
||||
setIsModalVisible(false);
|
||||
|
||||
if (loginReq) {
|
||||
console.log(loginReq);
|
||||
|
||||
try {
|
||||
const resp = await fetch(LOGIN_ENDPOINT, {
|
||||
method: 'POST',
|
||||
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
|
||||
body: loginReq,
|
||||
});
|
||||
|
||||
const respJson = resp.json();
|
||||
if (respJson['error']) {
|
||||
//TODO: handle error
|
||||
}
|
||||
|
||||
//TODO: handle success
|
||||
} catch (e) {
|
||||
//TODO: handle error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -208,7 +252,9 @@ const Main = () => {
|
|||
}
|
||||
|
||||
const login = (sessionId: string, challenge: string) => {
|
||||
|
||||
sessionRef.current = sessionId;
|
||||
challengeRef.current = challenge;
|
||||
return connectCard();
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
|
|
|
@ -23,9 +23,20 @@ const HomeScreen: FC<HomeScreenProps> = props => {
|
|||
const codeScanner = useCodeScanner({
|
||||
codeTypes: ['qr'],
|
||||
onCodeScanned: (codes) => {
|
||||
console.log(`Scanned ${codes.length} codes!`)
|
||||
//TODO: implement
|
||||
setStep(HomeSteps.Home);
|
||||
if ((codes.length != 1) || !codes[0].value) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const payload = JSON.parse(codes[0].value);
|
||||
|
||||
if (!payload["challenge"] || !payload["session-id"]) {
|
||||
return;
|
||||
}
|
||||
|
||||
setStep(HomeSteps.Home);
|
||||
onPressFunc(payload["session-id"], payload["challenge"]);
|
||||
} catch(e) {}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue