mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-31 06:58:42 +01:00
Upstream reformatted its whole tree in 16ddc0837. Matching it removes
formatting from the conflict surface of this and every later sync.
84 lines
2.3 KiB
Dart
84 lines
2.3 KiB
Dart
import 'dart:math';
|
|
import 'package:base32/base32.dart';
|
|
import 'package:crypto/crypto.dart';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
//*========================== TOTP 2FA Related Utilities ==========================================
|
|
|
|
String generateRandomBase32SecretKey(int byteLength) {
|
|
final Random _secureRandom = Random.secure();
|
|
// Generate random bytes
|
|
final randomBytes = Uint8List.fromList(
|
|
List<int>.generate(byteLength, (i) => _secureRandom.nextInt(256)),
|
|
);
|
|
|
|
// Encode bytes to base32
|
|
final base32SecretKey = base32.encode(randomBytes);
|
|
|
|
return base32SecretKey;
|
|
}
|
|
|
|
String generateOTP({required String secretKey, required int input}) {
|
|
/// base32 decode the secret
|
|
var hmacKey = base32.decode(secretKey);
|
|
|
|
/// initial the HMAC-SHA1 object
|
|
var hmacSha = Hmac(sha512, hmacKey);
|
|
|
|
/// get hmac answer
|
|
var hmac = hmacSha.convert(intToBytelist(input: input)).bytes;
|
|
|
|
/// calculate the init offset
|
|
int offset = hmac[hmac.length - 1] & 0xf;
|
|
|
|
/// calculate the code
|
|
int code = ((hmac[offset] & 0x7f) << 24 |
|
|
(hmac[offset + 1] & 0xff) << 16 |
|
|
(hmac[offset + 2] & 0xff) << 8 |
|
|
(hmac[offset + 3] & 0xff));
|
|
|
|
/// get the initial string code
|
|
var strCode = (code % pow(10, 8)).toString();
|
|
strCode = strCode.padLeft(8, '0');
|
|
|
|
return strCode;
|
|
}
|
|
|
|
List<int> intToBytelist({required int input, int padding = 8}) {
|
|
List<int> _result = [];
|
|
var _input = input;
|
|
while (_input != 0) {
|
|
_result.add(_input & 0xff);
|
|
_input >>= padding;
|
|
}
|
|
_result.addAll(List<int>.generate(padding, (_) => 0));
|
|
_result = _result.sublist(0, padding);
|
|
_result = _result.reversed.toList();
|
|
return _result;
|
|
}
|
|
|
|
String totpNow(String secretKey) {
|
|
int _formatTime = timeFormat(time: DateTime.now());
|
|
return generateOTP(input: _formatTime, secretKey: secretKey);
|
|
}
|
|
|
|
int timeFormat({required DateTime time}) {
|
|
final _timeStr = time.millisecondsSinceEpoch.toString();
|
|
final _formatTime = _timeStr.substring(0, _timeStr.length - 3);
|
|
|
|
return int.parse(_formatTime) ~/ 30;
|
|
}
|
|
|
|
bool verify({String? otp, DateTime? time, required String secretKey}) {
|
|
if (otp == null) {
|
|
return false;
|
|
}
|
|
|
|
var _time = time ?? DateTime.now();
|
|
var _input = timeFormat(time: _time);
|
|
|
|
String otpTime = generateOTP(input: _input, secretKey: secretKey);
|
|
return otp == otpTime;
|
|
}
|