Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
DuniterPy
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
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
Show more breadcrumbs
clients
python
DuniterPy
Commits
e92a661d
Commit
e92a661d
authored
4 years ago
by
Vincent Texier
Browse files
Options
Downloads
Patches
Plain Diff
[feat]
#151
Add DEWIF file format support for wallets
See RFC0013 of the Duniter Project
parent
e74fb6c2
No related branches found
No related tags found
No related merge requests found
Pipeline
#11335
passed
4 years ago
Stage: checks
Stage: tests
Changes
2
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
duniterpy/key/signing_key.py
+72
-0
72 additions, 0 deletions
duniterpy/key/signing_key.py
tests/key/test_signing_key.py
+33
-0
33 additions, 0 deletions
tests/key/test_signing_key.py
with
105 additions
and
0 deletions
duniterpy/key/signing_key.py
+
72
−
0
View file @
e92a661d
...
@@ -553,3 +553,75 @@ Data: {data}""".format(
...
@@ -553,3 +553,75 @@ Data: {data}""".format(
dklen
=
scrypt_params
.
seed_length
,
# 32
dklen
=
scrypt_params
.
seed_length
,
# 32
)
# type: bytes
)
# type: bytes
return
cls
(
_seed
)
return
cls
(
_seed
)
@classmethod
def
from_dewif_file
(
cls
,
path
:
Union
[
str
,
PathLike
],
password
:
str
)
->
SigningKeyType
:
"""
Load a DEWIF encrypted file using the password to decrypt
Add dewif_version and dewif_currency properties to the instance
:param path: Path of the file
:param password: Password to decrypt the file
:return:
"""
scrypt_params
=
ScryptParams
()
aes_key
=
scrypt
(
password
=
password
.
encode
(
"
utf-8
"
),
salt
=
sha256
(
f
"
dewif
{
password
}
"
.
encode
(
"
utf-8
"
)).
digest
(),
n
=
scrypt_params
.
N
,
# 4096
r
=
scrypt_params
.
r
,
# 16
p
=
scrypt_params
.
p
,
# 1
dklen
=
scrypt_params
.
seed_length
,
# 32
)
aes
=
AESModeOfOperationECB
(
aes_key
)
with
open
(
path
,
"
rb
"
)
as
file_handler
:
file_handler
.
seek
(
8
)
# header = file_handler.read(8)
# version, currency = struct.unpack("ii", header)
encrypted_data
=
file_handler
.
read
()
data
=
b
""
.
join
(
map
(
aes
.
decrypt
,
chunkstring
(
encrypted_data
,
16
)))
seed
=
data
[:
32
]
public_key
=
data
[
32
:]
signing_key
=
cls
(
seed
)
assert
signing_key
.
vk
==
public_key
return
signing_key
def
save_dewif_v1_file
(
self
,
path
:
Union
[
str
,
PathLike
],
password
:
str
,
currency
:
int
=
DEWIF_CURRENCY_CODE_G1
,
)
->
None
:
"""
Save the instance seed in an encrypted DEWIF V1 file
Use the password to encrypt data
:param path: Path of the file to save
:param password: Password to encrypt data
:param currency: Currency code (default=tikka.domain.dewif.DEWIF_CURRENCY_CODE_G1)
:return:
"""
scrypt_params
=
ScryptParams
()
aes_key
=
scrypt
(
password
=
password
.
encode
(
"
utf-8
"
),
salt
=
sha256
(
f
"
dewif
{
password
}
"
.
encode
(
"
utf-8
"
)).
digest
(),
n
=
scrypt_params
.
N
,
# 4096
r
=
scrypt_params
.
r
,
# 16
p
=
scrypt_params
.
p
,
# 1
dklen
=
scrypt_params
.
seed_length
,
# 32
)
header
=
struct
.
pack
(
"
>ii
"
,
1
,
currency
)
data
=
self
.
seed
+
self
.
vk
aes
=
AESModeOfOperationECB
(
aes_key
)
encrypted_data
=
b
""
.
join
(
map
(
aes
.
encrypt
,
chunkstring
(
data
,
16
)))
with
open
(
path
,
"
wb
"
)
as
file_handler
:
file_handler
.
write
(
header
+
encrypted_data
)
This diff is collapsed.
Click to expand it.
tests/key/test_signing_key.py
+
33
−
0
View file @
e92a661d
...
@@ -16,11 +16,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
...
@@ -16,11 +16,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
"""
import
base64
import
base64
import
os
import
os
from
hashlib
import
scrypt
from
pathlib
import
Path
from
duniterpy.key
import
VerifyingKey
,
SigningKey
,
PublicKey
from
duniterpy.key
import
VerifyingKey
,
SigningKey
,
PublicKey
from
duniterpy.key.scrypt_params
import
ScryptParams
from
duniterpy.key.scrypt_params
import
ScryptParams
import
unittest
import
unittest
from
duniterpy.key.signing_key
import
DEWIF_CURRENCY_CODE_G1_TEST
TEST_FILE_PATH
=
"
/tmp/test_file.txt
"
TEST_FILE_PATH
=
"
/tmp/test_file.txt
"
...
@@ -157,3 +161,32 @@ class TestSigningKey(unittest.TestCase):
...
@@ -157,3 +161,32 @@ class TestSigningKey(unittest.TestCase):
"
qGdvpbP9lJe7ZG4ZUSyu33KFeAEs/KkshAp9gEI4ReY=
"
,
"
qGdvpbP9lJe7ZG4ZUSyu33KFeAEs/KkshAp9gEI4ReY=
"
,
)
)
self
.
assertEqual
(
keypair
.
pubkey
,
"
732SSfuwjB7jkt9th1zerGhphs6nknaCBCTozxUcPWPU
"
)
self
.
assertEqual
(
keypair
.
pubkey
,
"
732SSfuwjB7jkt9th1zerGhphs6nknaCBCTozxUcPWPU
"
)
def
test_dewif_v1_save_and_load
(
self
):
path
=
"
/tmp/test.dewif
"
password
=
"
toto titi tata
"
scrypt_params
=
ScryptParams
()
seed
=
scrypt
(
password
=
b
"
user password
"
,
salt
=
b
"
user salt
"
,
n
=
scrypt_params
.
N
,
# 4096
r
=
scrypt_params
.
r
,
# 16
p
=
scrypt_params
.
p
,
# 1
dklen
=
scrypt_params
.
seed_length
,
)
signing_key
=
SigningKey
(
seed
)
signing_key
.
save_dewif_v1_file
(
path
,
password
,
DEWIF_CURRENCY_CODE_G1_TEST
)
with
open
(
path
,
"
rb
"
)
as
file_handler
:
b64_content
=
base64
.
b64encode
(
file_handler
.
read
()).
decode
(
"
utf-8
"
)
self
.
assertEqual
(
b64_content
,
"
AAAAARAAAAGfFDAs+jVZYkfhBlHZZ2fEQIvBqnG16g5+02cY18wSOjW0cUg2JV3SUTJYN2CrbQeRDwGazWnzSFBphchMmiL0
"
,
)
signing_key_loaded
=
SigningKey
.
from_dewif_file
(
path
,
password
)
self
.
assertEqual
(
signing_key_loaded
.
seed
,
signing_key
.
seed
)
if
Path
(
path
).
exists
():
Path
(
path
).
unlink
()
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