home,signin,login view and ol logik
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
|
||||
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
/// Retrieves the current date in the format "yyyy-MM-dd".
|
||||
///
|
||||
/// @return [String] A formatted date.
|
||||
String getCurrentDate(DateTime date) {
|
||||
return DateFormat("yyyy-MM-dd").format(date);
|
||||
}
|
||||
|
||||
var kListDropDownYear = <int>[
|
||||
for (var year = DateTime.now().year; year >= 2020; year--) year
|
||||
];
|
||||
|
||||
var kCurrentUserIdentId = '';
|
||||
@@ -0,0 +1,10 @@
|
||||
import 'dart:io';
|
||||
|
||||
class MyHttpOverrides extends HttpOverrides {
|
||||
@override
|
||||
HttpClient createHttpClient(SecurityContext? context) {
|
||||
return super.createHttpClient(context)
|
||||
..badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) => true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:cryptography/cryptography.dart';
|
||||
|
||||
class PasswordHelper {
|
||||
static const int _saltLength = 16;
|
||||
static const int _hashLength = 32;
|
||||
|
||||
// 19 MiB, laut aktueller cryptography-Doku ein sinnvoller Startwert.
|
||||
static const int _memory = 19 * 1024;
|
||||
static const int _iterations = 2;
|
||||
static const int _parallelism = 1;
|
||||
|
||||
static final Argon2id _algorithm = Argon2id(
|
||||
memory: _memory,
|
||||
iterations: _iterations,
|
||||
parallelism: _parallelism,
|
||||
hashLength: _hashLength,
|
||||
);
|
||||
|
||||
/// Erstellt einen neuen Passwort-Hash inklusive zufälligem Salt.
|
||||
///
|
||||
/// Rückgabeformat:
|
||||
/// argon2id$memory$iterations$parallelism$saltBase64$hashBase64
|
||||
static Future<String> hashPassword(String password) async {
|
||||
final salt = _generateSalt(_saltLength);
|
||||
|
||||
final secretKey = await _algorithm.deriveKeyFromPassword(
|
||||
password: password,
|
||||
nonce: salt,
|
||||
);
|
||||
|
||||
final hashBytes = await secretKey.extractBytes();
|
||||
|
||||
final saltBase64 = base64UrlEncode(salt);
|
||||
final hashBase64 = base64UrlEncode(hashBytes);
|
||||
|
||||
return 'argon2id'
|
||||
'\$$_memory'
|
||||
'\$$_iterations'
|
||||
'\$$_parallelism'
|
||||
'\$$saltBase64'
|
||||
'\$$hashBase64';
|
||||
}
|
||||
|
||||
/// Prüft ein Klartext-Passwort gegen den gespeicherten Hash.
|
||||
static Future<bool> verifyPassword(
|
||||
String password,
|
||||
String storedHash,
|
||||
) async {
|
||||
try {
|
||||
final parts = storedHash.split('\$');
|
||||
|
||||
if (parts.length != 6) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parts[0] != 'argon2id') {
|
||||
return false;
|
||||
}
|
||||
|
||||
final memory = int.parse(parts[1]);
|
||||
final iterations = int.parse(parts[2]);
|
||||
final parallelism = int.parse(parts[3]);
|
||||
|
||||
final salt = base64Url.decode(parts[4]);
|
||||
final expectedHash = base64Url.decode(parts[5]);
|
||||
|
||||
final algorithm = Argon2id(
|
||||
memory: memory,
|
||||
iterations: iterations,
|
||||
parallelism: parallelism,
|
||||
hashLength: expectedHash.length,
|
||||
);
|
||||
|
||||
final secretKey = await algorithm.deriveKeyFromPassword(
|
||||
password: password,
|
||||
nonce: salt,
|
||||
);
|
||||
|
||||
final calculatedHash = await secretKey.extractBytes();
|
||||
|
||||
return _constantTimeEquals(
|
||||
calculatedHash,
|
||||
expectedHash,
|
||||
);
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Erzeugt kryptographisch zufälligen Salt.
|
||||
static List<int> _generateSalt(int length) {
|
||||
final random = Random.secure();
|
||||
|
||||
return List<int>.generate(
|
||||
length,
|
||||
(_) => random.nextInt(256),
|
||||
);
|
||||
}
|
||||
|
||||
/// Vergleich ohne vorzeitigen Abbruch.
|
||||
static bool _constantTimeEquals(
|
||||
List<int> a,
|
||||
List<int> b,
|
||||
) {
|
||||
if (a.length != b.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var difference = 0;
|
||||
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
difference |= a[i] ^ b[i];
|
||||
}
|
||||
|
||||
return difference == 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../controller/home_controller.dart';
|
||||
import '../controller/login_controller.dart';
|
||||
import '../controller/signin_controller.dart';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class SampleBindings extends Bindings {
|
||||
@override
|
||||
void dependencies() {
|
||||
// Define your dependencies here no permanent Binding
|
||||
Get.lazyPut<LoginController>(() => LoginController());
|
||||
Get.lazyPut<SigninController>(() => SigninController());
|
||||
Get.lazyPut<HomeController>(() => HomeController());
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import 'package:get/get.dart';
|
||||
import '../pages/home_view.dart';
|
||||
import '../pages/login_view.dart';
|
||||
import '../pages/signin_view.dart';
|
||||
import 'sample_bindings.dart';
|
||||
|
||||
class SampleRouts {
|
||||
static final sampleBindings = SampleBindings();
|
||||
static List<GetPage<dynamic>> samplePages = [
|
||||
GetPage(
|
||||
name: LoginPage.namedRoute,
|
||||
page: () => const LoginPage(),
|
||||
binding: sampleBindings,
|
||||
),
|
||||
GetPage(
|
||||
name: SigninPage.namedRoute,
|
||||
page: () => const SigninPage(),
|
||||
binding: sampleBindings,
|
||||
),
|
||||
GetPage(
|
||||
name: HomePage.namedRoute,
|
||||
page: () => const HomePage(),
|
||||
binding: sampleBindings,
|
||||
),
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user