Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
DuniterPy
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
31
Issues
31
List
Boards
Labels
Service Desk
Milestones
Merge Requests
4
Merge Requests
4
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Package Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
clients
python
DuniterPy
Commits
821a3b9f
Commit
821a3b9f
authored
Feb 17, 2019
by
Vincent Texier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[enh]
#78
Add Ascii Armor encrypted and signed message creation and example
parent
d790538f
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
161 additions
and
2 deletions
+161
-2
duniterpy/key/__init__.py
duniterpy/key/__init__.py
+3
-2
duniterpy/key/ascii_armor.py
duniterpy/key/ascii_armor.py
+123
-0
examples/save_ascii_armor_encrypted_message.py
examples/save_ascii_armor_encrypted_message.py
+35
-0
No files found.
duniterpy/key/__init__.py
View file @
821a3b9f
from
.signing_key
import
SigningKey
,
ScryptParams
from
.signing_key
import
SigningKey
from
.verifying_key
import
VerifyingKey
from
.verifying_key
import
VerifyingKey
from
.encryption_key
import
SecretKey
,
PublicKey
from
.encryption_key
import
SecretKey
,
PublicKey
,
SCRYPT_PARAMS
,
SEED_LENGTH
from
.ascii_armor
import
AsciiArmor
duniterpy/key/ascii_armor.py
0 → 100644
View file @
821a3b9f
import
base64
import
libnacl
from
typing
import
Optional
,
List
from
duniterpy.key
import
SigningKey
,
PublicKey
,
SCRYPT_PARAMS
,
SEED_LENGTH
# Headers constants
BEGIN_MESSAGE_HEADER
=
"-----BEGIN DUNITER MESSAGE-----"
END_MESSAGE_HEADER
=
"-----END DUNITER MESSAGE-----"
BEGIN_SIGNATURE_HEADER
=
"-----BEGIN DUNITER SIGNATURE-----"
END_SIGNATURE_HEADER
=
"-----END DUNITER SIGNATURE-----"
# Version field values
AA_MESSAGE_VERSION
=
"Python Libnacl "
+
libnacl
.
__version__
AA_SIGNATURE_VERSION
=
"Python Libnacl "
+
libnacl
.
__version__
class
AsciiArmor
:
"""
Class to handle writing and reading of ascii armor messages
"""
@
staticmethod
def
encrypt
(
message
:
str
,
pubkey
:
str
,
signing_keys
:
Optional
[
List
[
SigningKey
]]
=
None
,
message_comment
:
Optional
[
str
]
=
None
,
signatures_comment
:
Optional
[
str
]
=
None
)
->
str
:
"""
Encrypt a message in ascii armor format, optionally signing it
:param message: Utf-8 message
:param pubkey: Public key of recipient for encryption
:param signing_keys: Optional list of SigningKey instances
:param message_comment: Optional message comment field
:param signatures_comment: Optional signatures comment field
:return:
"""
pubkey_instance
=
PublicKey
(
pubkey
)
base64_encrypted_message
=
base64
.
b64encode
(
pubkey_instance
.
encrypt_seal
(
message
))
# type: bytes
script_field
=
AsciiArmor
.
_get_scrypt_field
()
# create block with headers
ascii_armor_msg
=
"""
{begin_message_header}
Version: {version}
{script_field}
"""
.
format
(
begin_message_header
=
BEGIN_MESSAGE_HEADER
,
version
=
AA_MESSAGE_VERSION
,
script_field
=
script_field
)
# add message comment if specified
if
message_comment
:
ascii_armor_msg
+=
AsciiArmor
.
_get_comment_field
(
message_comment
)
# add encrypted message
ascii_armor_msg
+=
"""
{base64_encrypted_message}
"""
.
format
(
base64_encrypted_message
=
base64_encrypted_message
.
decode
(
'utf-8'
))
# if no signature...
if
signing_keys
is
None
:
# add message tail
ascii_armor_msg
+=
END_MESSAGE_HEADER
else
:
# add signature blocks and close block on last signature
count
=
1
for
signing_key
in
signing_keys
:
ascii_armor_msg
+=
AsciiArmor
.
_get_signature_block
(
message
,
signing_key
,
count
==
len
(
signing_keys
),
signatures_comment
)
count
+=
1
return
ascii_armor_msg
@
staticmethod
def
_get_scrypt_field
():
"""
Return the Scrypt field
:return:
"""
return
"Scrypt: N={0};r={1};p={2};len={3}"
.
format
(
SCRYPT_PARAMS
[
'N'
],
SCRYPT_PARAMS
[
'r'
],
SCRYPT_PARAMS
[
'p'
],
SEED_LENGTH
)
@
staticmethod
def
_get_comment_field
(
comment
:
str
)
->
str
:
"""
Return a comment field
:param comment: Comment text
:return:
"""
return
"Comment: {comment}
\n
"
.
format
(
comment
=
comment
)
@
staticmethod
def
_get_signature_block
(
message
:
str
,
signing_key
:
SigningKey
,
close_block
:
bool
=
True
,
comment
:
Optional
[
str
]
=
None
)
->
str
:
"""
Return a signature block
:param message: Message (not encrypted!) to sign
:param signing_key: The libnacl SigningKey instance of the keypair
:param close_block: Optional flag to close the signature block with the signature tail header
:param comment: Optional comment field content
:return:
"""
script_param_field
=
AsciiArmor
.
_get_scrypt_field
()
base64_signature
=
base64
.
b64encode
(
signing_key
.
signature
(
message
))
block
=
"""{begin_signature_header}
Version: {version}
Scrypt: {script_params}
"""
.
format
(
begin_signature_header
=
BEGIN_SIGNATURE_HEADER
,
version
=
AA_SIGNATURE_VERSION
,
script_params
=
script_param_field
)
# add message comment if specified
if
comment
:
block
+=
AsciiArmor
.
_get_comment_field
(
comment
)
block
+=
"""
{base64_signature}
"""
.
format
(
base64_signature
=
base64_signature
.
decode
(
'utf-8'
))
if
close_block
:
block
+=
END_SIGNATURE_HEADER
return
block
examples/save_ascii_armor_encrypted_message.py
0 → 100644
View file @
821a3b9f
import
getpass
from
duniterpy
import
__version__
from
duniterpy.key
import
AsciiArmor
,
SigningKey
################################################
AA_ENCRYPTED_MESSAGE_FILENAME
=
'duniter_aa_encrypted_message.txt'
if
__name__
==
'__main__'
:
# Ask public key of the recipient
pubkeyBase58
=
input
(
"Enter public key of the message recipient: "
)
# prompt hidden user entry
salt
=
getpass
.
getpass
(
"Enter your passphrase (salt): "
)
# prompt hidden user entry
password
=
getpass
.
getpass
(
"Enter your password: "
)
# init SigningKey instance
signing_key
=
SigningKey
.
from_credentials
(
salt
,
password
)
# Enter the message
message
=
input
(
"Enter your message: "
)
comment
=
"generated by Duniterpy {0}"
.
format
(
__version__
)
# Encrypt the message, only the recipient secret key will be able to decrypt the message
encrypted_message
=
AsciiArmor
.
encrypt
(
message
,
pubkeyBase58
,
[
signing_key
],
message_comment
=
comment
,
signatures_comment
=
comment
)
# Save encrypted message in a file
with
open
(
AA_ENCRYPTED_MESSAGE_FILENAME
,
'w'
)
as
file_handler
:
file_handler
.
write
(
encrypted_message
)
print
(
"Ascii Armor Encrypted message saved in file ./{0}"
.
format
(
AA_ENCRYPTED_MESSAGE_FILENAME
))
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment