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"