I thought it would be pretty straightforward to use a js library that is packaged with npm but I'm not having any luck. Any suggestions would be greatly appreciated. These are the steps I took.
- I installed a library with:
npm install hotp-totp;
- I then created a file for a custom component:
//otp.js
import React from 'react';
import {
Text,
View,
} from 'react-native';
import totp from 'hotp-totp';
const OTP = () => {
let secret = 'MNWRM734ZIOEZYEYCAW4I6EX';
let token = totp(secret);
return (
<View>
<Text>
{ token }
</Text>
</View>
)
}
export default OTP
I then import this component and attempt to render:
//App.js
import OTP from './otp.js';
const App: () => Node = () => {
return (
<SafeAreaView >
<ScrollView
contentInsetAdjustmentBehavior="automatic">
<OTP />
</ScrollView>
</SafeAreaView>
);
};
When I then try to run on my Android device I get the following error trace:
ERROR TypeError: (0, _hotpTotp.default) is not a function. (In '(0, _hotpTotp.default)(secret)', '(0, _hotpTotp.default)' is an instance of Object)
This error is located at:
in OTP (at App.js:74)
in RCTView (at View.js:32)
in View (at ScrollView.js:1682)
in RCTScrollView (at ScrollView.js:1800)
in ScrollView (at ScrollView.js:1826)
in ScrollView (at App.js:69)
in RCTView (at View.js:32)
in View (at SafeAreaView.js:41)
in SafeAreaView (at App.js:67)
in App (at renderApplication.js:50)
in RCTView (at View.js:32)
in View (at AppContainer.js:92)
in RCTView (at View.js:32)
in View (at AppContainer.js:119)
in AppContainer (at renderApplication.js:43)
in otp(RootComponent) (at renderApplication.js:60)
ERROR TypeError: (0, _hotpTotp.default) is not a function. (In '(0, _hotpTotp.default)(secret)', '(0, _hotpTotp.default)' is an instance of Object)
The library hotp-totp is pretty straightforward and I include it below for reference.
/* node_modules/hotp-totp/index.js */
import base32 from 'thirty-two';
// Time-based OTP
const totp = async (secret) => {
return hotp( secret, Math.floor( new Date() / 30000 ) );
}
// HMAC-based OTP
const hotp = async (secret, counter) => {
// Uint8Array(20)
const hmac = async (secret, counter) => {
const keyData = Uint8Array.from(base32.decode(secret));
const key = await crypto.subtle.importKey(
'raw',
keyData,
{ name: 'HMAC', hash: { name: 'SHA-1' } },
false,
['sign']
);
return new Uint8Array(
await crypto.subtle.sign('HMAC', key, padCounter(counter))
);
}
// Uint8Array(8)
const padCounter = (counter) => {
const pairs = counter.toString(16).padStart(16, '0').match(/..?/g);
const array = pairs.map(v => parseInt(v, 16));
return Uint8Array.from( array );
}
// Number
function truncate(hs) {
const offset = hs[19] & 0b1111;
return ((hs[offset] & 0x7f) << 24) | (hs[offset 1] << 16) | (hs[offset 2] << 8) | hs[offset 3];
}
// HOTP(K, C) = truncate(HMAC(K, C))
const num = truncate( await hmac(secret, counter) );
// return 6 digits, padded with leading zeros
return num.toString().padStart(6, '0').slice(-6);
}
/**/
export default {
hotp,
totp,
}
Any help would be greatly appreciated.
CodePudding user response:
You need to import totp like this
import {default as hotptotp} from 'hotp-totp
const {totp} = hotptotp
You can read more about it here