From 703ce1c29d6ec8df13ab37abcbc404c9e9a722d7 Mon Sep 17 00:00:00 2001 From: Salman Mitha Date: Thu, 6 May 2021 17:49:31 +0530 Subject: [PATCH] feat: generate real otp (#90) * chore: bump some versions * feat: extract otp into separate component * chore: downgrade expo to 40 * feat: generate real OTPs * chore: upgrade expo back --- package.json | 8 ++- src/components/Secret/OTP.js | 50 +++++++++++++++ src/components/Secret/Secret.js | 23 +------ src/lib/otp.js | 17 ++++- yarn.lock | 107 +++++++++++++++++++++----------- 5 files changed, 145 insertions(+), 60 deletions(-) create mode 100644 src/components/Secret/OTP.js diff --git a/package.json b/package.json index 6bb273cd..ae2b6d24 100644 --- a/package.json +++ b/package.json @@ -14,14 +14,18 @@ "dependencies": { "@expo-google-fonts/didact-gothic": "^0.1.0", "@expo-google-fonts/poppins": "^0.1.0", + "@otplib/core": "^12.0.1", + "@otplib/plugin-base32-enc-dec": "^12.0.1", + "@otplib/plugin-crypto-js": "^12.0.1", "@react-native-async-storage/async-storage": "^1.13.0", "@react-native-community/masked-view": "0.1.10", "@react-navigation/native": "5.9.4", "@react-navigation/stack": "5.14.4", "aes-js": "3.1.2", + "buffer": "^6.0.3", "color": "^3.1.3", "expo": "^41.0.0", - "expo-app-loading": "^1.0.1", + "expo-app-loading": "^1.0.3", "expo-auth-session": "~3.2.3", "expo-barcode-scanner": "~10.1.2", "expo-random": "~11.1.2", @@ -35,7 +39,7 @@ "react-native-countdown-circle-timer": "^2.5.2", "react-native-gesture-handler": "~1.10.2", "react-native-get-random-values": "~1.7.0", - "react-native-paper": "^4.7.2", + "react-native-paper": "^4.8.1", "react-native-reanimated": "~2.1.0", "react-native-safe-area-context": "3.2.0", "react-native-screens": "~3.0.0", diff --git a/src/components/Secret/OTP.js b/src/components/Secret/OTP.js new file mode 100644 index 00000000..ece71ff1 --- /dev/null +++ b/src/components/Secret/OTP.js @@ -0,0 +1,50 @@ +import React from 'react' +import { StyleSheet, View, Text } from 'react-native' +import { CountdownCircleTimer } from 'react-native-countdown-circle-timer' + +import otpLib from '../../lib/otp' +import theme from '../../lib/defaultTheme' + +const styles = StyleSheet.create({ + row: { + flex: 1, + marginTop: theme.spacing(2), + paddingHorizontal: theme.spacing(1), + }, + label: { + color: theme.colors.textSecondary, + marginRight: theme.spacing(1), + fontSize: 10, + }, + value: { + fontFamily: 'monospace', + fontSize: 24, + color: theme.colors.text, + marginBottom: theme.spacing(2), + }, + otpRow: { flexDirection: 'row', justifyContent: 'space-between' }, + otp: { fontSize: 12 }, +}) + +export default function OTP({ value }) { + return ( + + OTP + + {value} + + {({ remainingTime }) => ( + {remainingTime} + )} + + + + ) +} diff --git a/src/components/Secret/Secret.js b/src/components/Secret/Secret.js index 2ef07b26..7986fd1c 100644 --- a/src/components/Secret/Secret.js +++ b/src/components/Secret/Secret.js @@ -1,13 +1,13 @@ import React, { useEffect, useState } from 'react' import { StyleSheet, View, Text } from 'react-native' import { Divider, Button, Card, Avatar } from 'react-native-paper' -import { CountdownCircleTimer } from 'react-native-countdown-circle-timer' import otpLib from '../../lib/otp' import theme from '../../lib/defaultTheme' import { Headline } from '../typography' import Menu from './Menu' +import OTP from './OTP' const styles = StyleSheet.create({ container: { @@ -74,7 +74,7 @@ export default function Secret({ data, onGenerate, onDelete, onRevoke }) { } refreshOtp() return () => clearTimeout(timeout) - }, [data]) + }, [data.secret]) const handleGenerate = () => { onGenerate(data) @@ -121,24 +121,7 @@ export default function Secret({ data, onGenerate, onDelete, onRevoke }) { )} /> - - OTP - - {otp} - - {({ remainingTime }) => ( - {remainingTime} - )} - - - + {data.token && ( <> diff --git a/src/lib/otp.js b/src/lib/otp.js index 4667ef9a..983689ae 100644 --- a/src/lib/otp.js +++ b/src/lib/otp.js @@ -1,9 +1,22 @@ +import { Authenticator } from '@otplib/core' +import { createDigest, createRandomBytes } from '@otplib/plugin-crypto-js' +import { keyDecoder, keyEncoder } from '@otplib/plugin-base32-enc-dec' + +global.Buffer = global.Buffer || require('buffer').Buffer + +export const authenticator = new Authenticator({ + createDigest, + createRandomBytes, + keyDecoder, + keyEncoder, +}) + export default { generate(secret) { - return Math.round(Math.random() * 999999 + 100000) + return authenticator.generate(secret) }, timeRemaining() { - return 30 + return authenticator.timeRemaining() }, } diff --git a/yarn.lock b/yarn.lock index dfec19d2..0cf3e5cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1398,23 +1398,6 @@ semver "7.3.2" slugify "^1.3.4" -"@expo/configure-splash-screen@0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@expo/configure-splash-screen/-/configure-splash-screen-0.3.1.tgz#a55b52718751907fd3fbaeb76dbd4162d282fa13" - integrity sha512-Wf9U8OYoIQojYjTuXgtTqDmlA4SdSEEQo9PxnVKuF8224FtJoYX1Kwc6kiVKc/4suplrqE71ZVJXOE2Uyh4SHw== - dependencies: - "@react-native-community/cli-platform-android" "^4.10.0" - "@react-native-community/cli-platform-ios" "^4.10.0" - color-string "^1.5.3" - commander "^5.1.0" - core-js "^3.6.5" - deep-equal "^2.0.3" - fs-extra "^9.0.0" - lodash "^4.17.15" - pngjs "^5.0.0" - xcode "^3.0.0" - xml-js "^1.6.11" - "@expo/configure-splash-screen@0.3.3": version "0.3.3" resolved "https://registry.yarnpkg.com/@expo/configure-splash-screen/-/configure-splash-screen-0.3.3.tgz#ef44ba4d62443297f9d8a9326a71b40b8b413528" @@ -2509,6 +2492,28 @@ "@babel/runtime" "^7.7.2" regenerator-runtime "^0.13.3" +"@otplib/core@^12.0.1": + version "12.0.1" + resolved "https://registry.yarnpkg.com/@otplib/core/-/core-12.0.1.tgz#73720a8cedce211fe5b3f683cd5a9c098eaf0f8d" + integrity sha512-4sGntwbA/AC+SbPhbsziRiD+jNDdIzsZ3JUyfZwjtKyc/wufl1pnSIaG4Uqx8ymPagujub0o92kgBnB89cuAMA== + +"@otplib/plugin-base32-enc-dec@^12.0.1": + version "12.0.1" + resolved "https://registry.yarnpkg.com/@otplib/plugin-base32-enc-dec/-/plugin-base32-enc-dec-12.0.1.tgz#8de5b89a61a1aea2c794910a81c7c92c1c8d3a91" + integrity sha512-tYdIu9gUb0k9EMYH2CMcV66IDoKxfCILjz3a0UCwXkPlV26SpJ1GJykpqe429UXRpEQpvNhJLpGCfXZ1UvqYFw== + dependencies: + "@otplib/core" "^12.0.1" + base32-decode "^1.0.0" + base32-encode "^1.1.1" + +"@otplib/plugin-crypto-js@^12.0.1": + version "12.0.1" + resolved "https://registry.yarnpkg.com/@otplib/plugin-crypto-js/-/plugin-crypto-js-12.0.1.tgz#c5aae9e01cb777f6e1efc0014c3ea57561070689" + integrity sha512-NGspFU0GKCAHgwfk6trvP8Xd22fzI6YyNpP88hpEHCXxjsgqTMcIw6E7x20BxpvFU4HWSxde9ykGTdK3/iintQ== + dependencies: + "@otplib/core" "^12.0.1" + crypto-js "^3.1.9-1" + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -2587,7 +2592,7 @@ hermes-profile-transformer "^0.0.6" ip "^1.1.5" -"@react-native-community/cli-platform-android@^4.10.0", "@react-native-community/cli-platform-android@^4.13.0": +"@react-native-community/cli-platform-android@^4.13.0": version "4.13.0" resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-4.13.0.tgz#922681ec82ee1aadd993598b814df1152118be02" integrity sha512-3i8sX8GklEytUZwPnojuoFbCjIRzMugCdzDIdZ9UNmi/OhD4/8mLGO0dgXfT4sMWjZwu3qjy45sFfk2zOAgHbA== @@ -2901,9 +2906,9 @@ integrity sha512-gUWhy8s45fQp4PqqKecsnOkdW0kt1IaKjgOIR3HPokkzTmQj9ji2wWFID5THu1MKrtO+d4s2lVrlEhXUsPXSvg== "@types/node@>=12.12.47": - version "15.0.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-15.0.1.tgz#ef34dea0881028d11398be5bf4e856743e3dc35a" - integrity sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA== + version "15.0.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-15.0.2.tgz#51e9c0920d1b45936ea04341aa3e2e58d339fb67" + integrity sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA== "@types/node@^13.7.0": version "13.13.44" @@ -3671,6 +3676,18 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +base32-decode@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/base32-decode/-/base32-decode-1.0.0.tgz#2a821d6a664890c872f20aa9aca95a4b4b80e2a7" + integrity sha512-KNWUX/R7wKenwE/G/qFMzGScOgVntOmbE27vvc6GrniDGYb6a5+qWcuoXl8WIOQL7q0TpK7nZDm1Y04Yi3Yn5g== + +base32-encode@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/base32-encode/-/base32-encode-1.2.0.tgz#e150573a5e431af0a998e32bdfde7045725ca453" + integrity sha512-cHFU8XeRyx0GgmoWi5qHMCVRiqU6J3MHWxVgun7jggCBUpVzm1Ir7M9dYr2whjSNc3tFeXfQ/oZjQu/4u55h9A== + dependencies: + to-data-view "^1.1.0" + base64-js@^1.1.2, base64-js@^1.2.3, base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -3839,6 +3856,14 @@ buffer@^5.2.0: base64-js "^1.3.1" ieee754 "^1.1.13" +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -4371,6 +4396,11 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" +crypto-js@^3.1.9-1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.3.0.tgz#846dd1cce2f68aacfa156c8578f926a609b7976b" + integrity sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q== + crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" @@ -5207,12 +5237,12 @@ expect@^26.6.2: jest-message-util "^26.6.2" jest-regex-util "^26.0.0" -expo-app-loading@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/expo-app-loading/-/expo-app-loading-1.0.1.tgz#a2ef73235c5dd0a99c0319ad9d3f4d278237564c" - integrity sha512-qgsystchwMHep43YMAMHJAD5bRUikolQpb1d+ySWF4ZFTtNInmLAPqiBcVSey5taRuHD3cAvEijx3wc0W/HfVw== +expo-app-loading@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/expo-app-loading/-/expo-app-loading-1.0.3.tgz#35c2dfd71aacd9f5c53777e3ff2ac07549e766df" + integrity sha512-zLheUgBCQoyybJrGxw81MWfxvlnHb7zatjLbmkNosqMwqq3MOPC/P4HwF6qYsrVUFO6PIzb4yq3lFO3RkCCfhw== dependencies: - expo-splash-screen "0.8.1" + expo-splash-screen "~0.10.2" expo-application@~3.1.2: version "3.1.2" @@ -5310,12 +5340,12 @@ expo-secure-store@~10.1.0: resolved "https://registry.yarnpkg.com/expo-secure-store/-/expo-secure-store-10.1.0.tgz#a223b3323526b152cd29c6e13058d8c8c2711eab" integrity sha512-mH53aCptDMiLGopsq0uSpeRLtVpFi+IgwqLGNvIKn0CnSxBUbzE9bq5TSKCBm4JxN4/viohpV3R7L6Qj8MQT+g== -expo-splash-screen@0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/expo-splash-screen/-/expo-splash-screen-0.8.1.tgz#de4a018c82af879eeaa9b697013ef37d9567453a" - integrity sha512-7NQo8OgkfQ4sv4mIHE58fkiQTGyl5dOP70uAUTb5YXC/QUsHIqEpKQ6ZXDpkLU1cbZ32c8Vtok4r2FRIUrzxcg== +expo-splash-screen@~0.10.2: + version "0.10.2" + resolved "https://registry.yarnpkg.com/expo-splash-screen/-/expo-splash-screen-0.10.2.tgz#3e3d7c24c4ed180a60ce3ec64a77eefd04dd0d97" + integrity sha512-ngelW7g5yFqk3LWbyLDDxi3LYXEfgGFCJddL/Q8S/C1pMUc5foW2j9i/q+akK8i5mjYtSx3+Bk/qbyX92QIF/w== dependencies: - "@expo/configure-splash-screen" "0.3.1" + "@expo/configure-splash-screen" "0.3.4" expo-status-bar@~1.0.4: version "1.0.4" @@ -6138,7 +6168,7 @@ idb@3.0.2: resolved "https://registry.yarnpkg.com/idb/-/idb-3.0.2.tgz#c8e9122d5ddd40f13b60ae665e4862f8b13fa384" integrity sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw== -ieee754@^1.1.13: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -9488,10 +9518,10 @@ react-native-iphone-x-helper@^1.3.0, react-native-iphone-x-helper@^1.3.1: resolved "https://registry.yarnpkg.com/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.3.1.tgz#20c603e9a0e765fd6f97396638bdeb0e5a60b010" integrity sha512-HOf0jzRnq2/aFUcdCJ9w9JGzN3gdEg0zFE4FyYlp4jtidqU03D5X7ZegGKfT1EWteR0gPBGp9ye5T5FvSWi9Yg== -react-native-paper@^4.7.2: - version "4.7.2" - resolved "https://registry.yarnpkg.com/react-native-paper/-/react-native-paper-4.7.2.tgz#a40d1da87af5b030d45b525313cd703d490876ff" - integrity sha512-MOcDWjBOaknEpQgdm4fIOsRFIt4PJlMCgWlLk4kIe8Wv99/M0JIoxWABkAf4Lj5BuJgXjXdwr0DA/lhGY1BRoQ== +react-native-paper@^4.8.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/react-native-paper/-/react-native-paper-4.8.1.tgz#ade4e552e2aaecfc3096c8aebda37bd99facf63f" + integrity sha512-WgmqrDdcrr0ZbuiLCwMpmOMhl1n8uIvNulxsl2oCGtD8oeMkPJKHf4G/ONR+iNrSXcFbJek+uDRSmcGA5kDfUA== dependencies: "@callstack/react-theme-provider" "^3.0.5" color "^3.1.2" @@ -10761,6 +10791,11 @@ tmpl@1.0.x: resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= +to-data-view@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/to-data-view/-/to-data-view-1.1.0.tgz#08d6492b0b8deb9b29bdf1f61c23eadfa8994d00" + integrity sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ== + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"