Newer
Older
import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
import 'package:encrypt/encrypt.dart' as encrypt;
import 'package:encrypt/encrypt.dart';
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
Random createRandom() {
try {
return Random.secure();
} catch (e) {
return Random();
}
}
Uint8List generateUintSeed() {
final Random random = createRandom();
return Uint8List.fromList(List<int>.generate(32, (_) => random.nextInt(256)));
}
String seedToString(Uint8List seed) {
final Uint8List seedsBytes = Uint8List.fromList(seed);
final String encoded = json.encode(seedsBytes.toList());
return encoded;
}
CesiumWallet generateCesiumWallet(Uint8List seed) {
return CesiumWallet.fromSeed(seed);
}
Uint8List seedFromString(String sString) {
final List<dynamic> list = json.decode(sString) as List<dynamic>;
final Uint8List bytes =
Uint8List.fromList(list.map((dynamic e) => e as int).toList());
return bytes;
}
String generateSalt(int length) {
final Random random = createRandom();
const String charset =
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
return List<String>.generate(
length, (int index) => charset[random.nextInt(charset.length)]).join();
}
endpointUnParsed = endpointUnParsed.replaceFirst('GVA S', 'GVA_S');
try {
final List<String> parts = endpointUnParsed.split(' ');
// FIXME (vjrj): figure out if exists a way to detect http or https
const String protocol = 'https';
final String lastPart = parts.removeLast();
String path =
RegExp(r'^\/[a-zA-Z0-9\-\/]+$').hasMatch(lastPart) ? lastPart : '';
final String nextToLast = parts[parts.length - 1];
? (RegExp(r'^[0-9]+$').hasMatch(lastPart) ? lastPart : '443')
: RegExp(r'^[0-9]+$').hasMatch(nextToLast)
? nextToLast
: '443';
final List<String> hostSplited = parts[1].split('/');
// Process hosts like monnaie-libre.ortie.org/bma/
final String host = hostSplited[0];
path = path.isEmpty
? ((hostSplited.length > 1 && hostSplited[1].isNotEmpty
? hostSplited[1]
: '')
.isNotEmpty
? hostSplited.length > 1 && hostSplited[1].isNotEmpty
? '/${hostSplited[1]}'
: ''
: path)
: path;
if (port == '443') {
port = '';
} else {
port = ':$port';
}
final String endpoint = '$protocol://$host$port$path'.trim();
Sentry.captureMessage("Error $e trying to parse '$endpointUnParsed'");
r'^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44}$')
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
bool validateKey(String pubKey) {
final RegExp regex = RegExp(
r'^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44}(:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{3}))?$',
);
if (!regex.hasMatch(pubKey)) {
return false;
}
final List<String> parts = pubKey.split(':');
final String publicKeyPart = parts[0];
if (parts.length == 2) {
final String checksumPart = parts[1];
if (pkChecksum(publicKeyPart) != checksumPart) {
return false;
}
}
return true;
}
String pkChecksum(String pubkey) {
List<int> signpkInt8;
// Remove leading '1'
if (pubkey.length == 44 && pubkey.startsWith('1')) {
signpkInt8 = Base58Decode(pubkey.substring(1));
} else {
signpkInt8 = Base58Decode(pubkey);
}
// Double SHA256 hash
final Digest firstHash = sha256.convert(signpkInt8);
final Digest secondHash = sha256.convert(firstHash.bytes);
// Base58 encode and take the first 3 characters
final String checksum = Base58Encode(secondHash.bytes).substring(0, 3);
return checksum;
}
String getQrUri(
{required String pubKey, String locale = 'en', String amount = '0'}) {
double amountD;
try {
amountD = parseToDoubleLocalized(locale: locale, number: amount);
} catch (e) {
amountD = 0;
}
uri = 'june://$pubKey?amount=$amountD';
}
return uri;
}
PaymentState? parseScannedUri(String qr) {
final RegExp regexKeyCommentAmount = RegExp(
r'(duniter\:key|june\:\/)/(\w+)\?(comment=([^&]+))&amount=([\d.]+)');
final RegExpMatch? matchKeyCommentAmount =
regexKeyCommentAmount.firstMatch(qr);
if (matchKeyCommentAmount != null) {
final String publicKey = matchKeyCommentAmount.group(2)!;
final String? comment = matchKeyCommentAmount.group(4);
final double amount = double.parse(matchKeyCommentAmount.group(5)!);
return PaymentState(
contact: Contact(pubKey: publicKey),
amount: amount,
comment: comment ?? '');
}
final RegExp regexKeyAmount =
RegExp(r'(duniter\:key|june\:\/)/(\w+)\?amount=([\d.]+)');
final RegExpMatch? matchKeyAmount = regexKeyAmount.firstMatch(qr);
if (matchKeyAmount != null) {
final String publicKey = matchKeyAmount.group(2)!;
final double amount = double.parse(matchKeyAmount.group(3)!);
return PaymentState(contact: Contact(pubKey: publicKey), amount: amount);
final RegExp regexKey = RegExp(r'(duniter\:key|june\:\/)/(\w+)');
final RegExpMatch? matchKey = regexKey.firstMatch(qr);
if (matchKey != null) {
final String publicKey = matchKey.group(2)!;
final IV _iv = encrypt.IV.fromLength(16);
Map<String, String> encryptJsonForExport(String jsonString, String password) {
final Uint8List plainText = Uint8List.fromList(utf8.encode(jsonString));
final encrypt.Encrypted encrypted = encrypt.Encrypter(
encrypt.AES(encrypt.Key.fromUtf8(password.padRight(32))))
.encryptBytes(plainText, iv: _iv);
final Map<String, String> jsonData = <String, String>{
'key': base64Encode(encrypted.bytes)
};
return jsonData;
}
Map<String, dynamic> decryptJsonForImport(
String keyEncrypted, String password) {
final String decrypted = encrypt.Encrypter(
encrypt.AES(encrypt.Key.fromUtf8(password.padRight(32))))
.decrypt64(keyEncrypted, iv: _iv);
return jsonDecode(decrypted) as Map<String, dynamic>;
}
bool areDatesClose(DateTime date1, DateTime date2, Duration threshold) {
return date1.difference(date2).abs() <= threshold;
}
double toG1(double amount, bool isG1, double currentUd) {
return isG1 ? amount : amount * currentUd;
}