Skip to content
Snippets Groups Projects
Commit 69ccfa23 authored by poka's avatar poka
Browse files

Scrypt derivator is working as Bip32 standart

parent 3bb9cdab
Branches
Tags
No related merge requests found
......@@ -9,7 +9,7 @@ void main() {
final mnemonic = generateMnemonic(lang: mnemonicLang);
// Build HdWallet object from mnemonic
HdWallet _hdWallet = HdWallet.fromMnemonic(mnemonic, lang: mnemonicLang);
HdWallet _hdWallet = HdWallet.fromMnemonic(mnemonic);
// Get pubkey of derivation number $derivation
String pubkey = _hdWallet.getPubkey(harden(derivation));
......@@ -34,7 +34,7 @@ void main() {
String? decryptedDewif;
try {
decryptedDewif =
_dewif.mnemonicFromDewif(_dewifData, 'ABCDE', lang: mnemonicLang);
_dewif.mnemonicFromDewif(_dewifData.dewif, 'ABCDE', lang: mnemonicLang);
print('Unlock: ' + decryptedDewif);
} on ChecksumException {
print('Bad secret code');
......@@ -65,7 +65,7 @@ void main() {
Uint8List? decryptedCesiumDewif;
try {
decryptedCesiumDewif =
_dewif.cesiumSeedFromDewif(_dewifCesiumData, 'FGHIJ');
_dewif.cesiumSeedFromDewif(_dewifCesiumData.dewif, 'FGHIJ');
print('Unlock: ' + decryptedCesiumDewif.toString());
} on ChecksumException {
print('Bad secret code');
......
......@@ -17,6 +17,7 @@ library durt;
export 'src/crypto/hd_wallet.dart'
show HdWallet, generateMnemonic, harden, isHardened;
export 'src/crypto/dewif.dart' show Dewif, randomSecretCode, ChecksumException;
export 'src/crypto/dewif.dart'
show Dewif, randomSecretCode, ChecksumException, NewWallet;
export 'src/crypto/cesium_wallet.dart' show CesiumWallet;
export 'src/gva/gva.dart' show Gva;
......@@ -51,7 +51,7 @@ class Dewif {
/// Return the base64 DEWIF string generated from given mnemonic and password.
/// You can optionnaly specify a custom parameters, as language for mnemonic (default is enhlish)
/// More detail in the Duniter RFC13: https://git.duniter.org/documents/rfcs/blob/master/rfc/0013_Duniter_Encrypted_Wallet_Import_Format.md
String generateDewif(String mnemonic, String password,
NewWallet generateDewif(String mnemonic, String password,
{String lang = 'english',
int dewifCurrencyCode = DEWIF_CURRENCY_CODE_G1,
int dewifVersion = DEWIF_VERSION,
......@@ -139,7 +139,7 @@ class Dewif {
// print('Checksum: ' + HEX.encode(checksum));
// print(data);
return base64Data;
return NewWallet._(base64Data, password);
}
/// Decrypt the given DEWIF in base64 string format and associated password.
......@@ -229,8 +229,45 @@ class Dewif {
}
}
bool isNumeric(string) => num.tryParse(string) != null;
NewWallet changePassword(
{required String dewif,
required String oldPassword,
String? newPassword,
String lang = 'english',
int dewifCurrencyCode = DEWIF_CURRENCY_CODE_G1,
int dewifVersion = DEWIF_VERSION}) {
final mnemonic = mnemonicFromDewif(dewif, oldPassword,
lang: lang,
dewifCurrencyCode: dewifCurrencyCode,
dewifVersion: dewifVersion);
newPassword ??=
randomSecretCode(oldPassword.length, isNum: isNumeric(oldPassword));
return generateDewif(mnemonic, newPassword,
lang: lang,
dewifCurrencyCode: dewifCurrencyCode,
dewifVersion: dewifVersion);
}
NewWallet changeCesiumPassword(
{required String dewif,
required String oldPassword,
String? newPassword,
int dewifCurrencyCode = DEWIF_CURRENCY_CODE_G1,
int dewifVersion = DEWIF_VERSION}) {
final seed = cesiumSeedFromDewif(dewif, oldPassword,
dewifCurrencyCode: dewifCurrencyCode, dewifVersion: dewifVersion);
newPassword ??=
randomSecretCode(oldPassword.length, isNum: isNumeric(oldPassword));
return generateCesiumDewif(seed, newPassword,
dewifCurrencyCode: dewifCurrencyCode, dewifVersion: dewifVersion);
}
/// Return the base64 DEWIF string generated from given seed and password.
String generateCesiumDewif(Uint8List seed, String password,
NewWallet generateCesiumDewif(Uint8List seed, String password,
{int dewifCurrencyCode = DEWIF_CURRENCY_CODE_G1,
int dewifVersion = DEWIF_VERSION,
bool test = false}) {
......@@ -306,7 +343,7 @@ class Dewif {
// print('Checksum: ' + HEX.encode(checksum));
// print(data);
return base64Data;
return NewWallet._(base64Data, password);
}
/// Decrypt the given Cesium DEWIF in base64 string format and associated password.
......@@ -383,3 +420,10 @@ class ChecksumException implements Exception {
String cause;
ChecksumException(this.cause);
}
class NewWallet {
final String dewif;
final String password;
NewWallet._(this.dewif, this.password);
}
......@@ -3,23 +3,23 @@ import 'package:durt/durt.dart';
import 'package:fast_base58/fast_base58.dart';
import 'package:bip32_ed25519/api.dart';
import 'package:bip39_multi_nullsafety/bip39_multi_nullsafety.dart' as bip39;
import 'package:pinenacl/key_derivation.dart';
// import 'package:hex/hex.dart';
// import 'package:pinenacl/key_derivation.dart';
import 'package:pointycastle/digests/sha256.dart';
import 'package:pointycastle/digests/sha512.dart';
import 'package:pointycastle/pointycastle.dart'
show ScryptParameters, KeyDerivator;
class HdWallet {
final Bip32SigningKey rootSigningKey;
Bip32KeyPair key;
/// Root constructor taking a root signing key
HdWallet({required this.rootSigningKey, required this.key});
HdWallet({required this.key});
/// Build the root signing key based on given mnemonic.
factory HdWallet.fromMnemonic(String mnemonic, {String lang = 'english'}) {
factory HdWallet.fromMnemonic(String mnemonic) {
Bip32SigningKey rootSigningKeyFactory = _bip32signingKey(mnemonic);
return HdWallet(
rootSigningKey: rootSigningKeyFactory,
key: Bip32KeyPair(
signingKey: rootSigningKeyFactory,
verifyKey: rootSigningKeyFactory.verifyKey));
......@@ -31,7 +31,7 @@ class HdWallet {
}
/// return the root signing key
Bip32VerifyKey get rootVerifyKey => rootSigningKey.verifyKey;
Bip32VerifyKey? get rootVerifyKey => key.verifyKey;
/// derive root signing key given a seed
static Bip32SigningKey _bip32signingKey(String mnemonic) {
......@@ -41,32 +41,33 @@ class HdWallet {
// final mnemonicBytes = Uint8List.fromList(mnemonic.codeUnits);
final salt = sha256('dubp'.codeUnits + mnemonicUtf8);
// With pointyCastle lib: Very slower
//// Pbkdf2 version
// final seed = PBKDF2.hmac_sha512(
// mnemonicUtf8, salt, 4096, cip16ExtendedSigningKeySize);
//// With pointyCastle lib: Very slower
// final rawMaster = KeyDerivator('SHA-512/HMAC/PBKDF2')
// ..init(Pbkdf2Parameters(seed, 4096, cip16ExtendedSigningKeySize));
// final Bip32SigningKey rootXsk =
// Bip32SigningKey.normalizeBytes(rawMaster.process(Uint8List(0)));
// Scrypt version
final scrypt = KeyDerivator('scrypt');
scrypt.init(
final scrypt = KeyDerivator('scrypt')
..init(
ScryptParameters(
4096, //2^12
16,
1,
cip16ExtendedSigningKeySize, //RFC: 32; Expected: 96 (cip16ExtendedSigningKeySize); Problem...
32,
salt,
),
);
final seed = scrypt.process(mnemonicUtf8);
// Pbkdf2 version
// final seed = PBKDF2.hmac_sha512(
// mnemonicUtf8, salt, 4096, cip16ExtendedSigningKeySize);
final signingKey = Bip32SigningKey.normalizeBytes(seed);
final privateKey = SHA512Digest().process(seed);
final chainCode = sha256([1] + seed);
return signingKey;
return Bip32SigningKey.normalizeBytes(
Uint8List.fromList(privateKey + chainCode));
}
/// If a parent signing key is provided, a child signing key is generated. If a parent
......@@ -125,9 +126,6 @@ String generateMnemonic({String lang = 'english'}) {
/// They are denoted by a single quote in chain values.
const int hardenedOffset = 0x80000000;
/// Extended private key size in bytes
const cip16ExtendedSigningKeySize = 96;
/// Hardens index, meaning it won't have a public key
int harden(int index) => index | hardenedOffset;
......
......@@ -67,7 +67,9 @@ class Gva {
}
/// Pay a given pubkey.
Future<bool> pay(
/// This automatically recognizes whether it is an HD wallet or a Cesium wallet.
/// Return 'success' string if the transaction has been successfuly proced, or the specified error
Future<String> pay(
{required String recipient,
required double amount,
required String dewif,
......
......@@ -174,23 +174,20 @@ class Transaction {
return false;
}
Future<bool> process() async {
Future<String> process() async {
try {
final List transDocs = await _generateTransactionDocument();
if (_checkTransactionDocument(transDocs)) {
final List signedDocs = _signDocument(transDocs);
final bool result = await _sendSignedDocuments(signedDocs);
return result;
return result ? 'success' : 'Error with transaction document';
} else {
print('Transaction document is not valid.');
return false;
return 'Transaction document is not valid.';
}
} on GraphQLException catch (e) {
print('GraphQL error: ' + e.cause.split('message: ')[1].split(',')[0]);
return false;
return e.cause.split('message: ')[1].split(',')[0];
} on MySelfException catch (e) {
print(e.cause);
return false;
return e.cause;
}
}
}
......
name: durt
description: Dart lib for duniter cryptography, useful to integrate Ğ1 libre currency to your app
version: 0.1.3
version: 0.1.3+3
homepage: https://git.duniter.org/pokapow/durt.git
environment:
......
......@@ -13,14 +13,15 @@ void main() {
var _dewifDataTest = _dewif.generateCesiumDewif(
cesiumWallet.seed, 'JKSPU',
dewifCurrencyCode: DEWIF_CURRENCY_CODE_G1_TEST, test: true);
print('Lock: ' + _dewifDataTest);
print('Lock: ' + _dewifDataTest.dewif);
expect(_dewifDataTest,
expect(_dewifDataTest.dewif,
'AAAAARAAAAEOAcVCma5x/ipOzcfViv8J5cdgASn7zedlNz6M/19wbE79aNvILr1CEyM664m8BjgLKeWiz1GYJSR14+ZY61U=');
Uint8List? decryptedDewifTest;
try {
decryptedDewifTest = _dewif.cesiumSeedFromDewif(_dewifDataTest, 'JKSPU',
decryptedDewifTest = _dewif.cesiumSeedFromDewif(
_dewifDataTest.dewif, 'JKSPU',
dewifCurrencyCode: DEWIF_CURRENCY_CODE_G1_TEST);
print('Unlock: ' + decryptedDewifTest.toString());
} on ChecksumException {
......@@ -71,11 +72,61 @@ void main() {
expect(reCesiumWallet.pubkey,
'A6o88pwgb24Ri3N6UEGALLGhVAm7vrK8fJYHxmw91JSc');
var rereCesiumWallet = CesiumWallet.fromDewif(_dewifDataTest, 'JKSPU',
var rereCesiumWallet = CesiumWallet.fromDewif(
_dewifDataTest.dewif, _dewifDataTest.password,
dewifCurrencyCode: DEWIF_CURRENCY_CODE_G1_TEST, test: true);
expect(rereCesiumWallet.pubkey,
'A6o88pwgb24Ri3N6UEGALLGhVAm7vrK8fJYHxmw91JSc');
// Change Dewif password
var changeDewifPassword = _dewif.changeCesiumPassword(
dewif: _dewifDataTest.dewif,
oldPassword: _dewifDataTest.password,
newPassword: 'NBVCP',
dewifCurrencyCode: DEWIF_CURRENCY_CODE_G1_TEST);
expect(changeDewifPassword.password, 'NBVCP');
var unlockChangeDewifPassword = _dewif.cesiumSeedFromDewif(
changeDewifPassword.dewif, 'NBVCP',
dewifCurrencyCode: DEWIF_CURRENCY_CODE_G1_TEST);
expect(
unlockChangeDewifPassword,
equals([
218,
9,
63,
33,
79,
188,
150,
119,
73,
112,
60,
104,
121,
153,
74,
219,
187,
169,
221,
222,
100,
88,
195,
12,
84,
214,
238,
116,
63,
37,
238,
124
]));
});
});
}
......@@ -13,12 +13,12 @@ void main() {
lang: 'english',
dewifCurrencyCode: DEWIF_CURRENCY_CODE_G1_TEST,
testRfc: true);
print(_dewifDataRFC);
print(_dewifDataRFC.dewif);
String? decryptedDewifRFC;
try {
decryptedDewifRFC = _dewif.mnemonicFromDewif(
_dewifDataRFC, 'toto titi tata',
_dewifDataRFC.dewif, _dewifDataRFC.password,
lang: 'english', dewifCurrencyCode: DEWIF_CURRENCY_CODE_G1_TEST);
print('Unlock: ' + decryptedDewifRFC);
} on ChecksumException {
......@@ -30,6 +30,22 @@ void main() {
decryptedDewifRFC?.trim(),
equals(
'crop cash unable insane eight faith inflict route frame loud box vibrant'));
// Change Dewif password
var changeDewifPassword = _dewif.changePassword(
dewif: _dewifDataRFC.dewif,
oldPassword: _dewifDataRFC.password,
newPassword: 'NBVCX',
lang: 'english',
dewifCurrencyCode: DEWIF_CURRENCY_CODE_G1_TEST);
expect(changeDewifPassword.password, 'NBVCX');
var unlockChangeDewifPassword = _dewif.mnemonicFromDewif(
changeDewifPassword.dewif, 'NBVCX',
lang: 'english', dewifCurrencyCode: DEWIF_CURRENCY_CODE_G1_TEST);
expect(unlockChangeDewifPassword,
'crop cash unable insane eight faith inflict route frame loud box vibrant');
});
});
}
......@@ -4,8 +4,8 @@ import 'package:durt/src/crypto/hd_wallet.dart';
void main() {
group('wallets', () {
test('Generate HD wallet', () {
const String mnemonicLang = 'english';
final int derivation = harden(2);
const String mnemonicLang = 'french';
final int derivation = harden(3);
print('------------------\n HD Wallet Test\n------------------\n');
var mnemonicTest = generateMnemonic(lang: mnemonicLang);
......@@ -13,11 +13,14 @@ void main() {
// String mnemonic =
// "mauve victoire victoire cupide chaleur minimal punaise utopie plumage géologie quitter chaise";
final mnemonic =
'acquire flat utility climb filter device liberty beyond matrix satisfy metal essence';
'guide chagrin honorer grand tablier sortir analyse lavoir circuler tarder exigence séance';
// final mnemonic =
// 'tongue cute mail fossil great frozen same social weasel impact brush kind';
// final mnemonic =
// 'acquire flat utility climb filter device liberty beyond matrix satisfy metal essence';
HdWallet _hdWallet = HdWallet.fromMnemonic(mnemonic, lang: mnemonicLang);
HdWallet _hdWallet = HdWallet.fromMnemonic(mnemonic);
String pubkey = _hdWallet.getPubkey(derivation);
......@@ -30,7 +33,7 @@ void main() {
print('Pubkey N°$derivation: ' + pubkey);
print('Is signature OK ? : ' + isOK.toString());
expect(pubkey, 'HWy7CLMNJCvk7QYYax5xxbLoqDqMj9fv5DSnfLcmpjEe');
expect(pubkey, 'GauM5qWiX1uzqSdRRM51it95sMdadLnsNrRKSoMQU6xd');
expect(isOK, true);
});
});
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment