Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
D
dup-crypto-rs
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
libs
dup-crypto-rs
Commits
d260efcf
Commit
d260efcf
authored
5 years ago
by
Éloïs
Browse files
Options
Downloads
Patches
Plain Diff
[feat] dewif: add field currency
parent
aa3213a5
No related branches found
Branches containing commit
No related tags found
Tags containing commit
1 merge request
!4
[feat] dewif: add field currency
Pipeline
#8227
passed
5 years ago
Stage: fmt
Stage: tests
Stage: quality
Changes
4
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
src/dewif.rs
+34
-19
34 additions, 19 deletions
src/dewif.rs
src/dewif/currency.rs
+155
-0
155 additions, 0 deletions
src/dewif/currency.rs
src/dewif/read.rs
+56
-15
56 additions, 15 deletions
src/dewif/read.rs
src/dewif/write.rs
+48
-5
48 additions, 5 deletions
src/dewif/write.rs
with
293 additions
and
39 deletions
src/dewif.rs
+
34
−
19
View file @
d260efcf
...
@@ -18,8 +18,9 @@
...
@@ -18,8 +18,9 @@
//! # Write ed25519 key-pair in DEWIF file
//! # Write ed25519 key-pair in DEWIF file
//!
//!
//! ```
//! ```
//! use dup_crypto::dewif::write_dewif_v1_content;
//! use dup_crypto::dewif::
{Currency, G1_TEST_CURRENCY,
write_dewif_v1_content
}
;
//! use dup_crypto::keys::ed25519::{KeyPairFromSaltedPasswordGenerator, SaltedPassword};
//! use dup_crypto::keys::ed25519::{KeyPairFromSaltedPasswordGenerator, SaltedPassword};
//! use std::num::NonZeroU32;
//!
//!
//! // Get user credentials (from cli prompt or gui)
//! // Get user credentials (from cli prompt or gui)
//! let credentials = SaltedPassword::new("user salt".to_owned(), "user password".to_owned());
//! let credentials = SaltedPassword::new("user salt".to_owned(), "user password".to_owned());
...
@@ -31,10 +32,10 @@
...
@@ -31,10 +32,10 @@
//! let encryption_passphrase = "toto titi tata";
//! let encryption_passphrase = "toto titi tata";
//!
//!
//! // Serialize keypair in DEWIF format
//! // Serialize keypair in DEWIF format
//! let dewif_content = write_dewif_v1_content(&keypair, encryption_passphrase);
//! let dewif_content = write_dewif_v1_content(
Currency::from(G1_TEST_CURRENCY),
&keypair, encryption_passphrase);
//!
//!
//! assert_eq!(
//! assert_eq!(
//! "AAAAA
THfJ3vTvEPcXm22NwhJtnNdGuSjikpSYIMgX96Z9xVT0y8GoIlBL1HaxaWpu0jVDfuwtCGSP9bu2pj6HGbuYVA=
",
//! "AAAAA
RAAAAEx3yd707xD3F5ttjcISbZzXRrko4pKUmCDIF/emfcVU9MvBqCJQS9R2sWlqbtI1Q37sLQhkj/W7tqY+hxm7mFQ
",
//! dewif_content
//! dewif_content
//! )
//! )
//! ```
//! ```
...
@@ -42,18 +43,23 @@
...
@@ -42,18 +43,23 @@
//! # Read DEWIF file
//! # Read DEWIF file
//!
//!
//! ```
//! ```
//! use dup_crypto::dewif::read_dewif_file_content;
//! use dup_crypto::dewif::
{Currency, ExpectedCurrency,
read_dewif_file_content
}
;
//! use dup_crypto::keys::{KeyPair, Signator};
//! use dup_crypto::keys::{KeyPair, Signator};
//! use std::num::NonZeroU32;
//! use std::str::FromStr;
//!
//!
//! // Get DEWIF file content (Usually from disk)
//! // Get DEWIF file content (Usually from disk)
//! let dewif_file_content = "AAAAA
THfJ3vTvEPcXm22NwhJtnNdGuSjikpSYIMgX96Z9xVT0y8GoIlBL1HaxaWpu0jVDfuwtCGSP9bu2pj6HGbuYVA=
";
//! let dewif_file_content = "AAAAA
RAAAAEx3yd707xD3F5ttjcISbZzXRrko4pKUmCDIF/emfcVU9MvBqCJQS9R2sWlqbtI1Q37sLQhkj/W7tqY+hxm7mFQ
";
//!
//!
//! // Get user passphrase for DEWIF decryption (from cli prompt or gui)
//! // Get user passphrase for DEWIF decryption (from cli prompt or gui)
//! let encryption_passphrase = "toto titi tata";
//! let encryption_passphrase = "toto titi tata";
//!
//!
//! // Expected currency
//! let expected_currency = ExpectedCurrency::Specific(Currency::from_str("g1-test").expect("unknown currency"));
//!
//! // Read DEWIF file content
//! // Read DEWIF file content
//! // If the file content is correct, we get a key-pair iterator.
//! // If the file content is correct, we get a key-pair iterator.
//! let mut key_pair_iter = read_dewif_file_content(dewif_file_content, encryption_passphrase)?;
//! let mut key_pair_iter = read_dewif_file_content(
expected_currency,
dewif_file_content, encryption_passphrase)?;
//!
//!
//! // Get first key-pair
//! // Get first key-pair
//! let key_pair = key_pair_iter
//! let key_pair = key_pair_iter
...
@@ -81,9 +87,11 @@
...
@@ -81,9 +87,11 @@
//! ```
//! ```
//!
//!
mod
currency
;
mod
read
;
mod
read
;
mod
write
;
mod
write
;
pub
use
currency
::{
Currency
,
ExpectedCurrency
,
G1_CURRENCY
,
G1_TEST_CURRENCY
};
pub
use
read
::{
read_dewif_file_content
,
DewifReadError
};
pub
use
read
::{
read_dewif_file_content
,
DewifReadError
};
pub
use
write
::{
write_dewif_v1_content
,
write_dewif_v2_content
};
pub
use
write
::{
write_dewif_v1_content
,
write_dewif_v2_content
};
...
@@ -92,17 +100,17 @@ use crate::seeds::Seed32;
...
@@ -92,17 +100,17 @@ use crate::seeds::Seed32;
use
arrayvec
::
ArrayVec
;
use
arrayvec
::
ArrayVec
;
use
unwrap
::
unwrap
;
use
unwrap
::
unwrap
;
const
VERSION
_BYTES
:
usize
=
4
;
const
UNENCRYPTED
_BYTES
_LEN
:
usize
=
8
;
// v1
// v1
static
VERSION_V1
:
&
[
u8
]
=
&
[
0
,
0
,
0
,
1
];
static
VERSION_V1
:
&
[
u8
]
=
&
[
0
,
0
,
0
,
1
];
const
V1_BYTES_LEN
:
usize
=
68
;
const
V1_BYTES_LEN
:
usize
=
72
;
const
V1_ENCRYPTED_BYTES_LEN
:
usize
=
64
;
const
V1_ENCRYPTED_BYTES_LEN
:
usize
=
64
;
const
V1_AES_BLOCKS_COUNT
:
usize
=
4
;
const
V1_AES_BLOCKS_COUNT
:
usize
=
4
;
// v2
// v2
static
VERSION_V2
:
&
[
u8
]
=
&
[
0
,
0
,
0
,
2
];
static
VERSION_V2
:
&
[
u8
]
=
&
[
0
,
0
,
0
,
2
];
const
V2_BYTES_LEN
:
usize
=
13
2
;
const
V2_BYTES_LEN
:
usize
=
13
6
;
const
V2_ENCRYPTED_BYTES_LEN
:
usize
=
128
;
const
V2_ENCRYPTED_BYTES_LEN
:
usize
=
128
;
fn
gen_aes_seed
(
passphrase
:
&
str
)
->
Seed32
{
fn
gen_aes_seed
(
passphrase
:
&
str
)
->
Seed32
{
...
@@ -133,11 +141,13 @@ mod tests {
...
@@ -133,11 +141,13 @@ mod tests {
#[test]
#[test]
fn
dewif_v1
()
{
fn
dewif_v1
()
{
let
written_keypair
=
KeyPairFromSeed32Generator
::
generate
(
Seed32
::
new
([
0u8
;
32
]));
let
written_keypair
=
KeyPairFromSeed32Generator
::
generate
(
Seed32
::
new
([
0u8
;
32
]));
let
currency
=
Currency
::
from
(
G1_TEST_CURRENCY
);
let
dewif_content
=
write_dewif_v1_content
(
&
written_keypair
,
"toto"
);
let
dewif_content
=
write_dewif_v1_content
(
currency
,
&
written_keypair
,
"toto"
);
let
mut
keypairs_iter
=
read_dewif_file_content
(
&
dewif_content
,
"toto"
)
let
mut
keypairs_iter
=
.expect
(
"dewif content must be readed successfully"
);
read_dewif_file_content
(
ExpectedCurrency
::
Specific
(
currency
),
&
dewif_content
,
"toto"
)
.expect
(
"dewif content must be readed successfully"
);
let
keypair_read
=
keypairs_iter
.next
()
.expect
(
"Must read one keypair"
);
let
keypair_read
=
keypairs_iter
.next
()
.expect
(
"Must read one keypair"
);
assert_eq!
(
KeyPairEnum
::
Ed25519
(
written_keypair
),
keypair_read
,)
assert_eq!
(
KeyPairEnum
::
Ed25519
(
written_keypair
),
keypair_read
,)
...
@@ -146,15 +156,16 @@ mod tests {
...
@@ -146,15 +156,16 @@ mod tests {
#[test]
#[test]
fn
dewif_v1_corrupted
()
->
Result
<
(),
()
>
{
fn
dewif_v1_corrupted
()
->
Result
<
(),
()
>
{
let
written_keypair
=
KeyPairFromSeed32Generator
::
generate
(
Seed32
::
new
([
0u8
;
32
]));
let
written_keypair
=
KeyPairFromSeed32Generator
::
generate
(
Seed32
::
new
([
0u8
;
32
]));
let
currency
=
Currency
::
from
(
G1_TEST_CURRENCY
);
let
mut
dewif_content
=
write_dewif_v1_content
(
&
written_keypair
,
"toto"
);
let
mut
dewif_content
=
write_dewif_v1_content
(
currency
,
&
written_keypair
,
"toto"
);
// Corrupt one byte in dewif_content
// Corrupt one byte in dewif_content
let
dewif_bytes_mut
=
unsafe
{
dewif_content
.as_bytes_mut
()
};
let
dewif_bytes_mut
=
unsafe
{
dewif_content
.as_bytes_mut
()
};
dewif_bytes_mut
[
13
]
=
0x52
;
dewif_bytes_mut
[
13
]
=
0x52
;
if
let
Err
(
DewifReadError
::
CorruptedContent
)
=
if
let
Err
(
DewifReadError
::
CorruptedContent
)
=
read_dewif_file_content
(
&
dewif_content
,
"toto"
)
read_dewif_file_content
(
ExpectedCurrency
::
Specific
(
currency
),
&
dewif_content
,
"toto"
)
{
{
Ok
(())
Ok
(())
}
else
{
}
else
{
...
@@ -166,11 +177,14 @@ mod tests {
...
@@ -166,11 +177,14 @@ mod tests {
fn
dewif_v2
()
{
fn
dewif_v2
()
{
let
written_keypair1
=
KeyPairFromSeed32Generator
::
generate
(
Seed32
::
new
([
0u8
;
32
]));
let
written_keypair1
=
KeyPairFromSeed32Generator
::
generate
(
Seed32
::
new
([
0u8
;
32
]));
let
written_keypair2
=
KeyPairFromSeed32Generator
::
generate
(
Seed32
::
new
([
1u8
;
32
]));
let
written_keypair2
=
KeyPairFromSeed32Generator
::
generate
(
Seed32
::
new
([
1u8
;
32
]));
let
currency
=
Currency
::
from
(
G1_TEST_CURRENCY
);
let
dewif_content
=
write_dewif_v2_content
(
&
written_keypair1
,
&
written_keypair2
,
"toto"
);
let
dewif_content
=
write_dewif_v2_content
(
currency
,
&
written_keypair1
,
&
written_keypair2
,
"toto"
);
let
mut
keypairs_iter
=
read_dewif_file_content
(
&
dewif_content
,
"toto"
)
let
mut
keypairs_iter
=
.expect
(
"dewif content must be readed successfully"
);
read_dewif_file_content
(
ExpectedCurrency
::
Specific
(
currency
),
&
dewif_content
,
"toto"
)
.expect
(
"dewif content must be readed successfully"
);
let
keypair1_read
=
keypairs_iter
.next
()
.expect
(
"Must read one keypair"
);
let
keypair1_read
=
keypairs_iter
.next
()
.expect
(
"Must read one keypair"
);
let
keypair2_read
=
keypairs_iter
.next
()
.expect
(
"Must read one keypair"
);
let
keypair2_read
=
keypairs_iter
.next
()
.expect
(
"Must read one keypair"
);
...
@@ -182,16 +196,17 @@ mod tests {
...
@@ -182,16 +196,17 @@ mod tests {
fn
dewif_v2_corrupted
()
->
Result
<
(),
()
>
{
fn
dewif_v2_corrupted
()
->
Result
<
(),
()
>
{
let
written_keypair1
=
KeyPairFromSeed32Generator
::
generate
(
Seed32
::
new
([
0u8
;
32
]));
let
written_keypair1
=
KeyPairFromSeed32Generator
::
generate
(
Seed32
::
new
([
0u8
;
32
]));
let
written_keypair2
=
KeyPairFromSeed32Generator
::
generate
(
Seed32
::
new
([
1u8
;
32
]));
let
written_keypair2
=
KeyPairFromSeed32Generator
::
generate
(
Seed32
::
new
([
1u8
;
32
]));
let
currency
=
Currency
::
from
(
G1_TEST_CURRENCY
);
let
mut
dewif_content
=
let
mut
dewif_content
=
write_dewif_v2_content
(
&
written_keypair1
,
&
written_keypair2
,
"toto"
);
write_dewif_v2_content
(
currency
,
&
written_keypair1
,
&
written_keypair2
,
"toto"
);
// Corrupt one byte in dewif_content
// Corrupt one byte in dewif_content
let
dewif_bytes_mut
=
unsafe
{
dewif_content
.as_bytes_mut
()
};
let
dewif_bytes_mut
=
unsafe
{
dewif_content
.as_bytes_mut
()
};
dewif_bytes_mut
[
13
]
=
0x52
;
dewif_bytes_mut
[
13
]
=
0x52
;
if
let
Err
(
DewifReadError
::
CorruptedContent
)
=
if
let
Err
(
DewifReadError
::
CorruptedContent
)
=
read_dewif_file_content
(
&
dewif_content
,
"toto"
)
read_dewif_file_content
(
ExpectedCurrency
::
Specific
(
currency
),
&
dewif_content
,
"toto"
)
{
{
Ok
(())
Ok
(())
}
else
{
}
else
{
...
...
This diff is collapsed.
Click to expand it.
src/dewif/currency.rs
0 → 100644
+
155
−
0
View file @
d260efcf
// Copyright (C) 2020 Éloïs SANCHEZ.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! Define DEWIF currency field
use
std
::
fmt
::
Display
;
use
std
::
num
::
NonZeroU32
;
use
std
::
str
::
FromStr
;
/// Ğ1 currency
pub
const
G1_CURRENCY
:
u32
=
1
;
const
G1_CURRENCY_STR
:
&
str
=
"g1"
;
/// Ğ1-Test currency
pub
const
G1_TEST_CURRENCY
:
u32
=
268_435_457
;
const
G1_TEST_CURRENCY_STR
:
&
str
=
"g1-test"
;
#[derive(Copy,
Clone,
Debug,
PartialEq)]
/// Expected DEWIF currency
pub
enum
ExpectedCurrency
{
/// Expected any currency (no limitation)
Any
,
/// Expected specific currency
Specific
(
Currency
),
}
impl
ExpectedCurrency
{
pub
(
crate
)
fn
is_valid
(
self
,
currency
:
Currency
)
->
bool
{
match
self
{
Self
::
Any
=>
true
,
Self
::
Specific
(
expected_currency
)
=>
expected_currency
==
currency
,
}
}
}
impl
Display
for
ExpectedCurrency
{
fn
fmt
(
&
self
,
f
:
&
mut
std
::
fmt
::
Formatter
)
->
Result
<
(),
std
::
fmt
::
Error
>
{
match
self
{
Self
::
Any
=>
write!
(
f
,
"Any"
),
Self
::
Specific
(
expected_currency
)
=>
expected_currency
.fmt
(
f
),
}
}
}
/// DEWIF currency
#[derive(Copy,
Clone,
Debug,
PartialEq)]
pub
struct
Currency
(
Option
<
NonZeroU32
>
);
impl
Currency
{
/// None currency
pub
fn
none
()
->
Self
{
Currency
(
None
)
}
}
impl
Display
for
Currency
{
fn
fmt
(
&
self
,
f
:
&
mut
std
::
fmt
::
Formatter
)
->
Result
<
(),
std
::
fmt
::
Error
>
{
if
let
Some
(
currency_code
)
=
self
.0
{
match
currency_code
.get
()
{
G1_CURRENCY
=>
write!
(
f
,
"{}"
,
G1_CURRENCY_STR
),
G1_TEST_CURRENCY
=>
write!
(
f
,
"{}"
,
G1_TEST_CURRENCY_STR
),
other
=>
write!
(
f
,
"{}"
,
other
),
}
}
else
{
write!
(
f
,
"None"
)
}
}
}
impl
From
<
u32
>
for
Currency
{
fn
from
(
source
:
u32
)
->
Self
{
Self
(
NonZeroU32
::
new
(
source
))
}
}
impl
Into
<
u32
>
for
Currency
{
fn
into
(
self
)
->
u32
{
if
let
Some
(
currency_code
)
=
self
.0
{
currency_code
.get
()
}
else
{
0u32
}
}
}
/// Unknown currency name
#[derive(Copy,
Clone,
Debug,
PartialEq)]
pub
struct
UnknownCurrencyName
;
impl
FromStr
for
Currency
{
type
Err
=
UnknownCurrencyName
;
fn
from_str
(
source
:
&
str
)
->
Result
<
Self
,
Self
::
Err
>
{
match
source
{
""
=>
Ok
(
Currency
(
None
)),
G1_CURRENCY_STR
=>
Ok
(
Currency
(
NonZeroU32
::
new
(
G1_CURRENCY
))),
G1_TEST_CURRENCY_STR
=>
Ok
(
Currency
(
NonZeroU32
::
new
(
G1_TEST_CURRENCY
))),
_
=>
Err
(
UnknownCurrencyName
),
}
}
}
#[cfg(test)]
mod
tests
{
use
super
::
*
;
#[test]
fn
display_expected_currency
()
{
assert_eq!
(
"None"
,
&
format!
(
"{}"
,
ExpectedCurrency
::
Specific
(
Currency
::
from
(
0
))),
);
assert_eq!
(
"Any"
,
&
format!
(
"{}"
,
ExpectedCurrency
::
Any
));
}
#[test]
fn
display_currency
()
{
assert_eq!
(
G1_CURRENCY_STR
,
&
format!
(
"{}"
,
Currency
::
from
(
G1_CURRENCY
)),);
assert_eq!
(
G1_TEST_CURRENCY_STR
,
&
format!
(
"{}"
,
Currency
::
from
(
G1_TEST_CURRENCY
)),
);
assert_eq!
(
"42"
,
&
format!
(
"{}"
,
Currency
::
from
(
42
)),);
assert_eq!
(
"None"
,
&
format!
(
"{}"
,
Currency
::
from
(
0
)),);
}
#[test]
fn
currency_from_str
()
{
assert_eq!
(
Currency
::
from
(
G1_CURRENCY
),
Currency
::
from_str
(
G1_CURRENCY_STR
)
.expect
(
"unknown currency"
),
);
assert_eq!
(
Currency
::
from
(
G1_TEST_CURRENCY
),
Currency
::
from_str
(
G1_TEST_CURRENCY_STR
)
.expect
(
"unknown currency"
),
);
assert_eq!
(
Err
(
UnknownCurrencyName
),
Currency
::
from_str
(
"unknown currency"
),
);
}
}
This diff is collapsed.
Click to expand it.
src/dewif/read.rs
+
56
−
15
View file @
d260efcf
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
//! Read [DEWIF](https://git.duniter.org/nodes/common/doc/blob/dewif/rfc/0013_Duniter_Encrypted_Wallet_Import_Format.md) file content
//! Read [DEWIF](https://git.duniter.org/nodes/common/doc/blob/dewif/rfc/0013_Duniter_Encrypted_Wallet_Import_Format.md) file content
use
super
::{
Currency
,
ExpectedCurrency
};
use
crate
::
keys
::
ed25519
::{
KeyPairFromSeed32Generator
,
PublicKey
,
PUBKEY_SIZE_IN_BYTES
};
use
crate
::
keys
::
ed25519
::{
KeyPairFromSeed32Generator
,
PublicKey
,
PUBKEY_SIZE_IN_BYTES
};
use
crate
::
keys
::
KeyPairEnum
;
use
crate
::
keys
::
KeyPairEnum
;
use
crate
::
seeds
::
Seed32
;
use
crate
::
seeds
::
Seed32
;
...
@@ -32,22 +33,30 @@ type KeyPairsIter = arrayvec::IntoIter<[KeyPairEnum; MAX_KEYPAIRS_COUNT]>;
...
@@ -32,22 +33,30 @@ type KeyPairsIter = arrayvec::IntoIter<[KeyPairEnum; MAX_KEYPAIRS_COUNT]>;
#[derive(Clone,
Debug,
Error)]
#[derive(Clone,
Debug,
Error)]
pub
enum
DewifReadError
{
pub
enum
DewifReadError
{
/// DEWIF file content is corrupted
/// DEWIF file content is corrupted
#[error(
"DEWIF file content is corrupted"
)]
#[error(
"DEWIF file content is corrupted
.
"
)]
CorruptedContent
,
CorruptedContent
,
/// Invalid base 64 string
/// Invalid base 64 string
#[error(
"Invalid base 64 string: {0}"
)]
#[error(
"Invalid base 64 string: {0}
.
"
)]
InvalidBase64Str
(
base64
::
DecodeError
),
InvalidBase64Str
(
base64
::
DecodeError
),
/// Invalid format
/// Invalid format
#[error(
"Invalid format"
)]
#[error(
"Invalid format
.
"
)]
InvalidFormat
,
InvalidFormat
,
/// Too short content
/// Too short content
#[error(
"Too short content"
)]
#[error(
"Too short content
.
"
)]
TooShortContent
,
TooShortContent
,
/// Too long content
/// Too long content
#[error(
"Too long content"
)]
#[error(
"Too long content
.
"
)]
TooLongContent
,
TooLongContent
,
/// Unexpected currency
#[error(
"Unexpected currency '{actual}', expected: '{expected}'."
)]
UnexpectedCurrency
{
/// Expected currency
expected
:
ExpectedCurrency
,
/// Actual currency
actual
:
Currency
,
},
/// Unsupported version
/// Unsupported version
#[error(
"Version {actual
:?
} is not supported. Supported versions: [1, 2]."
)]
#[error(
"Version {actual} is not supported. Supported versions: [1, 2]."
)]
UnsupportedVersion
{
UnsupportedVersion
{
/// Actual version
/// Actual version
actual
:
u32
,
actual
:
u32
,
...
@@ -56,24 +65,33 @@ pub enum DewifReadError {
...
@@ -56,24 +65,33 @@ pub enum DewifReadError {
/// read dewif file content with user passphrase
/// read dewif file content with user passphrase
pub
fn
read_dewif_file_content
(
pub
fn
read_dewif_file_content
(
expected_currency
:
ExpectedCurrency
,
file_content
:
&
str
,
file_content
:
&
str
,
passphrase
:
&
str
,
passphrase
:
&
str
,
)
->
Result
<
impl
Iterator
<
Item
=
KeyPairEnum
>
,
DewifReadError
>
{
)
->
Result
<
impl
Iterator
<
Item
=
KeyPairEnum
>
,
DewifReadError
>
{
let
mut
bytes
=
base64
::
decode
(
file_content
)
.map_err
(
DewifReadError
::
InvalidBase64Str
)
?
;
let
mut
bytes
=
base64
::
decode
(
file_content
)
.map_err
(
DewifReadError
::
InvalidBase64Str
)
?
;
if
bytes
.len
()
<
4
{
if
bytes
.len
()
<
8
{
return
Err
(
DewifReadError
::
TooShortContent
);
return
Err
(
DewifReadError
::
TooShortContent
);
}
}
let
version
=
byteorder
::
BigEndian
::
read_u32
(
&
bytes
[
0
..
4
]);
let
version
=
byteorder
::
BigEndian
::
read_u32
(
&
bytes
[
0
..
4
]);
let
currency
=
Currency
::
from
(
byteorder
::
BigEndian
::
read_u32
(
&
bytes
[
4
..
8
]));
if
!
expected_currency
.is_valid
(
currency
)
{
return
Err
(
DewifReadError
::
UnexpectedCurrency
{
expected
:
expected_currency
,
actual
:
currency
,
});
}
match
version
{
match
version
{
1
=>
Ok
({
1
=>
Ok
({
let
mut
array_keypairs
=
KeyPairsArray
::
new
();
let
mut
array_keypairs
=
KeyPairsArray
::
new
();
array_keypairs
.push
(
read_dewif_v1
(
&
mut
bytes
[
4
..
],
passphrase
)
?
);
array_keypairs
.push
(
read_dewif_v1
(
&
mut
bytes
[
8
..
],
passphrase
)
?
);
array_keypairs
.into_iter
()
array_keypairs
.into_iter
()
}),
}),
2
=>
read_dewif_v2
(
&
mut
bytes
[
4
..
],
passphrase
),
2
=>
read_dewif_v2
(
&
mut
bytes
[
8
..
],
passphrase
),
other_version
=>
Err
(
DewifReadError
::
UnsupportedVersion
{
other_version
=>
Err
(
DewifReadError
::
UnsupportedVersion
{
actual
:
other_version
,
actual
:
other_version
,
}),
}),
...
@@ -142,7 +160,8 @@ mod tests {
...
@@ -142,7 +160,8 @@ mod tests {
#[test]
#[test]
fn
read_unsupported_version
()
->
Result
<
(),
()
>
{
fn
read_unsupported_version
()
->
Result
<
(),
()
>
{
if
let
Err
(
DewifReadError
::
UnsupportedVersion
{
..
})
=
read_dewif_file_content
(
if
let
Err
(
DewifReadError
::
UnsupportedVersion
{
..
})
=
read_dewif_file_content
(
"ABAAAfKjMzOFfhwgypF3mAx0QDXyozMzhX4cIMqRd5gMdEA1WZwQjCR49iZDK2QhYfdTbPz9AGB01edt4iRSzdTp3c4="
,
ExpectedCurrency
::
Any
,
"ABAAAb30ng3kI9QGMbR7TYCqPhS99J4N5CPUBjG0e02Aqj4U1UmOemI6pweNm1Ab1AR4V6ZWFnwkkp9QPxppVeMv7aaLWdop"
,
"toto"
"toto"
)
{
)
{
Ok
(())
Ok
(())
...
@@ -153,7 +172,9 @@ mod tests {
...
@@ -153,7 +172,9 @@ mod tests {
#[test]
#[test]
fn
read_too_short_content
()
->
Result
<
(),
()
>
{
fn
read_too_short_content
()
->
Result
<
(),
()
>
{
if
let
Err
(
DewifReadError
::
TooShortContent
)
=
read_dewif_file_content
(
"AAA"
,
"toto"
)
{
if
let
Err
(
DewifReadError
::
TooShortContent
)
=
read_dewif_file_content
(
ExpectedCurrency
::
Any
,
"AAA"
,
"toto"
)
{
Ok
(())
Ok
(())
}
else
{
}
else
{
panic!
(
"Read must be fail with error TooShortContent."
)
panic!
(
"Read must be fail with error TooShortContent."
)
...
@@ -161,19 +182,39 @@ mod tests {
...
@@ -161,19 +182,39 @@ mod tests {
}
}
#[test]
#[test]
fn
tmp
()
{
fn
read_unexpected_currency
()
->
Result
<
(),
()
>
{
if
let
Err
(
DewifReadError
::
UnexpectedCurrency
{
..
})
=
read_dewif_file_content
(
ExpectedCurrency
::
Specific
(
Currency
::
from
(
42
)),
"AAAAARAAAAEx3yd707xD3F5ttjcISbZzXRrko4pKUmCDIF/emfcVU9MvBqCJQS9R2sWlqbtI1Q37sLQhkj/W7tqY+hxm7mFQ"
,
"toto titi tata"
)
{
Ok
(())
}
else
{
panic!
(
"Read must be fail with error UnexpectedCurrency."
)
}
}
#[test]
fn
read_ok
()
{
use
crate
::
dewif
::
Currency
;
use
crate
::
keys
::{
KeyPair
,
Signator
};
use
crate
::
keys
::{
KeyPair
,
Signator
};
use
std
::
str
::
FromStr
;
// Get DEWIF file content (Usually from disk)
// Get DEWIF file content (Usually from disk)
let
dewif_file_content
=
"AAAAA
THfJ3vTvEPcXm22NwhJtnNdGuSjikpSYIMgX96Z9xVT0y8GoIlBL1HaxaWpu0jVDfuwtCGSP9bu2pj6HGbuYVA=
"
;
let
dewif_file_content
=
"AAAAA
RAAAAEx3yd707xD3F5ttjcISbZzXRrko4pKUmCDIF/emfcVU9MvBqCJQS9R2sWlqbtI1Q37sLQhkj/W7tqY+hxm7mFQ
"
;
// Get user passphrase for DEWIF decryption (from cli prompt or gui)
// Get user passphrase for DEWIF decryption (from cli prompt or gui)
let
encryption_passphrase
=
"toto titi tata"
;
let
encryption_passphrase
=
"toto titi tata"
;
// Expected currency
let
expected_currency
=
ExpectedCurrency
::
Specific
(
Currency
::
from_str
(
"g1-test"
)
.expect
(
"unknown currency"
));
// Read DEWIF file content
// Read DEWIF file content
// If the file content is correct, we get a key-pair iterator.
// If the file content is correct, we get a key-pair iterator.
let
mut
key_pair_iter
=
read_dewif_file_content
(
dewif_file_content
,
encryption_passphrase
)
let
mut
key_pair_iter
=
.expect
(
"invalid DEWIF file."
);
read_dewif_file_content
(
expected_currency
,
dewif_file_content
,
encryption_passphrase
)
.expect
(
"invalid DEWIF file"
);
// Get first key-pair
// Get first key-pair
let
key_pair
=
key_pair_iter
let
key_pair
=
key_pair_iter
...
...
This diff is collapsed.
Click to expand it.
src/dewif/write.rs
+
48
−
5
View file @
d260efcf
...
@@ -15,38 +15,52 @@
...
@@ -15,38 +15,52 @@
//! Write [DEWIF](https://git.duniter.org/nodes/common/doc/blob/dewif/rfc/0013_Duniter_Encrypted_Wallet_Import_Format.md) file content
//! Write [DEWIF](https://git.duniter.org/nodes/common/doc/blob/dewif/rfc/0013_Duniter_Encrypted_Wallet_Import_Format.md) file content
use
super
::
Currency
;
use
crate
::
keys
::
ed25519
::
Ed25519KeyPair
;
use
crate
::
keys
::
ed25519
::
Ed25519KeyPair
;
use
arrayvec
::
ArrayVec
;
use
arrayvec
::
ArrayVec
;
use
unwrap
::
unwrap
;
use
unwrap
::
unwrap
;
/// Write dewif v1 file content with user passphrase
/// Write dewif v1 file content with user passphrase
pub
fn
write_dewif_v1_content
(
keypair
:
&
Ed25519KeyPair
,
passphrase
:
&
str
)
->
String
{
pub
fn
write_dewif_v1_content
(
currency
:
Currency
,
keypair
:
&
Ed25519KeyPair
,
passphrase
:
&
str
,
)
->
String
{
let
mut
bytes
=
ArrayVec
::
<
[
u8
;
super
::
V1_BYTES_LEN
]
>
::
new
();
let
mut
bytes
=
ArrayVec
::
<
[
u8
;
super
::
V1_BYTES_LEN
]
>
::
new
();
unwrap!
(
bytes
.try_extend_from_slice
(
super
::
VERSION_V1
));
unwrap!
(
bytes
.try_extend_from_slice
(
super
::
VERSION_V1
));
let
currency_code
:
u32
=
currency
.into
();
unwrap!
(
bytes
.try_extend_from_slice
(
&
currency_code
.to_be_bytes
()));
unwrap!
(
bytes
.try_extend_from_slice
(
keypair
.seed
()
.as_ref
()));
unwrap!
(
bytes
.try_extend_from_slice
(
keypair
.seed
()
.as_ref
()));
unwrap!
(
bytes
.try_extend_from_slice
(
keypair
.pubkey
()
.as_ref
()));
unwrap!
(
bytes
.try_extend_from_slice
(
keypair
.pubkey
()
.as_ref
()));
let
cipher
=
crate
::
aes256
::
new_cipher
(
super
::
gen_aes_seed
(
passphrase
));
let
cipher
=
crate
::
aes256
::
new_cipher
(
super
::
gen_aes_seed
(
passphrase
));
crate
::
aes256
::
encrypt
::
encrypt_n_blocks
(
&
cipher
,
&
mut
bytes
[
4
..
],
super
::
V1_AES_BLOCKS_COUNT
);
crate
::
aes256
::
encrypt
::
encrypt_n_blocks
(
&
cipher
,
&
mut
bytes
[
super
::
UNENCRYPTED_BYTES_LEN
..
],
super
::
V1_AES_BLOCKS_COUNT
,
);
base64
::
encode
(
bytes
.as_ref
())
base64
::
encode
(
bytes
.as_ref
())
}
}
/// Write dewif v2 file content with user passphrase
/// Write dewif v2 file content with user passphrase
pub
fn
write_dewif_v2_content
(
pub
fn
write_dewif_v2_content
(
currency
:
Currency
,
keypair1
:
&
Ed25519KeyPair
,
keypair1
:
&
Ed25519KeyPair
,
keypair2
:
&
Ed25519KeyPair
,
keypair2
:
&
Ed25519KeyPair
,
passphrase
:
&
str
,
passphrase
:
&
str
,
)
->
String
{
)
->
String
{
let
mut
bytes
=
ArrayVec
::
<
[
u8
;
super
::
V2_BYTES_LEN
]
>
::
new
();
let
mut
bytes
=
ArrayVec
::
<
[
u8
;
super
::
V2_BYTES_LEN
]
>
::
new
();
unwrap!
(
bytes
.try_extend_from_slice
(
super
::
VERSION_V2
));
unwrap!
(
bytes
.try_extend_from_slice
(
super
::
VERSION_V2
));
let
currency_code
:
u32
=
currency
.into
();
unwrap!
(
bytes
.try_extend_from_slice
(
&
currency_code
.to_be_bytes
()));
unwrap!
(
bytes
.try_extend_from_slice
(
keypair1
.seed
()
.as_ref
()));
unwrap!
(
bytes
.try_extend_from_slice
(
keypair1
.seed
()
.as_ref
()));
unwrap!
(
bytes
.try_extend_from_slice
(
keypair1
.pubkey
()
.as_ref
()));
unwrap!
(
bytes
.try_extend_from_slice
(
keypair1
.pubkey
()
.as_ref
()));
unwrap!
(
bytes
.try_extend_from_slice
(
keypair2
.seed
()
.as_ref
()));
unwrap!
(
bytes
.try_extend_from_slice
(
keypair2
.seed
()
.as_ref
()));
unwrap!
(
bytes
.try_extend_from_slice
(
keypair2
.pubkey
()
.as_ref
()));
unwrap!
(
bytes
.try_extend_from_slice
(
keypair2
.pubkey
()
.as_ref
()));
let
cipher
=
crate
::
aes256
::
new_cipher
(
super
::
gen_aes_seed
(
passphrase
));
let
cipher
=
crate
::
aes256
::
new_cipher
(
super
::
gen_aes_seed
(
passphrase
));
crate
::
aes256
::
encrypt
::
encrypt_8_blocks
(
&
cipher
,
&
mut
bytes
[
super
::
VERSION
_BYTES
..
]);
crate
::
aes256
::
encrypt
::
encrypt_8_blocks
(
&
cipher
,
&
mut
bytes
[
super
::
UNENCRYPTED
_BYTES
_LEN
..
]);
base64
::
encode
(
bytes
.as_ref
())
base64
::
encode
(
bytes
.as_ref
())
}
}
...
@@ -57,15 +71,44 @@ mod tests {
...
@@ -57,15 +71,44 @@ mod tests {
use
super
::
*
;
use
super
::
*
;
use
crate
::
keys
::
ed25519
::
KeyPairFromSeed32Generator
;
use
crate
::
keys
::
ed25519
::
KeyPairFromSeed32Generator
;
use
crate
::
seeds
::
Seed32
;
use
crate
::
seeds
::
Seed32
;
use
std
::
str
::
FromStr
;
#[test]
#[test]
fn
write_dewif_v1
()
{
fn
write_dewif_v1
()
{
let
keypair
=
KeyPairFromSeed32Generator
::
generate
(
Seed32
::
new
([
0u8
;
32
]));
let
keypair
=
KeyPairFromSeed32Generator
::
generate
(
Seed32
::
new
([
0u8
;
32
]));
let
dewif_content
=
write_dewif_v1_content
(
&
keypair
,
"toto"
);
let
dewif_content
=
write_dewif_v1_content
(
Currency
::
none
(),
&
keypair
,
"toto"
);
println!
(
"{}"
,
dewif_content
);
println!
(
"{}"
,
dewif_content
);
assert_eq!
(
assert_eq!
(
"AAAAAb30ng3kI9QGMbR7TYCqPhS99J4N5CPUBjG0e02Aqj4UElionaHOt0kv+eaWgGSGkrP1LQfuwivuvg7+9n0gd18="
,
"AAAAAQAAAAC99J4N5CPUBjG0e02Aqj4UvfSeDeQj1AYxtHtNgKo+FBJYqJ2hzrdJL/nmloBkhpKz9S0H7sIr7r4O/vZ9IHdf"
,
dewif_content
)
}
#[test]
fn
write_ok
()
{
use
crate
::
dewif
::
write_dewif_v1_content
;
use
crate
::
keys
::
ed25519
::{
KeyPairFromSaltedPasswordGenerator
,
SaltedPassword
};
// Get user credentials (from cli prompt or gui)
let
credentials
=
SaltedPassword
::
new
(
"user salt"
.to_owned
(),
"user password"
.to_owned
());
// Generate ed25519 keypair
let
keypair
=
KeyPairFromSaltedPasswordGenerator
::
with_default_parameters
()
.generate
(
credentials
);
// Get user passphrase for DEWIF encryption
let
encryption_passphrase
=
"toto titi tata"
;
// Expected currency
let
expected_currency
=
Currency
::
from_str
(
"g1-test"
)
.expect
(
"unknown currency"
);
// Serialize keypair in DEWIF format
let
dewif_content
=
write_dewif_v1_content
(
expected_currency
,
&
keypair
,
encryption_passphrase
);
assert_eq!
(
"AAAAARAAAAEx3yd707xD3F5ttjcISbZzXRrko4pKUmCDIF/emfcVU9MvBqCJQS9R2sWlqbtI1Q37sLQhkj/W7tqY+hxm7mFQ"
,
dewif_content
dewif_content
)
)
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment